在以上內容學習的過程當中,其實大家已經接觸過實例變量是引用的情況,不知道吧!例如在Student學生類當中有一個屬性“String name;”,這個屬性/實例變量name描述的是學生的姓名,name變量的數據類型是String類型,String類型不屬于基本數據類型的范疇,也就是說String類型屬于引用數據類型,換句話說String類型應該對應一個String.class文件才對,String是一個類,和我們自己定義的類沒什么區別,是這樣嗎?一起來看看JDK的java源代碼:
圖9-25:jdk java源代碼位置
圖9-26:String類源代碼位置
圖9-27:String類源代碼
通過查看源代碼得知,其實String是一個class,和我們定義的類沒有區別,它和基本數據類型還是不一樣的(int i = 10,i變量是基本數據類型,i變量中存儲的就是10),也就是說String name = “zhangsan”,實際上name變量中存儲的并不是”zhangsan”這個字符串,因為name是一個引用,那name中必然存儲的是”zhangsan”字符串對象的內存地址。因為之前我們說過引用的概念,什么是引用:引用就是一個變量,只不過該變量中存儲的是java對象的內存地址。也就是說,以前所講內容中使用內存圖描述字符串的時候都是有偏差的。我們來修正一下,請看代碼:
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("學號:" + s1.no);
System.out.println("姓名:" + s1.name);
System.out.println("年齡:" + s1.age);
System.out.println("性別:" + (s1.sex ? "男" : "女"));
}
}
以上程序的運行結果請看下圖:
圖9-28:運行結果
將以上內存結構圖畫出來,請看:
圖9-29:修正字符串對象的內存
通過上圖可以看到,Student對象當中的name這個“屬性/實例變量”是一個引用,保存的不是”zhangsan”字符串,而是字符串對象的內存地址。(按照實際來說,字符串”zhangsan”是在方法區的字符串常量池當中,這個后期再繼續進行修正)。接下來,我們再來看看當屬性是其他類型引用的時候,請看代碼:
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("編號=" + v.id);
System.out.println("姓名=" + v.name);
System.out.println("生日=" + v.birth.year + "年" + v.birth.month + "月" + v.birth.day + "日");
}
}
運行結果如下圖所示:
圖9-30:運行結果
以上程序main方法的內存結構圖如下所示:
圖9-31:Date d = new Date(1983 , 5 , 6);
圖9-32:Vip v = new Vip(123 , "jack" , d);
通過以上內容的學習大家掌握當對象的屬性是一個引用的時候內存圖是怎樣的了嗎?其實只要記住一點,任何“引用”當中存儲一定是對象的內存地址,“引用”不一定只是以局部變量的形式存在,例如以上程序,其中Vip類當中的birth屬性就是一個“引用”,它是一個實例變量。當一個對象的屬性是引用的時候應該如何訪問這個引用所指向的對象呢?這里其實有一個規律,大家記住就行:類當中有什么就可以“.”什么,例如:Vip類中有birth屬性,那么就可以v.birth,那么v.birth是Date類型,Date類當中有year屬性,那么就可以v.birth.year,你懂了嗎?