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

java的賦值

編輯:關於JAVA

賦值是用等號運算符(=)進行的。它的意思是“取得右邊的值,把它復制到左邊”。右邊的值可以是任何常數、變量或者表達式,只要能產生一個值就行。但左邊的值必須是一個明確的、已命名的變量。也就是說,它必須有一個物理性的空間來保存右邊的值。舉個例子來說,可將一個常數賦給一個變量(A=4;),但不可將任何東西賦給一個常數(比如不能4=A)。
對主數據類型的賦值是非常直接的。由於主類型容納了實際的值,而且並非指向一個對象的句柄,所以在為其賦值的時候,可將來自一個地方的內容復制到另一個地方。例如,假設為主類型使用“A=B”,那麼B處的內容就復制到A。若接著又修改了A,那麼B根本不會受這種修改的影響。作為一名程序員,這應成為自己的常識。
但在為對象“賦值”的時候,情況卻發生了變化。對一個對象進行操作時,我們真正操作的是它的句柄。所以倘若“從一個對象到另一個對象”賦值,實際就是將句柄從一個地方復制到另一個地方。這意味著假若為對象使用“C=D”,那麼C和D最終都會指向最初只有D才指向的那個對象。下面這個例子將向大家闡示這一點。
這裡有一些題外話。在後面,大家在代碼示例裡看到的第一個語句將是“package 03”使用的“package”語句,它代表本書第3章。本書每一章的第一個代碼清單都會包含象這樣的一個“package”(封裝、打包、包裹)語句,它的作用是為那一章剩余的代碼建立章節編號。在第17章,大家會看到第3章的所有代碼清單(除那些有不同封裝名稱的以外)都會自動置入一個名為c03的子目錄裡;第4章的代碼置入c04;以此類推。所有這些都是通過第17章展示的CodePackage.java程序實現的;“封裝”的基本概念會在第5章進行詳盡的解釋。就目前來說,大家只需記住象“package 03”這樣的形式只是用於為某一章的代碼清單建立相應的子目錄。
為運行程序,必須保證在classpath裡包含了我們安裝本書源碼文件的根目錄(那個目錄裡包含了c02,c03c,c04等等子目錄)。
對於Java後續的版本(1.1.4和更高版本),如果您的main()用package語句封裝到一個文件裡,那麼必須在程序名前面指定完整的包裹名稱,否則不能運行程序。在這種情況下,命令行是:
java c03.Assignment
運行位於一個“包裹”裡的程序時,隨時都要注意這方面的問題。
下面是例子:

 

//: Assignment.java
// Assignment with objects is a bit tricky
package c03;

class Number {
  int i;
}

public class Assignment {
  public static void main(String[] args) {
    Number n1 = new Number();
    Number n2 = new Number();
    n1.i = 9;
    n2.i = 47;
    System.out.println("1: n1.i: " + n1.i +
      ", n2.i: " + n2.i);
    n1 = n2;
    System.out.println("2: n1.i: " + n1.i +
      ", n2.i: " + n2.i);
    n1.i = 27;
    System.out.println("3: n1.i: " + n1.i +
      ", n2.i: " + n2.i);
  }
} ///:~


Number類非常簡單,它的兩個實例(n1和n2)是在main()裡創建的。每個Number中的i值都賦予了一個不同的值。隨後,將n2賦給n1,而且n1發生改變。在許多程序設計語言中,我們都希望n1和n2任何時候都相互獨立。但由於我們已賦予了一個句柄,所以下面才是真實的輸出:
1: n1.i: 9, n2.i: 47
2: n1.i: 47, n2.i: 47
3: n1.i: 27, n2.i: 27
看來改變n1的同時也改變了n2!這是由於無論n1還是n2都包含了相同的句柄,它指向相同的對象(最初的句柄位於n1內部,指向容納了值9的一個對象。在賦值過程中,那個句柄實際已經丟失;它的對象會由“垃圾收集器”自動清除)。
這種特殊的現象通常也叫作“別名”,是Java操作對象的一種基本方式。但假若不願意在這種情況下出現別名,又該怎麼操作呢?可放棄賦值,並寫入下述代碼:
n1.i = n2.i;
這樣便可保留兩個獨立的對象,而不是將n1和n2綁定到相同的對象。但您很快就會意識到,這樣做會使對象內部的字段處理發生混亂,並與標准的面向對象設計准則相悖。由於這並非一個簡單的話題,所以留待第12章詳細論述,那一章是專門討論別名的。其時,大家也會注意到對象的賦值會產生一些令人震驚的效果。

1. 方法調用中的別名處理
將一個對象傳遞到方法內部時,也會產生別名現象。

 

//: PassObject.java
// Passing objects to methods can be a bit tricky

class Letter {
  char c;
}

public class PassObject {
  static void f(Letter y) {
    y.c = 'z';
  }
  public static void main(String[] args) {
    Letter x = new Letter();
    x.c = 'a';
    System.out.println("1: x.c: " + x.c);
    f(x);
    System.out.println("2: x.c: " + x.c);
  }
} ///:~


在許多程序設計語言中,f()方法表面上似乎要在方法的作用域內制作自己的自變量Letter y的一個副本。但同樣地,實際傳遞的是一個句柄。所以下面這個程序行:
y.c = 'z';
實際改變的是f()之外的對象。輸出結果如下:
1: x.c: a
2: x.c: z
別名和它的對策是非常復雜的一個問題。盡管必須等至第12章才可獲得所有答案,但從現在開始就應加以重視,以便提早發現它的缺點。

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