多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區(qū)平臺 聯系我們 | 收藏本站
阿里云優(yōu)惠2
您當前位置:首頁 > php開源 > php教程 > Java對象引用,以及對象賦值

Java對象引用,以及對象賦值

來源:程序員人生   發(fā)布時間:2017-02-04 09:12:43 閱讀次數:2686次

學習Java的同學注意了!!! 
學習進程中遇到甚么問題或想獲得學習資源的話,歡迎加入Java學習交換群,群號碼:183993990  我們1起學Java!


關鍵字: java對象 援用

Java對象及其援用

關于對象與援用之間的1些基本概念。

       初學Java時,在很長1段時間里,總覺得基本概念很模糊。后來才知道,在許多Java書中,把對象和對象的援用混為1談。可是,如果我分不清對象與對象援用,

       那實在沒法很好地理解下面的面向對象技術。把自己的1點認識寫下來,也許能讓初學Java的朋友們少走1點彎路。

       為便于說明,我們先定義1個簡單的類:

       class Vehicle {

       int passengers;      

       int fuelcap;

       int mpg;

                   }

有了這個模板,就能夠用它來創(chuàng)建對象:

       Vehicle veh1 = new Vehicle();

通常把這條語句的動作稱之為創(chuàng)建1個對象,其實,它包括了4個動作。

1)右側的“new Vehicle”,是以Vehicle類為模板,在堆空間里創(chuàng)建1個Vehicle類對象(也簡稱為Vehicle對象)。

2)末尾的()意味著,在對象創(chuàng)建后,立即調用Vehicle類的構造函數,對剛生成的對象進行初始化。構造函數是肯定有的。如果你沒寫,Java會給你補上1個默許的構造函數。

3)左側的“Vehicle veh 1”創(chuàng)建了1個Vehicle類援用變量。所謂Vehicle類援用,就是以后可以用來指向Vehicle對象的對象援用。

4)“=”操作符使對象援用指向剛創(chuàng)建的那個Vehicle對象。

我們可以把這條語句拆成兩部份:

Vehicle veh1;

veh1 = new Vehicle();

效果是1樣的。這樣寫,就比較清楚了,有兩個實體:1是對象援用變量,1是對象本身。

       在堆空間里創(chuàng)建的實體,與在數據段和棧空間里創(chuàng)建的實體不同。雖然它們也是確確切實存在的實體,但是,我們看不見,也摸不著。不但如此,

       我們仔細研究1下第2句,找找剛創(chuàng)建的對象叫甚么名字?有人說,它叫“Vehicle”。不對,“Vehicle”是類(對象的創(chuàng)建模板)的名字。

       1個Vehicle類可以據此創(chuàng)建出無數個對象,這些對象不可能全叫“Vehicle”。

       對象連名都沒有,沒法直接訪問它。我們只能通過對象援用來間接訪問對象。

       為了形象地說明對象、援用及它們之間的關系,可以做1個也許不很妥當的比喻。對象好比是1只很大的氣球,大到我們抓不住它。援用變量是1根繩, 可以用來系汽球。

       如果只履行了第1條語句,還沒履行第2條,此時創(chuàng)建的援用變量veh1還沒指向任何1個對象,它的值是null。援用變量可以指向某個對象,或為null

       它是1根繩,1根還沒有系上任何1個汽球的繩。履行了第2句后,1只新汽球做出來了,并被系在veh1這根繩上。我們捉住這根繩,就等于捉住了那只汽球。

       再來1句:

       Vehicle veh2;

就又做了1根繩,還沒系上汽球。如果再加1句:

       veh2 = veh1;

系上了。這里,產生了復制行動。但是,要說明的是,對象本身并沒有被復制,被復制的只是對象援用。結果是,veh2也指向了veh1所指向的對象。兩根繩系的是同1只汽球。

       如果用下句再創(chuàng)建1個對象:

veh2 = new Vehicle();

則援用變量veh2改指向第2個對象。

       從以上敘述再推演下去,我們可以取得以下結論:

1)1個對象援用可以指向0個或1個對象(1根繩子可以不系汽球,也能夠系1個汽球);

2)1個對象可以有N個援用指向它(可以有N條繩子系住1個汽球)。

       如果再來下面語句:

       veh1 = veh2;

按上面的推斷,veh1也指向了第2個對象。這個沒問題。問題是第1個對象呢?沒有1條繩子系住它,它飛了。多數書里說,它被Java的垃圾回收機制回收了。

這不確切。正確地說,它已成為垃圾回收機制的處理對象。至于甚么時候真正被回收,那要看垃圾回收機制的心情了。

       由此看來,下面的語句應當不合法吧?最少是沒用的吧?

new Vehicle();

不對。它是合法的,而且可用的。比方,如果我們僅僅為了打印而生成1個對象,就不需要用援用變量來系住它。最多見的就是打印字符串:

    System.out.println(“I am Java!”);

字符串對象“I am Java!”在打印后即被拋棄。有人把這類對象稱之為臨時對象。

       對象與援用的關系將延續(xù)到對象回收。

  

Java對象及援用

 

Java對象及援用是容易混淆卻又必須掌握的基礎知識,本章論述Java對象和援用的概念,和與其密切相干的參數傳遞。

 

先看下面的程序:

StringBuffer s;

s = new StringBuffer("Hello World!");

第1個語句僅為援用(reference)分配了空間,而第2個語句則通過調用類(StringBuffer)的構造函數StringBuffer(String str)為類生成了1個實例(或稱為對象)。這兩個操作被完成后,對象的內容則可通過s進行訪問——在Java里都是通過援用來操縱對象的。

 

Java對象和援用的關系可以說是相互關聯,卻又彼此獨立。彼此獨立主要表現在:援用是可以改變的,它可以指向別的對象,比方上面的s,你可以給它另外的對象,如:

s = new StringBuffer("Java");

這樣1來,s就和它指向的第1個對象脫離關系。

 

從存儲空間上來講,對象和援用也是獨立的,它們存儲在不同的地方,對象1般存儲在堆中,而援用存儲在速度更快的堆棧中。

 

援用可以指向不同的對象,對象也能夠被多個援用操縱,如:

StringBuffer s1 = s;

這條語句使得s1s指向同1個對象。既然兩個援用指向同1個對象,那末不管使用哪一個援用操縱對象,對象的內容都產生改變,并且只有1份,通過s1s得到的內容自然也1樣,(String除外,由于String始終不變,String s1=”AAAA”; String s=s1,操作s,s1由于始終不變,所以為s另外開辟了空間來存儲s,)以下面的程序:

StringBuffer s;

s = new StringBuffer("Java");

StringBuffer s1 = s;

s1.append(" World");

System.out.println("s1=" + s1.toString());//打印結果為:s1=Java World

System.out.println("s=" + s.toString());//打印結果為:s=Java World

  

上面的程序表明,s1s打印出來的內容是1樣的,這樣的結果看起來讓人非常疑惑,但是仔細想一想,s1s只是兩個援用,它們只是操縱桿而已,它們指向同1個對象,操縱的也是同1個對象,通過它們得到的是同1個對象的內容。這就像汽車的剎車和油門,它們操縱的都是車速,假設汽車開始的速度是80,然后你踩了1次油門,汽車加速了,假設車速升到了120,然后你踩1下剎車,此時車速是從120開始降落的,假設降落到60,再踩1次油門,車速則從60開始上升,而不是從第1次踩油門后的120開始。也就是說車速同時受油門和剎車影響,它們的影響是積累起來的,而不是各自獨立(除非剎車和油門不在1輛車上)。所以,在上面的程序中,不管使用s1還是s操縱對象,它們對對象的影響也是積累起來的(更多的援用同理)。

 

只有理解了對象和援用的關系,才能理解參數傳遞。

1般面試題中都會考Java傳參的問題,并且它的標準答案是Java只有1種參數傳遞方式:那就是按值傳遞,即Java中傳遞任何東西都是傳值。如果傳入方法的是基本類型的東西,你就得到此基本類型的1份拷貝。如果是傳遞援用,就得到援用的拷貝。

 

1般來講,對基本類型的傳遞,我們很容易理解,而對對象,總讓人感覺是按援用傳遞,看下面的程序:

public class ObjectRef {

 

    //基本類型的參數傳遞

    public static void testBasicType(int m) {

        System.out.println("m=" + m);//m=50

        m = 100;

        System.out.println("m=" + m);//m=100

    }

   

    //參數為對象,不改變援用的值 ??????

    public static void add(StringBuffer s) {

        s.append("_add");

    }

   

    //參數為對象,改變援用的值 ?????

    public static void changeRef(StringBuffer s) {

        s = new StringBuffer("Java");

    }

   

    public static void main(String[] args) {

        int i = 50;

        testBasicType(i);

        System.out.println(i);//i=50

        StringBuffer sMain = new StringBuffer("init");

        System.out.println("sMain=" + sMain.toString());//sMain=init

        add(sMain);

        System.out.println("sMain=" + sMain.toString());//sMain=init_add

        changeRef(sMain);

        System.out.println("sMain=" + sMain.toString());//sMain=init_add

    }

}

以上程序的允許結果顯示出,testBasicType方法的參數是基本類型,雖然參數m的值產生改變,但其實不影響i

      add方法的參數是1個對象,當把sMain傳給參數s時,s得到的是sMain的拷貝,所以ssMain指向同1個對象,因此,使用s操作影響的其實就是sMain指向的對象,故調用add方法后,sMain指向的對象的內容產生了改變。

      在changeRef方法中,參數也是對象,當把sMain傳給參數s時,s得到的是sMain的拷貝,但與add方法不同的是,在方法體內改變了s指向的對象(也就是s指向了別的對象,牽著氣球的繩子換氣球了),給s重新賦值后,ssMain已毫無關聯,它和sMain指向了不同的對象,所以不管對s做甚么操作,都不會影響sMain指向的對象,故調用changeRef方法前后sMain指向的對象內容并未產生改變。

 

add方法的調用結果,可能很多人會有這類感覺:這不明明是按援用傳遞嗎?對這類問題,還是套用Bruce Eckel的話:這依賴于你如何看待援用,終究你會明白,這個爭辯并沒那末重要。真正重要的是,你要理解,傳援用使得(調用者的)對象的修改變得不可預期。

 

 public   class   Test
{   public int   i,j;  
    public   void   test_m(Test   a)
    {     Test   b   =  new   Test();
          b.i   =   1;
          b.j   =   2;
          a   =   b;
    }
    public   void   test_m1(Test   a   )
    {     a.i   =   1;
        a.j   =   2;
    }
    public   static   void   main(String   argv[])
    {     Test   t=   new   Test();
          t.i   =   5;
          t.j   =   6;
          System.out.println( "t.i   =   "+   t.i   +   "   t.j=   "   +   t.j); //5,6
          t.test_m(t);
          System.out.println( "t.i   =   "+   t.i   +   "   t.j=   "   +   t.j); //5,6,
at都指向了1個對象,而在test_ms又指向了另外一個對象,所以對象t不變!!!

          t.test_m1(t);

          System.out.println( "t.i   =   "+   t.i   +   "   t.j=   "   +   t.j); //1,2

    }

}

答案只有1個:Java里都是按值傳遞參數。而實際上,我們要明白,當參數是對象時,傳援用會產生甚么狀態(tài)(就像上面的add方法)?

 

=========================================================================

樓主,這樣來記這個問題
以下表達式:
A a1 = new A();
它代表A是類,a1是援用,a1不是對象,new A()才是對象,a1援用指向new A()這個對象。

在JAVA里,“=”不能被看成是1個賦值語句,它不是在把1個對象賦給另外1個對象,它的履行進程實質上是將右側對象的地址傳給了左側的援用,使得左側的援用指向了右側的對象。JAVA表面上看起來沒有指針,但它的援用其實質就是1個指針,援用里面寄存的其實不是對象,而是該對象的地址,使得該援用指向了對象。在JAVA里,“=”語句不應當被翻譯成賦值語句,由于它所履行的確切不是1個賦值的進程,而是1個傳地址的進程,被譯成賦值語句會造成很多誤解,譯得不準確。

 

再如:
A a2;
它代表A是類,a2是援用,a2不是對象,a2所指向的對象為空null;

 

再如:
a2 = a1;
它代表,a2是援用,a1也是援用,a1所指向的對象的地址傳給了a2(傳址),使得a2和a1指向了同1對象。

綜上所述,可以簡單的記為,在初始化時,“=”語句左側的是援用,右側new出來的是對象。
在后面的左右都是援用的“=”語句時,左右的援用同時指向了右側援用所指向的對象。

再所謂實例,其實就是對象的同義詞。

 

 

 

如果需要賦值,就需要類實現Cloneable接口,實現clone()方法。

1
2
3
4
5
6
7
8
9
10
11
class D implements Cloneable{//實現Cloneable接口
	String sex;
	D(String sex){
		this.sex=sex;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// 實現clone方法
		return super.clone();
	}
}

賦值的時候:

1
2
D d=new D("男");
D d2=(D) d.clone();//把d賦值給d2

如果類中的變量不是主類型,而是對象,也需要調用該對象的clone()方法
下面是1個完全的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Test2 {
	public static void main(String[] args) throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		D d=new D("男");
		C c=new C("張3","20",d);
		C new_c=(C) c.clone();//調用clone方法來賦值
		new_c.name="李4";
		d.sex="女";//d
		System.out.println(c.d.sex);
		System.out.println(c.name);
 
	}
 
}
 
class C implements Cloneable{
	String name;
	String age;
	D d;
	C(String name,String age,D d) throws CloneNotSupportedException{
		this.name=name;
		this.age=age;
		this.d=(D) d.clone();//調用clone方法來賦值,這樣即使外部的d產生變化,c里的也不會變
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
}
class D implements Cloneable{//實現Cloneable接口
	String sex;
	D(String sex){
		this.sex=sex;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// 實現clone方法
		return super.clone();
	}
}

學習Java的同學注意了!!! 
學習進程中遇到甚么問題或想獲得學習資源的話,歡迎加入Java學習交換群,群號碼:183993990  我們1起學Java!

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 高清欧美在线三级视频 | 日韩欧美综合在线二区三区 | 国产三级第一页 | 久久精品女人毛片国产 | 99久久精品国产高清一区二区 | 国产日韩欧美精品一区二区三区 | 激情久久久久久久久久 | 91精品福利一区二区 | 日韩精品在线播放 | 久久国产综合精品欧美 | 欧美成人精品高清在线播放 | 欧美亚洲国产另类 | 成人精品一区二区www | 国产成人久久精品推最新 | 性激烈的欧美三级视频中文字幕 | 在线免费网站 | 亚洲欧美成人综合在线 | 国产成人爱片免费观看视频 | 性欧美高清极品猛交 | 伊人影院在线观看视频 | 黄上床大片 | 农村女人的一级毛片 | 色中色欧美 | 成人性生活免费看 | 国产清纯91天堂在线观看 | 91精品国产亚洲爽啪在线影院 | 一级毛片真人不卡免费播 | h网站在线看 | 手机在线色视频 | 亚洲欧美日韩综合在线一区二区三区 | 欧美亚洲综合视频 | 免费国产一区二区三区四区 | 欧美精品免费一区欧美久久优播 | 国产精品区一区二区免费 | 亚洲精品色一区二区三区 | 久久亚洲精品无码观看不卡 | 日本免费色视频 | 视频二区 调教中字 知名国产 | 午夜噜噜噜私人影院在线播放 | 国产精品亚洲一区二区三区正片 | 日本一道dvd在线中文字幕 |