2015-05-04 59 views
1

我想知道爲什麼在obj = w;之後引用「w」會引發錯誤。你是不是隻是通過說obj = w來創建另一個指向該w實例的指針?即爲什麼說String s = "hi"; String w = s;這樣的話謝謝!爲什麼此Java轉換會引發錯誤?

public class Casting { 
    public static void main(String[] args) { 
     // casting doesn't change the object 
     Object obj; 
     { 
      Stopwatch w = new Stopwatch(); 
      obj = w; 
     } 
     System.out.println(obj); // this line does work 
     System.out.println(w); //this line does not work 
    } 
} 
+5

迎刃而解'w'是斷章取義的,它只有內上下文中的'{...}'塊 – MadProgrammer

+0

所以我們根本不知道這整個'obj對象;'東西 - 這些代碼行究竟發生了什麼?我們只學習了一個方法/類聲明,後面跟着一組花括號 - 從來不是一個對象。就像我會得到它,如果'對象obj;'被替換爲方法聲明,但這是一個...對象聲明? – rb612

+1

請參閱[本](http://stackoverflow.com/questions/241088/java-what-do-curly-braces-mean-by-自己)。 – user1803551

回答

4

沒有什麼比早上引用JLS的第一件事了。

JLS 6.3。宣言的範圍:

局部變量聲明的塊中的範圍(§14.4)是在其中出現的聲明,開始與它自己的初始化,並且包括任何進一步說明符到右邊的塊的其餘部分在局部變量聲明語句中。

JLS 14.2。塊:

是語句,局部類聲明,並且括號內的局部變量聲明的語句序列。

是什麼,你的情況是什麼意思?當地varialbe w在塊

{ 
    Stopwatch w = new Stopwatch(); 
    obj = w; 
} 

聲明(「自身的初始化」是塊中的第一行),因此其範圍是該塊的其餘部分。對它的引用,

System.out.println(w); 

是塊之外,並且因此w將不能夠解決給一個變量。

那麼局部變量obj呢那麼呢?它在塊

public static void main(String[] args) { 

    Object obj; 
    { 
     Stopwatch w = new Stopwatch(); 
     obj = w; 
    } 
    System.out.println(obj); 
    System.out.println(w); 
} 

中聲明,在這種情況下是方法塊。電話

System.out.println(obj); 

是塊內部,因此可以成功引用obj

+0

我很好奇,有沒有機會正確使用這樣的塊?我從來沒有在Java中跑過這個... –

+0

@ DanCiborowski-MSFT在大多數代碼段中它確實不是一個常見的站點,但是代碼塊有很多用途。我會盡量以一個例子回覆你。 – user1803551

+0

@Dan,最典型的用例是'switch'語句的'case'(對於雙關語),如'switch(value){... case MAGIC:{MyMagic magic = new MyMagic() ; magic.castSpell();打破;}' - 這樣你可以限制它的可見性到'case'。另一個例子是一個巨大的構造函數,它在將它們分配給final字段之前創建許多臨時變量。 –

0

變量w在塊內部聲明,因此超出塊不存在。這個問題與鑄造無關。取下牙套,它會工作:

public class Casting { 
    public static void main(String[] args) { 
     // casting doesn't change the object 
     Object obj; 
     Stopwatch w = new Stopwatch(); 
     obj = w; 
     System.out.println(obj); 
     System.out.println(w); 
    } 
} 
+0

好了。謝謝。那麼,Object obj;後面跟着一組大括號是做什麼的呢? – rb612

+2

'Object obj;'只是聲明一個類型爲'Object'的變量'obj',並且語句在這裏結束。之後是一個獨立於前一個聲明的區塊聲明。塊語句有其自己的範圍,這意味着塊中聲明的變量在其外部不可見。 –

0

正如所提及般在其他的答案,去掉括號將工作。如果你想保留括號,你也可以做如下。實際上在java中,變量有範圍,一個變量可以在聲明的範圍內使用。就像在「if」塊或「try」塊中聲明某個變量一樣,它只能在該範圍內使用。 這有助於有效的垃圾收集。但最好在最小需求範圍內定義變量但是,如果您要在某個地方創建某個對象,但您希望在該部分之後使用該對象(塊),請在該塊之外聲明(變量不必創建對象)。

public class Casting { 
public static void main(String[] args) { 
    // casting doesn't change the object 
    Object obj; 
    Stopwatch w ; 
    { 
     w = new Stopwatch(); 
     obj = w; 
    } 
    System.out.println(obj); // this line does work 
    System.out.println(w); //this line does not work 
    } 
} 
+0

謝謝你的迴應。那麼現在這兩個println語句都可以工作,因爲你在大括號之外創建了對象? – rb612

+1

兩個println都可以工作,因爲我已經在大括號外聲明瞭兩個變量。創建對象和聲明變量是有區別的。對象將在我們擁有新關鍵字的大括號中創建。但是,直到主方法結束,該對象纔會被垃圾收集。因爲持有該對象的變量w在大括號外宣佈 – Panther

1

這與

{ 
     Stopwatch w = new Stopwatch(); 
     obj = w; 
    } 

這裏在W範圍括號內obly這個變量是無法訪問的scope.The範圍問題outside.So這裏也沒有分配的問題,但問題是涉及到的範圍,並且可以通過

public class Casting { public static void main(String[] args) { 
    // casting doesn't change the object 
    String w; 
    Object obj; 
    { 
     w = new String(); 
     obj = w; 
    } 
    System.out.println(obj); // this line does work 
    System.out.println(w); //this line now working  } } 
相關問題