賦值是用等號運算符(=)進行的
它的意思是
取得右邊的值
把它復制到左邊
右邊的值可以是任何常數
變量或者表達式
只要能產生一個值就行
但左邊的值必須是一個明確的
已命名的變量
也就是說
它必須有一個物理性的空間來保存右邊的值
舉個例子來說
可將一個常數賦給一個變量(A=
;)
但不可將任何東西賦給一個常數(比如不能
=A)
對主數據類型的賦值是非常直接的
由於主類型容納了實際的值
而且並非指向一個對象的句柄
所以在為其賦值的時候
可將來自一個地方的內容復制到另一個地方
例如
假設為主類型使用
A=B
那麼B處的內容就復制到A
若接著又修改了A
那麼B根本不會受這種修改的影響
作為一名程序員
這應成為自己的常識
但在為對象
賦值
的時候
情況卻發生了變化
對一個對象進行操作時
我們真正操作的是它的句柄
所以倘若
從一個對象到另一個對象
賦值
實際就是將句柄從一個地方復制到另一個地方
這意味著假若為對象使用
C=D
那麼C和D最終都會指向最初只有D才指向的那個對象
下面這個例子將向大家闡示這一點
這裡有一些題外話
在後面
大家在代碼示例裡看到的第一個語句將是
package
使用的
package
語句
它代表本書第
章
本書每一章的第一個代碼清單都會包含象這樣的一個
package
(封裝
打包
包裹)語句
它的作用是為那一章剩余的代碼建立章節編號
在第
章
大家會看到第
章的所有代碼清單(除那些有不同封裝名稱的以外)都會自動置入一個名為c
的子目錄裡
第
章的代碼置入c
以此類推
所有這些都是通過第
章展示的CodePackage
java程序實現的
封裝
的基本概念會在第
章進行詳盡的解釋
就目前來說
大家只需記住象
package
這樣的形式只是用於為某一章的代碼清單建立相應的子目錄
為運行程序
必須保證在classpath裡包含了我們安裝本書源碼文件的根目錄(那個目錄裡包含了c
c
c
c
等等子目錄)
對於Java後續的版本(
和更高版本)
如果您的main()用package語句封裝到一個文件裡
那麼必須在程序名前面指定完整的包裹名稱
否則不能運行程序
在這種情況下
命令行是
java c
Assignment
運行位於一個
包裹
裡的程序時
隨時都要注意這方面的問題
下面是例子
//: Assignment
java
// Assignment with objects is a bit tricky
package c
;
class Number {
int i;
}
public class Assignment {
public static void main(String[] args) {
Number n
= new Number();
Number n
= new Number();
n
i =
;
n
i =
;
System
out
println(
: n
i:
+ n
i +
n
i:
+ n
i);
n
= n
;
System
out
println(
: n
i:
+ n
i +
n
i:
+ n
i);
n
i =
;
System
out
println(
: n
i:
+ n
i +
n
i:
+ n
i);
}
} ///:~
Number類非常簡單
它的兩個實例(n
和n
)是在main()裡創建的
每個Number中的i值都賦予了一個不同的值
隨後
將n
賦給n
而且n
發生改變
在許多程序設計語言中
我們都希望n
和n
任何時候都相互獨立
但由於我們已賦予了一個句柄
所以下面才是真實的輸出
: n
i:
n
i:
: n
i:
n
i:
: n
i:
n
i:
看來改變n
的同時也改變了n
!這是由於無論n
還是n
都包含了相同的句柄
它指向相同的對象(最初的句柄位於n
內部
指向容納了值
的一個對象
在賦值過程中
那個句柄實際已經丟失
它的對象會由
垃圾收集器
自動清除)
這種特殊的現象通常也叫作
別名
是Java操作對象的一種基本方式
但假若不願意在這種情況下出現別名
又該怎麼操作呢?可放棄賦值
並寫入下述代碼
n
i = n
i;
這樣便可保留兩個獨立的對象
而不是將n
和n
綁定到相同的對象
但您很快就會意識到
這樣做會使對象內部的字段處理發生混亂
並與標准的面向對象設計准則相悖
由於這並非一個簡單的話題
所以留待第
章詳細論述
那一章是專門討論別名的
其時
大家也會注意到對象的賦值會產生一些令人震驚的效果
方法調用中的別名處理
將一個對象傳遞到方法內部時
也會產生別名現象
//: 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(
: x
c:
+ x
c);
f(x);
System
out
println(
: x
c:
+ x
c);
}
} ///:~
在許多程序設計語言中
f()方法表面上似乎要在方法的作用域內制作自己的自變量Letter y的一個副本
但同樣地
實際傳遞的是一個句柄
所以下面這個程序行
y
c =
z
;
實際改變的是f()之外的對象
輸出結果如下
: x
c: a
: x
c: z
別名和它的對策是非常復雜的一個問題
盡管必須等至第
章才可獲得所有答案
但從現在開始就應加以重視
以便提早發現它的缺點
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19494.html