第五章:面向?qū)ο蠡A(chǔ)——類(lèi)與對(duì)象進(jìn)一步研究 。

本章目標(biāo)

  • 掌握J(rèn)ava中的內(nèi)存劃分
  • 初窺Java引用傳遞
  • 垃圾的產(chǎn)生分析

內(nèi)存劃分:對(duì)象創(chuàng)建之初

public class ClassDemo02{
    public static void main(String args[]){
        Person per = new Person() ; // 創(chuàng)建并實(shí)例化對(duì)象
    }
}
Person per = new Person();
  • 聲明對(duì)象:Person per, 棧內(nèi)存中聲明,與數(shù)組一樣,數(shù)組名稱(chēng)就保存在棧內(nèi)存中,只開(kāi)辟了 棧內(nèi)存的對(duì)象是無(wú)法使用的,必須有其堆內(nèi)存的引用才可以使用。
  • 實(shí)例化對(duì)象:new Person(),在堆中開(kāi)辟空間,所有的內(nèi)容都是默認(rèn)值。
    • String:是一個(gè)字符串,本身是一個(gè)類(lèi),就是一個(gè)引用數(shù)據(jù)類(lèi)型,則此時(shí)默認(rèn)值就是null。
    • int:是一個(gè)整數(shù),本身是一個(gè)數(shù),所以是基本數(shù)據(jù)類(lèi)型,則此時(shí)的默認(rèn)值就是0。

如果進(jìn)一步劃分以上的代碼,則可以寫(xiě)成如下的形式:

Person per = null ;     // 聲明對(duì)象
per = new Person() ;    // 實(shí)例化對(duì)象

開(kāi)發(fā)中,數(shù)據(jù)最好賦一個(gè)初值,這樣操作會(huì)比較方便。

了解了其分配關(guān)系,就可以為屬性賦值,并調(diào)用類(lèi)中的方法。
使用格式:

  • 調(diào)用屬性:對(duì)象.屬性
  • 調(diào)用方法:對(duì)象.方法()
class Person{
    String name ;       // 聲明姓名屬性
    int age ;           // 聲明年齡屬性
    public void tell(){ // 取得信息
        System.out.println("姓名:" + name + ",年齡:" + age) ;
    }
};
public class ClassDemo03{
    public static void main(String args[]){
        Person per = null ;     // 聲明對(duì)象
        per = new Person() ;    // 實(shí)例化對(duì)象
        per.name = "張三" ;       // 為姓名賦值
        per.age = 30 ;          // 為年齡賦值
        per.tell() ;            // 調(diào)用方法,打印信息
    }
};
輸出結(jié)果:
姓名:張三,年齡:30

此時(shí),內(nèi)容顯示出來(lái)后,實(shí)際上所有的操作都是要在內(nèi)存中直接體現(xiàn)出來(lái)的。

問(wèn)題
對(duì)象是保存在棧內(nèi)存之中的,屬性是保存在堆內(nèi)存之中的,那么方法呢?
在程序中,所有方法是保存在全局代碼區(qū)之中的。此區(qū)域中的內(nèi)容是共享的。
注意
在使用對(duì)象的時(shí)候,對(duì)象必須被實(shí)例化之后才可以使用(實(shí)例化對(duì)象,并不單單指的是通過(guò)new關(guān)鍵字實(shí)現(xiàn)的,只要有堆內(nèi)存的空間指向,則就表示實(shí)例化成功。)

如果不實(shí)例化會(huì)如何呢?

Exception in thread "main" java.lang.NullPointerException
                 at ClassDemo03 main(ClassDemo03.java:12)

此時(shí)出現(xiàn)了一個(gè)空指向異常。

在引用操作中,如果一個(gè)對(duì)象沒(méi)有堆內(nèi)存的引用,而調(diào)用了類(lèi)中的屬性或方法,就會(huì)出現(xiàn)此問(wèn)題。

那么既然可以產(chǎn)生一個(gè)對(duì)象,能不能產(chǎn)生多個(gè)對(duì)象呢?
可以,只要按照操作格式完成即可。

class Person{
    String name ;       // 聲明姓名屬性
    int age ;           // 聲明年齡屬性
    public void tell(){ // 取得信息
        System.out.println("姓名:" + name + ",年齡:" + age) ;
    }
};
public class ClassDemo04{
    public static void main(String args[]){
        Person per1 = null ;        // 聲明per1對(duì)象
        Person per2 = null ;        // 聲明per2對(duì)象
        per1 = new Person() ;       // 實(shí)例化per1對(duì)象
        per2 = new Person() ;       // 實(shí)例化per2對(duì)象
        per1.name = "張三" ;      // 設(shè)置per1中的name屬性?xún)?nèi)容
        per1.age = 30 ;             // 設(shè)置per1中的age屬性?xún)?nèi)容
        per2.name = "李四" ;      // 設(shè)置per2中的name屬性?xún)?nèi)容
        per2.age = 33 ;             // 設(shè)置per2中的age屬性?xún)?nèi)容
        System.out.print("per1對(duì)象中的內(nèi)容 --> ") ;
        per1.tell() ;               // 調(diào)用類(lèi)中的方法
        System.out.print("per2對(duì)象中的內(nèi)容 --> ") ;
        per2.tell() ;               // 調(diào)用類(lèi)中的方法
    }
};
輸出結(jié)果:
per1對(duì)象中的內(nèi)容 --> 姓名:張三,年齡:30
per2對(duì)象中的內(nèi)容 --> 姓名:李四,年齡:33

類(lèi)是引用數(shù)據(jù)類(lèi)型,那么這些是如何引用的呢?
所謂的引用數(shù)據(jù)類(lèi)型,實(shí)際上就是傳遞的就是是堆內(nèi)存的使用權(quán),可以同時(shí)為一個(gè)堆內(nèi)存空間定義多個(gè)棧內(nèi)存的引用操作 。

class Person{
    String name ;       // 聲明姓名屬性
    int age ;           // 聲明年齡屬性
    public void tell(){ // 取得信息
        System.out.println("姓名:" + name + ",年齡:" + age) ;
    }
};
public class ClassDemo05{
    public static void main(String args[]){
        Person per1 = null ;        // 聲明per1對(duì)象
        Person per2 = null ;        // 聲明per2對(duì)象
        per1 = new Person() ;       // 只實(shí)例化per1一個(gè)對(duì)象
        per2 = per1 ;               // 把per1的堆內(nèi)存空間使用權(quán)給per2
        per1.name = "張三" ;      // 設(shè)置per1中的name屬性?xún)?nèi)容
        per1.age = 30 ;             // 設(shè)置per1中的age屬性?xún)?nèi)容
        // 設(shè)置per2對(duì)象的內(nèi)容,實(shí)際上就是設(shè)置per1對(duì)象的內(nèi)容
        per2.age = 33 ;             // 設(shè)置per2中的age屬性?xún)?nèi)容
        System.out.print("per1對(duì)象中的內(nèi)容 --> ") ;
        per1.tell() ;               // 調(diào)用類(lèi)中的方法
        System.out.print("per2對(duì)象中的內(nèi)容 --> ") ;
        per2.tell() ;               // 調(diào)用類(lèi)中的方法
    }
};
輸出結(jié)果:
per1對(duì)象中的內(nèi)容 --> 姓名:張三,年齡:33
per2對(duì)象中的內(nèi)容 --> 姓名:張三,年齡:33

再看一道引用傳遞的程序。

class Person{
    String name ;       // 聲明姓名屬性
    int age ;           // 聲明年齡屬性
    public void tell(){ // 取得信息
        System.out.println("姓名:" + name + ",年齡:" + age) ;
    }
};
public class ClassDemo06{
    public static void main(String args[]){
        Person per1 = null ;        // 聲明per1對(duì)象
        Person per2 = null ;        // 聲明per2對(duì)象
        per1 = new Person() ;       // 實(shí)例化per1對(duì)象
        per2 = new Person() ;       // 實(shí)例化per2對(duì)象

        per1.name = "張三" ;      // 設(shè)置per1中的name屬性?xún)?nèi)容
        per1.age = 30 ;             // 設(shè)置per1中的age屬性?xún)?nèi)容
        per2.name = "李四" ;
        per2.age = 33 ;             // 設(shè)置per2中的age屬性?xún)?nèi)容

        per2 = per1 ;               // 把per1的堆內(nèi)存空間使用權(quán)給per2
        System.out.print("per1對(duì)象中的內(nèi)容 --> ") ;
        per1.tell() ;               // 調(diào)用類(lèi)中的方法
        System.out.print("per2對(duì)象中的內(nèi)容 --> ") ;
        per2.tell() ;               // 調(diào)用類(lèi)中的方法
    }
};
輸出結(jié)果:
per1對(duì)象中的內(nèi)容 --> 姓名:張三,年齡:30
per2對(duì)象中的內(nèi)容 --> 姓名:張三,年齡:30


因?yàn)閜er2改變了指向,所以其原本的內(nèi)存空間就沒(méi)有任何棧的引用,則這樣的內(nèi)存就被稱(chēng)為垃圾,等待著垃圾收集機(jī)制進(jìn)行回收。
GC垃圾收集機(jī)制的簡(jiǎn)稱(chēng)。

總結(jié)

1、掌握棧與堆內(nèi)存的關(guān)系
2、對(duì)象保存在棧內(nèi)存之中,而具體內(nèi)容保存在堆內(nèi)存之中
3、對(duì)象間的引用傳遞,實(shí)際上傳遞的就是堆內(nèi)存空間的使用權(quán)
4、垃圾的產(chǎn)生。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容