1. 程式人生 > >Java類和物件 詳解(一)

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(垃圾收集器)不定期的進行回收與空間的釋放。

未完待續。。。