本質
面向對象編程(Object-Oriented Programming,OOP),本質就是以類的方式組織代碼,以對象的組織(封裝)數據。
面向過程是具體的、面向對象是抽象的。
抽象
三大特性: 封裝、繼承、多態
類和對象的關係
類是一種抽象的數據類型,它是對某一類事物整體描述/定義,但是並不能代表某一個具體的事物。
例: 動物、植物、手機…
Person類、Pet類、Cat類,這些類都是用來描述/定義某一類具體的事物應該具備的特點和行爲。
對象是抽象概念的具體實例。
例:李四就是人的一個具體實例,李四的狗狗jack就是Cat的一個具體實例
能夠體現出特點,展現出功能的是具體的實例,而不是抽象的概念
創建與初始化對象
使用new關鍵字創建對象
使用new關鍵字創建的時候,除了分配內存空間之外,還會給創建好的對象進行默認的初始化以及對類中構造器的調用。
類中的構造器也稱爲構造方法,是在進行創建對象的時候必須調用的。並且構造器有以下兩個特點:
- 必須和類的名字相同
- 必須沒有返回類型,也不能有void
構造器
- 使用new關鍵字,本質是調用構造器,必須使用構造器
- 用來初始化值
一旦定義了有參構造,如果想使用無參構造,必須顯示定義無參構造。
封裝
- 該露的露,該藏的藏
設計程序追求“高內聚、低耦合”。高內聚指的是類的內部數據操作細節自己完成,不允許外部干涉;低耦合指的是盡暴露少量的方法給外部使用。
-
封裝(數據的隱藏)
通常,應禁止直接訪問一個對象中數據的實際表示,而應通過操作接口來訪問,這成爲信息隱藏。
屬性私有(private),get/set
繼承
本質是對某一批類的抽象,從而實現對現實世界的更好建模。
extends的意思是“擴展”,子類是父類的擴展。
注意:Java只有單繼承,沒有多繼承。(一個兒子只能有一個爸爸,一個爸爸可以有多個兒子)
繼承是類於類之間的一種關係。除此之外,類與類之間的關係還有依賴、組合和聚合
繼承關係是兩個類。一個父類(基類),一個子類(派生類),子類繼承父類使用extends來表示
子類和父類之間,從意義上講應該是“is a“ 的關係
私有的父類屬性不能繼承。(可以通過get/set來實現繼承)
子類調用父類使用super
public class Stu extends Person{
private String name = "Halo";
public void test(String name){
//這裏的name是調用的test的形參name
System.out.println(name);
//這裏的name調用的Stu類中的私有屬性name
System.out.println(this.name);
//這裏的name調用的是父類的name屬性
System.out.println(super.name);
}
}
執行過程:子類的無參構造中有隱藏的super,所以調用父類的構造器,必須要在子類構造器的第一行。
super注意點
- super調用父類的構造方法,必須在構造方法的第一個
- super必須只能出現在子類的方法或者構造方法中
- super和this不能同時出現在構造方法中
super和this的區別
代表的對象不同:
- this:本身調用者這個對象
- super:代表父類對象的應用
前提:
- this:沒有繼承也可以用
- super:只能在繼承條件下才可以使用
構造方法:
- this(); 本類的構造
- super(); 父類的構造
方法的重寫
重寫都是方法的重寫,和屬性無關!@Override
靜態方法和非靜態方法區別非常大!
靜態方法:方法調用只和左邊定義的數據類型有關。
重寫之和非靜態有關係!
因爲靜態方法
class A extends B{
public static void test(){
system.out.println("A->test");
}
}
class B{
public static void test(){
system.out.println("B->test");
}
}
public static void main(String[] args){
A a = new A();
a.test(); //輸出A->test
B b = new A();
b.test(); //輸出B->test
}
class A extends B{
@Override
public void test(){
system.out.println("A->test");
}
}
class B{
public void test(){
system.out.println("B->test");
}
}
public static void main(String[] args){
A a = new A();
a.test(); //輸出A->test
B b = new A();
b.test(); //輸出A->test
}
重寫:需要有繼承的關係,子類重寫父類的方法!
- 方法名必須相同
- 參數列表必須相同
- 修飾符:範圍可以擴大但不能縮小: public-> protected -> default ->private
- 拋出的異常:範圍可以縮小,但不能擴大:ClassNotFoundException -> Exception
重寫:子類的方法和弗雷德必須一致,方法體不同!
Why需要重寫?
A:父類的功能,子類不一定需要或者不一定滿足!
多態
即同一個方法,可以根據發送對象的不同而採用不同的行爲方式。
一個對象的實際類型是確定的,但是可以指向對象的引用的類型有很多。
- 多態是方法的多態,屬性沒有多態!
- 父類和子類有聯繫, 沒有關係的會報出類型轉換異常!ClassCastException
- 存在的條件:
- 繼承關係
- 子類重寫父類的方法,以下方法不會被重寫:
- static 方法屬於類,不屬於實例
- final 常量
- private 方法
- 父類的引用指向子類 Father F = new Son();
static關鍵字
public class Person{
{
System.out.println("匿名代碼塊");
}
static{
System.out.println("靜態代碼塊");
}
public Person(){
System.out.println("構造方法");
}
public static void main(String[] args){
Person person = new Person();
}
}
執行結果:
靜態代碼塊
匿名代碼快
構造方法
public class Person{
//賦初始值
{
System.out.println("匿名代碼塊");
}
//只執行一次
static{
System.out.println("靜態代碼塊");
}
public Person(){
System.out.println("構造方法");
}
public static void main(String[] args){
Person person1 = new Person();
System.out.println("=============");
Person person2 = new Person();
}
}
執行結果:
靜態代碼塊
匿名代碼快
構造方法
==========
匿名代碼塊
構造方法
靜態導入包
當只導入包中指定的方法,可以使用static關鍵字。例:
import static java.lang.Math.random;
public class Test{
public static void main(String[] args){
System.out.println(random());
}
}
和下面的方式一樣
import static java.lang.Math;
public class Test{
public static void main(String[] args){
System.out.println(Math.random());
}
}
抽象類
是一種約束,有人能幫你實現。abstract,抽象方法,只有方法的名字,沒有方法的實現!
- 不能new這個抽象類,只能靠子類去實現它;約束!
- 抽象類中可以寫普通的方法
- 抽象方法必須在抽象類中
接口
普通類:只能有具體實現
抽象類:具體實現和規範(抽象方法)都有
接口:只是規範,自己無法寫方法~專業的抽象!約束和實現的分離:面向接口的編程(即可以實現多繼承)
聲明類的關鍵字是class,聲明接口的關鍵字是interface
接口就是規範,定義的是一組規則,體現了現實世界中“如果你是…則必須能…”的思想。如果你是貓,就必須會捉老鼠。
接口的本質是契約,就像我們人間的法律一樣。制定好後大家都遵守。
oo的精髓是對對象的抽象,最能體現這一點的就是接口,爲什麼我們討論設計模式都是隻針對具備了抽象能力的語言(比如c++,java,C#等),就是因爲設計模式所研究的,實際上就是如何合理的去抽象。
作用
- 約束
- 定義一些方法,讓不同的人實現
- 方法默認都是public abstract
- 常量默認都是public static final
- 接口不能實例化,接口中沒有構造方法
- implements可以實現多個接口
- 必須重寫接口中的方法
內部類
內部類就是在一個類的內部定義一個類,比如,A類中定義一個B類,那麼B類相對於A類來說就是稱爲內部類,而A類相對B類磊說就是外部類。
- 成員內部類
- 靜態內部類
- 局部內部類
- 匿名內部類
成員內部類
通過這個外部類來實例化內部類
public class Outer{
public class Inner{
public void in(){
System.out.println("這是內部類方法");
}
}
}
public class Test{
public static void mian(String[] args){
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.in();
}
}
獲取外部內的私有屬性
public class Outer{
private int age=10;
public class Inner{
public void in(){
System.out.println("這是內部類方法");
}
public void getAge(){
System.out.println(age);
}
}
}
局部內部類
public class Outer{
public void method(){
//在方法中在構建類
class Inner{
}
}
}
異常機制
五個關鍵字:
try
catch
finally
throw
throws
throw 是語句拋出一個異常;throws 是方法拋出一個異常;
- throw語法:throw <異常對象>
在方法聲明中,添加throws子句表示該方法將拋出異常。 - throws語法:[<修飾符>]<返回值類型><方法名>([<參數列表>])[throws<異常類>]
【其中:異常類可以聲明多個,用逗號分割。】
- 處理運行時異常,採用邏輯去合理規避同時輔助try-catch處理
- 在多重catch塊後面,可以加一個catch(Exception)來處理可能會被遺漏的異常
- 對於不確定的代碼,也可以加上try-catch,處理潛在的異常
- 儘量去處理異常,切忌只是簡單的調用printStackTrace()去打印輸出
- 具體如何處理異常,要根據不同的業務需求和異常類型去決定
- 儘量添加finally語句去釋放佔用的資源