在以上內(nèi)容學(xué)習(xí)的過程當(dāng)中,其實(shí)大家已經(jīng)接觸過實(shí)例變量是引用的情況,不知道吧!例如在Student學(xué)生類當(dāng)中有一個(gè)屬性“String name;”,這個(gè)屬性/實(shí)例變量name描述的是學(xué)生的姓名,name變量的數(shù)據(jù)類型是String類型,String類型不屬于基本數(shù)據(jù)類型的范疇,也就是說String類型屬于引用數(shù)據(jù)類型,換句話說String類型應(yīng)該對(duì)應(yīng)一個(gè)String.class文件才對(duì),String是一個(gè)類,和我們自己定義的類沒什么區(qū)別,是這樣嗎?一起來看看JDK的java源代碼:
圖9-25:jdk java源代碼位置
圖9-26:String類源代碼位置
圖9-27:String類源代碼
通過查看源代碼得知,其實(shí)String是一個(gè)class,和我們定義的類沒有區(qū)別,它和基本數(shù)據(jù)類型還是不一樣的(int i = 10,i變量是基本數(shù)據(jù)類型,i變量中存儲(chǔ)的就是10),也就是說String name = “zhangsan”,實(shí)際上name變量中存儲(chǔ)的并不是”zhangsan”這個(gè)字符串,因?yàn)閚ame是一個(gè)引用,那name中必然存儲(chǔ)的是”zhangsan”字符串對(duì)象的內(nèi)存地址。因?yàn)橹拔覀冋f過引用的概念,什么是引用:引用就是一個(gè)變量,只不過該變量中存儲(chǔ)的是java對(duì)象的內(nèi)存地址。也就是說,以前所講內(nèi)容中使用內(nèi)存圖描述字符串的時(shí)候都是有偏差的。我們來修正一下,請(qǐng)看代碼:
public class Student {
int no;
String name;
int age;
boolean sex;
public Student(int _no,String _name,int _age,boolean _sex){
no = _no;
name = _name;
age = _age;
sex = _sex;
}
}
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student(110 , "zhangsan" , 20 , true);
System.out.println("學(xué)號(hào):" + s1.no);
System.out.println("姓名:" + s1.name);
System.out.println("年齡:" + s1.age);
System.out.println("性別:" + (s1.sex ? "男" : "女"));
}
}
以上程序的運(yùn)行結(jié)果請(qǐng)看下圖:
圖9-28:運(yùn)行結(jié)果
將以上內(nèi)存結(jié)構(gòu)圖畫出來,請(qǐng)看:
圖9-29:修正字符串對(duì)象的內(nèi)存
通過上圖可以看到,Student對(duì)象當(dāng)中的name這個(gè)“屬性/實(shí)例變量”是一個(gè)引用,保存的不是”zhangsan”字符串,而是字符串對(duì)象的內(nèi)存地址。(按照實(shí)際來說,字符串”zhangsan”是在方法區(qū)的字符串常量池當(dāng)中,這個(gè)后期再繼續(xù)進(jìn)行修正)。接下來,我們?cè)賮砜纯串?dāng)屬性是其他類型引用的時(shí)候,請(qǐng)看代碼:
public class Date {
int year;
int month;
int day;
public Date(){
}
public Date(int year1 , int month1 , int day1){
year = year1;
month = month1;
day = day1;
}
}
public class Vip {
int id;
String name;
Date birth;
public Vip(){
}
public Vip(int _id,String _name,Date _birth){
id = _id;
name = _name;
birth = _birth;
}
}
public class VipTest {
public static void main(String[] args) {
Date d = new Date(1983 , 5 , 6);
Vip v = new Vip(123 , "jack" , d);
System.out.println("編號(hào)=" + v.id);
System.out.println("姓名=" + v.name);
System.out.println("生日=" + v.birth.year + "年" + v.birth.month + "月" + v.birth.day + "日");
}
}
運(yùn)行結(jié)果如下圖所示:
圖9-30:運(yùn)行結(jié)果
以上程序main方法的內(nèi)存結(jié)構(gòu)圖如下所示:
圖9-31:Date d = new Date(1983 , 5 , 6);
圖9-32:Vip v = new Vip(123 , "jack" , d);
通過以上內(nèi)容的學(xué)習(xí)大家掌握當(dāng)對(duì)象的屬性是一個(gè)引用的時(shí)候內(nèi)存圖是怎樣的了嗎?其實(shí)只要記住一點(diǎn),任何“引用”當(dāng)中存儲(chǔ)一定是對(duì)象的內(nèi)存地址,“引用”不一定只是以局部變量的形式存在,例如以上程序,其中Vip類當(dāng)中的birth屬性就是一個(gè)“引用”,它是一個(gè)實(shí)例變量。當(dāng)一個(gè)對(duì)象的屬性是引用的時(shí)候應(yīng)該如何訪問這個(gè)引用所指向的對(duì)象呢?這里其實(shí)有一個(gè)規(guī)律,大家記住就行:類當(dāng)中有什么就可以“.”什么,例如:Vip類中有birth屬性,那么就可以v.birth,那么v.birth是Date類型,Date類當(dāng)中有year屬性,那么就可以v.birth.year,你懂了嗎?