程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java別名問題

java別名問題

編輯:關於JAVA

“別名”意味著多個句柄都試圖指向同一個對象,就象前面的例子展示的那樣。若有人向那個對象裡寫入一點什麼東西,就會產生別名問題。若其他句柄的所有者不希望那個對象改變,恐怕就要失望了。這可用下面這個簡單的例子說明:
 

//: Alias1.java
// Aliasing two handles to one object

public class Alias1 {
  int i;
  Alias1(int ii) { i = ii; }
  public static void main(String[] args) {
    Alias1 x = new Alias1(7);
    Alias1 y = x; // Assign the handle
    System.out.println("x: " + x.i);
    System.out.println("y: " + y.i);
    System.out.println("Incrementing x");
    x.i++;
    System.out.println("x: " + x.i);
    System.out.println("y: " + y.i);
  }
} ///:~

對下面這行:
Alias1 y = x; // Assign the handle
它會新建一個Alias1句柄,但不是把它分配給由new創建的一個新鮮對象,而是分配給一個現有的句柄。所以句柄x的內容——即對象x指向的地址——被分配給y,所以無論x還是y都與相同的對象連接起來。這樣一來,一旦x的i在下述語句中增值:
x.i++;
y的i值也必然受到影響。從最終的輸出就可以看出:
 

x: 7
y: 7
Incrementing x
x: 8
y: 8

此時最直接的一個解決辦法就是干脆不這樣做:不要有意將多個句柄指向同一個作用域內的同一個對象。這樣做可使代碼更易理解和調試。然而,一旦准備將句柄作為一個自變量或參數傳遞——這是Java設想的正常方法——別名問題就會自動出現,因為創建的本地句柄可能修改“外部對象”(在方法作用域之外創建的對象)。下面是一個例子:
 

//: Alias2.java
// Method calls implicitly alias their
// arguments.

public class Alias2 {
  int i;
  Alias2(int ii) { i = ii; }
  static void f(Alias2 handle) {
    handle.i++;
  }
  public static void main(String[] args) {
    Alias2 x = new Alias2(7);
    System.out.println("x: " + x.i);
    System.out.println("Calling f(x)");
    f(x);
    System.out.println("x: " + x.i);
  }
} ///:~

輸出如下:
x: 7
Calling f(x)
x: 8

方法改變了自己的參數——外部對象。一旦遇到這種情況,必須判斷它是否合理,用戶是否願意這樣,以及是不是會造成問題。
通常,我們調用一個方法是為了產生返回值,或者用它改變為其調用方法的那個對象的狀態(方法其實就是我們向那個對象“發一條消息”的方式)。很少需要調用一個方法來處理它的參數;這叫作利用方法的“副作用”(Side Effect)。所以倘若創建一個會修改自己參數的方法,必須向用戶明確地指出這一情況,並警告使用那個方法可能會有的後果以及它的潛在威脅。由於存在這些混淆和缺陷,所以應該盡量避免改變參數。
若需在一個方法調用期間修改一個參數,且不打算修改外部參數,就應在自己的方法內部制作一個副本,從而保護那個參數。本章的大多數內容都是圍繞這個問題展開的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved