ความแตกต่างระหว่างตัวแปรวัตถุ uninitialized และตัวแปรวัตถุเริ่มต้นเป็นโมฆะใน Java คืออะไร


12

ฉันมีตัวแปรออบเจคต์สองตัวต่อไปนี้

Date a;
Date b=null;

แน่นอนทั้ง 'a' และ 'b' ไม่ได้อ้างอิงถึงวัตถุใด ๆ

ตอนนี้ถ้าฉันเรียกใช้คำสั่งต่อไปนี้

System.out.println(a.toString());

จะมีข้อผิดพลาดเวลารวบรวมขณะที่ถ้าฉันเรียกใช้คำสั่งต่อไปนี้

System.out.println(b.toString());

จะไม่มีข้อผิดพลาดเวลารวบรวม แต่จะมีข้อผิดพลาดรันไทม์ อะไรคือสาเหตุของสิ่งนี้และค่าใดที่จะถูกเก็บไว้ใน 'b' เพื่อแทนค่า Null?


2
ถามและตอบหลายครั้งที่ SO: เหตุใดตัวแปรโลคอลจึงไม่เริ่มต้นใน Java , ตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้นและสมาชิกใน Javaและในคำถามมากมายที่เชื่อมโยงกับสิ่งเหล่านี้
ริ้น

@gnat มีคำถามอื่นใดที่จัดการกับความแตกต่างระหว่าง "uninitialized" และ "null" หรือไม่ เพียงเพราะคำตอบคล้ายกันไม่ได้หมายความว่านี่เป็นคำถามที่ซ้ำกัน
DougM

@DougM แน่นอนคุณอ่านคำถามแรกที่ฉันอ้างถึงหรือไม่ "มีเหตุผลใดที่นักออกแบบของ Java รู้สึกว่าตัวแปรท้องถิ่นไม่ควรได้รับค่าเริ่มต้นหรือไม่อย่างจริงจังหากตัวแปรอินสแตนซ์สามารถได้รับค่าเริ่มต้นแล้วทำไมเราไม่สามารถทำเช่นเดียวกันสำหรับตัวแปรท้องถิ่น" (FWIW มันไม่สามารถในทางเทคนิคเป็นที่ซ้ำกันเพียงเพราะมันเป็นที่สถานที่อื่น)
ริ้น

1
ที่ไม่ได้ระบุความแตกต่างระหว่าง "ไม่กำหนดค่าเริ่มต้น" และ "กำหนดค่าเริ่มต้นเป็นค่าว่าง" เท่านั้น "ทำไมจึงไม่มีตัวแปรเริ่มต้นให้เป็นค่าว่างโดยอัตโนมัติ" หัวข้อเดียวกันคำถามที่แตกต่างกันเล็กน้อย
DougM

คำตอบ:


3

นั่นเป็นเพราะสถานะของตัวแปรท้องถิ่นถูกควบคุมภายในขอบเขตของมัน

 // method/loop/if/try-catch etc...
 {
   Date d; // if it's not intialised in this scope then its not intialised  anywhere
 }

ซึ่งไม่ใช่กรณีสำหรับฟิลด์

class Foo{
 Date d; // it could be intialised anywhere, so its out of control and java will set to null for you
}

ทีนี้ทำไมมันถึงดีกว่าที่จะตั้งค่าตัวแปรให้เป็นโมฆะและใช้มันทันที? อาจเป็นความผิดพลาดทางประวัติศาสตร์ที่บางครั้งนำไปสู่ข้อผิดพลาดที่น่ากลัว

 {
  Date d = null;
  try{
  }catch{ // hide it here 
  }
  return d;
 } 

ตอนนี้ความแตกต่างทางความหมายคืออะไร?

Date d;

เพียงแค่ประกาศตัวแปรที่สามารถเก็บการอ้างอิงที่ชี้ไปยังวัตถุประเภทDateอย่างไรก็ตาม

Date d= null; 

ทำเหมือนกันทุกประการ แต่การอ้างอิงชี้ไปที่ null ในครั้งนี้ null เป็นเหมือนการอ้างอิงใด ๆ มันใช้พื้นที่ของตัวชี้เนทีฟนั่นคือ 4 ไบต์บนเครื่อง 32- บิตและ 8 ไบต์บนเครื่อง 64- บิต


สิ่งนี้ดูเหมือนจะทำซ้ำเพียงจุดและอธิบายในคำตอบก่อนหน้าโพสต์เมื่อชั่วโมงที่แล้ว
gnat

@gnat ขอบคุณสำหรับความคิดเห็นของคุณ แต่ฉันไม่คิดว่ามันจะเป็นกำลังใจ
Sleiman Jneidi

คุณหมายความว่า null นั้นเป็นวัตถุที่เก็บไว้ในหน่วยความจำและตัวแปรวัตถุทั้งหมดที่กำหนดด้วย null นั้นชี้ไปที่วัตถุ null นั้น
Harish_N

@ Harish.N ไม่ฉันไม่ได้พูดอย่างนั้นฉันบอกว่ามันเป็นการอ้างอิงและไม่ใช่วัตถุ
Sleiman Jneidi

ในตัวอย่างที่คุณให้ 'd' คือการอ้างอิง .. มันเป็นการอ้างอิงถึงวัตถุประเภท Date ... ในทำนองเดียวกันถ้า null เป็นการอ้างอิง .. กับวัตถุใดที่มันอ้างถึง .. ?
Harish_N

19

ไม่มีความแตกต่างสำหรับฟิลด์คลาส พวกเขาจะnullตามค่าเริ่มต้นสำหรับวัตถุ, 0 สำหรับค่าตัวเลขและfalseสำหรับ booleans

สำหรับตัวแปรที่ประกาศในเมธอด - Java ต้องการให้มีการเตรียมใช้งาน การไม่กำหนดค่าเริ่มต้นจะทำให้เกิดข้อผิดพลาดในเวลารวบรวมเมื่อมีการเข้าถึง

เหตุผลคืออะไร ฟิลด์คลาสสามารถแก้ไขได้โดยวิธีใด ๆ ไม่ว่าจะเรียงลำดับตามวิธีใดก็ตาม ฟิลด์ที่ไม่ใช่ส่วนตัวทั้งหมดอาจถูกแก้ไขโดยคลาสอื่นและ / หรือคลาสที่ขยายคลาสนั้น ดังนั้นจึงไม่มีประเด็นที่จะแจ้งให้ทราบเกี่ยวกับตัวแปรที่ไม่มีการกำหนดค่าเริ่มต้นเนื่องจากอาจถูกกำหนดในหลาย ๆ ที่

อย่างไรก็ตามตัวแปรภายในเมธอดนั้นเป็นแบบโลคัลและสามารถแก้ไขภายในเมธอดเองเท่านั้น ดังนั้นจึงเป็นไปได้และมีเหตุผลที่จะชี้ให้เห็นข้อผิดพลาดที่เป็นไปได้ และคอมไพเลอร์พยายามที่จะทำมัน หากรู้ว่าฟิลด์นั้นไม่ได้ถูกเตรียมใช้งานมันจะแสดงข้อผิดพลาดเพราะนั่นไม่ใช่สิ่งที่คุณต้องการ หากไม่แน่ใจ - จะแจ้งเตือนเพื่อให้คุณมั่นใจได้

public static class Test {
    Date a; // ok 
    Date b = null; // ok

    public void test() {
        Date c;
        Date d = null;

        System.out.println(a.toString());
        System.out.println(b.toString());
        System.out.println(c.toString()); // error
        System.out.println(d.toString()); // warning
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.