Java類和對象 詳解(一)

一、面向對象簡述

面向對象是一種現在最爲流行的程序設計方法,幾乎現在的所有應用都以面向對象爲主了,最早的面向對象的概念實際上是由IBM提出的,在70年代的Smaltalk語言之中進行了應用,後來根據面向對象的設計思路,才形成C++,而由C++產生了Java這門面向對象的編程語言。

但是在面向對象設計之前,廣泛採用的是面向過程,面向過程只是針對於自己來解決問題。面向過程的操作是以程序的基本功能實現爲主,實現之後就完成了,也不考慮修改的可能性,面向對象,更多的是要進行子模塊化的設計,每一個模塊都需要單獨存在,並且可以被重複利用,所以,面向對象的開發更像是一個具備標準的開發模式。

在面向對象定義之中,也規定了一些基本的特徵:
(1)封裝:保護內部的操作不被破壞;
(2)繼承:在原本的基礎之上繼續進行擴充;
(3)多態:在一個指定的範圍之內進行概念的轉換。

對於面向對象的開發來講也分爲三個過程:OOA(面向對象分析)、OOD(面向對象設計)、OOP(面向對象編程)。

二、類與對象的基本概念

類與對象時整個面向對象中最基礎的組成單元。

:是抽象的概念集合,表示的是一個共性的產物,類之中定義的是屬性和行爲(方法);
對象:對象是一種個性的表示,表示一個獨立的個體,每個對象擁有自己獨立的屬性,依靠屬性來區分不同對象。

可以一句話來總結出類和對象的區別:類是對象的模板,對象是類的實例。類只有通過對象纔可以使用,而在開發之中應該先產生類,之後再產生對象。類不能直接使用,對象是可以直接使用的。

三、類與對象的定義和使用

在Java中定義類,使用關鍵字class完成。語法如下:

class 類名稱 {
         屬性 (變量) ;
         行爲 (方法) ;
}

範例:定義一個Person類

class Person {     // 類名稱首字母大寫
    String name ;
    int age ;
    public void tell() {        // 沒有static
          System.out.println("姓名:" + name + ",年齡:" + age) ;
         }
}

類定義完成之後,肯定無法直接使用。如果要使用,必須依靠對象,那麼由於類屬於引用數據類型,所以對象的產生格式(兩種格式)如下:

(1)格式一:聲明並實例化對象

類名稱 對象名稱 = new 類名稱 () ;

(2)格式二:先聲明對象,然後實例化對象:

類名稱 對象名稱 = null ;
對象名稱 = new 類名稱 () ;

引用數據類型與基本數據類型最大的不同在於:引用數據類型需要內存的分配和使用。所以,關鍵字new的主要功能就是分配內存空間,也就是說,只要使用引用數據類型,就要使用關鍵字new來分配內存空間。

當一個實例化對象產生之後,可以按照如下的方式進行類的操作:
對象.屬性:表示調用類之中的屬性;
對象.方法():表示調用類之中的方法。

範例:使用對象操作類

package com.wz.classandobj;

class Person { 
    String name ;
    int age ;
    public void get() {
        System.out.println("姓名:" + name + ",年齡:" + age);
    }
}

public class TestDemo {
        public static void main(String args[]) {
            Person per = new Person() ;// 聲明並實例化對象
            per.name = "張三" ;//操作屬性內容
            per.age = 30 ;//操作屬性內容
            per.get() ;//調用類中的get()方法
        }
}

運行結果:

姓名:張三,年齡:30

以上完成了一個類和對象的操作關係,下面換另外一個操作來觀察一下:

package com.wz.classandobj;

class Person { 
    String name ;
    int age ;
    public void get() {
        System.out.println("姓名:" + name + ",年齡:" + age);
    }
}

public class TestDemo {
        public static void main(String args[]) {
            Person per = null;//聲明對象
            per = new Person() ;//實例化對象
            per.name = "張三" ;//操作屬性內容
            per.age = 30 ;//操作屬性內容
            per.get() ;//調用類中的get()方法
        }
}

運行結果:

姓名:張三,年齡:30

那麼,問題來了,以上兩種不同的實例化方式有什麼區別呢?
我們從內存的角度分析。首先,給出兩種內存空間的概念:
(1)堆內存:保存對象的屬性內容。堆內存需要用new關鍵字來分配空間;
(2)棧內存:保存的是堆內存的地址(在這裏爲了分析方便,可以簡單理解爲棧內存保存的是對象的名字)。

1

任何情況下,只要看見關鍵字new,都表示要分配新的堆內存空間,一旦堆內存空間分配了,裏面就會有類中定義的屬性,並且屬性內容都是其對應數據類型的默認值。

於是,上面兩種對象實例化對象方式內存表示如下:
這裏寫圖片描述

兩種方式的區別在於①②,第一種聲明並實例化的方式實際就是①②組合在一起,而第二種先聲明然後實例化是把①和②分步驟來。

另外,如果使用了沒有實例化的對象,結果如何?
如下:

package com.wz.classandobj;

class Person { 
    String name ;
    int age ;
    public void get() {
        System.out.println("姓名:" + name + ",年齡:" + age);
    }
}

public class TestDemo {
        public static void main(String args[]) {
            Person per = null;//聲明對象
            //per = new Person() ;//實例化對象
            per.name = "張三" ;//操作屬性內容
            per.age = 30 ;//操作屬性內容
            per.get() ;//調用類中的get()方法
        }
}

運行結果:

Exception in thread "main" java.lang.NullPointerException
    at com.wz.classandobj.TestDemo.main(TestDemo.java:15)

此時,程序只聲明瞭Person對象,但並沒有實例化Person對象(只有了棧內存,並沒有對應的堆內存空間),則程序在編譯的時候不會出現任何的錯誤,但是在執行的時候出現了上面的錯誤信息。這個錯誤信息表示的是“NullPointerException(空指向異常)”,這種異常只要是應用數據類型都有可能出現。

四、對象引用傳遞初步分析

引用傳遞的精髓:同一塊堆內存空間,可以同時被多個棧內存所指向,不同的棧可以修改同一塊堆內存的內容。

下面通過若干個程序,以及程序的內存分配圖,來進行代碼的講解。

我們來看一個範例:

class Person {     
         String name ;
         int age ;
         public void tell() {        
                   System.out.println("姓名:" + name + ",年齡:" + age) ;
         }
}
public class TestDemo {
         public static void main(String args[]) {
                   Person per1 = new Person() ;         // 聲明並實例化對象
                   per1.name = "張三" ;
                   per1.age = 20 ;
                   Person per2 = per1 ;  // 引用傳遞
                   per2.name = "李四" ;
                   per1.tell() ;
         }
}

對應的內存分配圖如下:

11

再來看另外一個:

class Person {
         String name ;
         int age ;
         public void tell() {
                   System.out.println("姓名:" + name + ",年齡:" + age) ;
         }
}
public class TestDemo {
         public static void main(String args[]) {
                   Person per1 = new Person() ;         // 聲明並實例化對象
                   Person per2 = new Person() ;
                   per1.name = "張三" ;
                   per1.age = 20 ;
                   per2.name = "李四" ;
                   per2.age = 30 ;
                   per2 = per1 ;// 引用傳遞
                   per2.name = "王五" ;
                   per1.tell() ;
         }
}

對應的內存分配圖如下:
12

垃圾:指的是在程序開發之中沒有任何對象所指向的一塊堆內存空間,這塊空間就成爲垃圾,所有的垃圾將等待GC(垃圾收集器)不定期的進行回收與空間的釋放。

未完待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章