1. 程式人生 > >JAVA面向物件知識點詳解

JAVA面向物件知識點詳解

一、類和物件

類:類是對物件的一種抽象描述,也就是說,類其實就是定義物件的一個模板,在這個模板裡面充分描述了物件所具有的屬性和行為(方法)
 
物件:通過類具體創建出來的實體,就是物件,這些物件是可以拿來使用的,一個類可以創建出任意個相同的物件(也就是一對多關係)
 
所以,在編寫程式碼時,必須先編寫類(Class),然後通過這個Class來建立物件,建立物件使用new關鍵字(例如:People p = new People())

二、類載入器和載入過程

我們都知道,當我們編寫完一個類以後,需要通過javac編譯成成對應的class位元組碼檔案(也就是將java原始檔編譯成二進位制的位元組碼檔案)
 
概念:
當執行一個Java程式的時候,JVM(Java虛擬機器)首先要做的事情就是類載入。類載入是通過類載入器(ClassLoader)來完成的。當類載入載入完class檔案以後,會對這個class檔案建立一個Class物件。Class物件就是在記憶體中隊位元組碼檔案的一個具體描述,以後建立的所有例項,都是由這個Class物件來建立的,每一個class檔案對應著一個Class物件,這個Class物件是有JVM建立的。
 
1)Java中的類載入器主要分為三類:
     BootClassLoader(啟動類載入器,主要是用於載入JRE\lib資料夾下的jar檔案,其中有一個是rt.jar包,這個jar包含了JDK的核心類庫。這個類載入器是使用C++語言編寫的,所以在Java程式中不能直接使用它,因此這個類載入器是由JVM在啟動時建立來使用的。) 
    
    ExtClassLoader(擴充套件類載入器,它主要用於載入jre\lib\ext目錄下的jar檔案,這個目錄下是jre的擴充套件類庫)

     AppClassLoader(系統類載入器,它主要用於載入classpath下的class檔案以及jar包,通常我們自己編寫的類都是由這個載入器來完成的)

2)這三個類載入器的載入順序:
在載入一個class的時候,是基於雙親委模型來載入的,
AppClassLoader首先會呼叫ExtClassLoader來載入,ExtClassLoader又會委託給BootClassLoader來載入,
當父類載入器不能載入該class的時候,又會讓其子類來載入,
當所有載入器都不能載入這個class檔案時,就會引發一個ClassNotFoundException異常,表示無法找到該類檔案。

三、JVM的記憶體分配

JVM在執行時將記憶體分為三大塊:
1).棧
棧是遵循先進後出的原則(先入棧的變數最後才出棧)。
區域性變數都是在棧中分配的,如果變數是基本資料型別,那麼這個變數的值一併存放在棧中。如果是引用資料型別,那麼在棧中存放的只是一個引用地址,這個地址是指向堆中的物件首地址。
 
2).堆
只要通過new關鍵字創建出來的物件,都會分配到堆中,每個物件在堆中都會有一個唯一的地址,這個地址可以被棧中的變數所引用。
堆中的物件通常存放例項變數,例項變數是隨著物件的建立而建立,也隨著物件的銷燬而銷燬,每個例項都有自己的例項變數,他們之間是互不影響的,不會產生共享。
(注意:在引數傳遞的過程中,如果引數的型別是基本資料型別,那麼傳遞過去的就是基本資料型別的值,如果引數的型別是引用資料型別,那麼傳遞過去的是一個引用地址的值,這個引用地址同樣是指向堆中的同一個物件)
關於垃圾貨收:當堆中的任何一個物件沒有引用指向它的時候,這個物件就被視為垃圾物件,JVM會在定期去自動回收它,並釋放記憶體。
 
3).方法區
方法區中通常用於存放類載入的class資訊(欄位資訊,方法資訊,類的資訊,介面資訊,還包括靜態變數,以及常量等等)當這些資訊載入到方法區後,jvm就會根據這些資訊構建一個Class物件

四、封裝、繼承、多型

1、封裝:
隱藏內部的細節,對外提供某種訪問的方式。通常實現封裝的手段我們都會使用訪問修飾符。
包的封裝,控制當前包中的哪些類可以被其他包中的類去訪問
通常我們在定義一個class的時候都會使用訪問修飾符public。(注意:class只能使用public或者是預設的,也就是不需要任何訪問修飾符),沒有使用public修飾的類,只能被本包中其他類去訪問,不能被其他包中的類去訪問
類成員的封裝,將屬性和行為封裝在一個類中,並且也可以通過訪問修飾符來控制他們的訪問許可權
行為本身也具備封裝的特性,把實現的細節隱藏,對於呼叫者而言,內部的實現是透明的。
 
 
2、繼承:
繼承是一種父與子的關係,繼承的好處在於將子類共性的東西提取到父類中,讓子類做更少的事情,因此達到程式碼的複用性,這樣使整個結構更加清晰。(繼承是一種is a的關係)
 Java中只能是單繼承的關係,也就是一個子類只能有一個父類,但是一個父類有多個子類的。
在java中所有類的預設父類都是Object。
在繼承的時候,使用extends關鍵字。
 
3、多型:
一個物件具有多種形態的表現,多型的前提是必須有繼承。因為在不同場合或者業務場景中,子類是可以替代父類來完成具體的某件事情。
1)引用多型
     父類的引用型別,子類的物件
2)行為上的多型
     通常在子類中會重寫父類的方法,來完成具體的功能。
編譯時看父類,執行時看子類(編譯的時候看下父類有沒有定義這個方法,執行時看子類有沒有重寫這個方法,如果子類重寫,則優先呼叫子類重寫的方法,如果沒有重寫,則呼叫繼承父類而來的方法)
 
4、關於重寫和過載的區別
1)過載,方法名相同,引數的個數和型別不同,對返回值不要求,這就是過載,過載既可以發生在本當中,也可以發生在父類和子類當中。構造方法也是可以過載的。
2)重寫(覆蓋),方法名相同,引數的個數和型別也必須相同,返回值也必須相同。重寫只能發生在父類和子類當中。


五、抽象類和介面

1、抽象類:
當一個類不能具體去描述一個物件的時候,我們就認為它是抽象的。因此抽象類是不能用來建立例項來使用的,主要用來被繼承。
1)抽象類可以有自己的構造方法
2)抽象類可以有具體的方法
3)抽象類可以有抽象方法,必須使用abstract關鍵字修飾,這個方法必須由子類來實現。
4)抽象類不能使用new關鍵字來建立例項
5)定義抽象類必須使用abstract關鍵字宣告
6)當一個類中只要有一個抽象方法,這個類就必須是抽象類
7)抽象類可以定義例項變數和靜態變數以及常量 
8)抽象類可以再繼承抽象類,也可以繼承普通的類
 
2、介面:
介面是比抽象類更為抽象的一個元件,它主要是用於定義行為的標準。因此介面是用來被實現的,使用implements關鍵字。
1)介面只能定義常量
2)介面只能定義抽象方法
3)介面只能繼承介面,不能繼承普通的類和抽象類
4)介面是沒有構造方法的
 
3、注意:
1)在介面中定義常量時,可以不用final static修飾,因為編譯器在編譯時會自動加上。
2)在介面中定義抽象方法時可以省略abstract關鍵字,編譯器在編譯時同樣會加上。
當然了,面向物件還遠遠不止這些,上面的只是最最基本的知識點總結了一下,後續還會補充。。。希望各位大牛們補充