九.面向物件的思想(五)
九.面向物件的思想(五)
1.程式碼塊
程式碼塊又稱為初始化塊,屬於類中的成員(即 是類的一部分),類似於方法,將邏輯語句封裝在方法體中,通過{}包圍起來。
但和方法不同,沒有方法名,沒有返回,沒有引數,只有方法體,而且不用通過物件或類的顯式呼叫,而是載入類時,或建立物件時隱 式呼叫。
程式碼塊語法
【修飾符】{
程式碼
};
說明注意:
1)修飾符可選,要寫的話,也只能寫static
2)程式碼塊分為兩類,使用static修飾的叫靜態程式碼塊,沒有static修飾的,叫普通程式碼塊/非靜態程式碼塊。
3)邏輯語句可以任何邏輯語句(輸入,輸出,方法呼叫,迴圈,判斷等)
4);號可以寫上,也可以忽略
程式碼塊的好處:
1)相當於另外一種形式的構造器(對構造器的補充機制),可以做初始化操作
2)場景:如果多個構造器中都有重複的語句,可以抽取到程式碼塊中,提高程式碼的重用性。
使用注意事項
1)static程式碼塊也叫靜態程式碼塊,作用就是對類進行初始化,而且它隨著類的載入而執行,並且只會執行一次。如果是普通程式碼塊,沒建立一個物件,就執行。
2)類什麼時候被載入
1.建立物件例項時
2.建立物件的子類物件例項,父類也會被載入
3.使用類的靜態成員時(靜態屬性,靜態方法)
3)普通的程式碼塊,在建立物件例項時,會被隱式的呼叫。
被建立以西,就會呼叫一次。
如果只是是喲了那個類的靜態成員時,普通程式碼塊並不會執行
建立一個子類物件時,他們的靜態程式碼塊,靜態程式碼塊,普通程式碼塊,普通屬性初始化,構造方法的呼叫順序
1.父類的靜態程式碼塊和靜態屬性(優先順序一樣,按定義順序執行)
2.子類的靜態程式碼塊和靜態屬性(優先順序一樣,定義順序執行)
3.父類的普通程式碼塊和普通屬性初始化(優先順序一樣,按定義順序執行)
4.父類的構造方法
5.子列的普通程式碼塊和普通屬性初始化(優先順序一樣,按定義順序執行)
5.子類的構造方法
2.單例設計模式
1.單例設計模式,就是採取一定的方法保證整個的軟體系統中,對某個類只能存在一個物件的例項,並且該列只提供一個取得其物件例項的方法
2.單例設計模式有兩種方式:1)餓漢式 2)懶漢式
單例設計模式的兩種實現方式:
一、懶漢式:隨著類的載入在記憶體中物件為null,當呼叫 getInstance 方法時才建立物件(延遲載入)
二、餓漢式:隨著類的載入直接建立物件(推薦開發中使用)
單例設計模式的實現步驟:
1.保證一個類只有一個例項,實現方式:構造方法私有化
2.必須要自己建立這個例項,實現方式:在本類中維護一個本類物件(私有,靜態)
3.必須向整個程式提供這個例項,實現方式:對外提供公共的訪問方式(getInstance方法,靜態)
懶漢式實現如下:
class Single{
private Single(){}
private static Single s1 = null;
public static Single getInstance(){
if(s1 == null){
s1 = new Single();
}
return s1;
}
}
餓漢式實現如下:
class Single2{
private Single2(){}
private static Single2 s = new Single2();
public static Single getInstance(){
return s;
}
}
餓漢式和懶漢式的區別
1).二者最主要的區別子啊與建立物件的時機不同:餓漢式是在類載入就建立了物件例項,而懶漢式是在使用時才建立。
2)餓漢式不存線上程安全問題,懶漢式竄線上程安全問題。
3)餓漢式存在浪費資源的可能,懶漢式是使用才建立,就不存在這個問題。
3.final關鍵字
final可以修飾類,屬性,方法和區域性變數。
使用情況
在某些情況下,程式設計師可能有以下需求,就會使用到final:
1)當不希望類被繼承時,可以使用final修飾。
2)當不希望父類的某個方法被子類覆蓋/重寫(override)時,可以用final關鍵字修飾。
3)當不希望類的某個屬性的值被修改時,可以用final關鍵字修飾。
4)當不希望某個區域性變數被修改,可以使用final修飾。
final使用的注意事項
1)final修飾的屬性又叫常量,一般用大寫字母和下劃線來命名
2)final修飾的屬性在定義是,必須賦初始值,並且以後不能再修改,賦值可以在以下位置之一:
1.定義是:如public final double TAX_RATE=0.08;
2.在構造器中
3.在程式碼塊中
3)如果final修飾的屬性是靜態的,則初始化的位置只能是
1.定義時
2.在靜態程式碼塊中,不能在構造器中賦值。
4)final類不能繼承,但是可以例項化物件
5)如果類不是final類,但是含有final方法,則該方法雖然不能重寫,但是可以被繼承。
6)一般來說,如果一個類已經是final類了,就沒有比喻哦啊再將方法修飾成finall
7)final和static往往搭配使用,效率更高,不會導致類載入底層編譯器做了優化處理。
8)包裝類(Integer,Double,Float,Boolean等都是final),String也是final類。
4.抽象類
當父類的某些方法,需要宣告,但是又不能確定如何實現時,可以將其宣告為抽象方法,那麼這個類就是抽象類
public class Abstract01 {
public static void main(String[] args) {
}
}
abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
//思考:這裡 eat 這裡你實現了,其實沒有什麼意義
//即: 父類方法不確定性的問題
//===> 考慮將該方法設計為抽象(abstract)方法
//===> 所謂抽象方法就是沒有實現的方法
//===> 所謂沒有實現就是指,沒有方法體
//===> 當一個類中存在抽象方法時,需要將該類宣告為 abstract 類
//===> 一般來說,抽象類會被繼承,有其子類來實現抽象方法. // public void eat() {
// System.out.println("這是一個動物,但是不知道吃什麼..");
// }
public abstract void eat() ;
}
抽象類的介紹
1)用abstract關鍵字來修飾一個類時,這個類就叫抽象類
訪問修飾符 abstract 類名{
}
2)用abstract關鍵字來修飾一個方法時,這個方法就是抽象方法
訪問修飾符 abstract 返回型別 方法名(引數列表);//沒有方法體
3)抽象類的價值更多作用在於設計,是設計者設計好後,讓子類繼承並實現抽象類()
抽象類的使用注意事項
1)抽象類不能被例項化
2)抽象類不一定要包括abstract方法。也就是說,抽象類可以沒有abstarct方法
3)一旦類包含了abstract方法,則這個類必須宣告為abstract
4)abstract只能修飾類和方法,不能修飾屬性和其他的。
5)抽象類可以有任意成員【抽象類本質還是類】,比如:非抽象方法,構造器,靜態屬性等等
6)抽象方法不能有主體,即不能實現。
7)如果一個類繼承了抽象類,則它必須實現抽象類的所有抽象方法,除非它自己也宣告為abstract類。
8)抽象方法不能使用private,final和static來修飾,因為這些關鍵字都是和重寫相違背的。
5.介面
基本介紹
介面解釋給出一些沒有實現的方法,封裝到一起,到某個類要使用的時候,在根據具體情況把這些方法寫出來。
語法:
• interface 介面名{
• //屬性
• //抽象方法
• }
• class 類名 implements 介面 {
• 自己的屬性;
• 自己的方法;
• 必須實現的介面的抽象方法
• }
介面是更加抽象的類,抽象類裡的方法可以有方法體,接口裡的所有方法都沒有方法體。介面體現了程式的多型和高內聚低耦合的設計思想。
public interface DBInterface { //專案經理
public void connect();//連線方法
public void close();//關閉連線
}
//A 程式
public class MysqlDB implements DBInterface {
@Override
public void connect() {
System.out.println("連線 mysql")
}
@Override
public void close() {
System.out.println("關閉 mysql");
}
}
//B 程式設計師連線 Oracle
public class OracleDB implements DBInterface{
@Override
public void connect() {
System.out.println("連線 oracle");
}
@Override
public void close() {
System.out.println("關閉 oracle");
}
}
public class Interface03 {
public static void main(String[] args) {
MysqlDB mysqlDB = new MysqlDB();
t(mysqlDB);
OracleDB oracleDB = new OracleDB();
t(oracleDB);
}
public static void t(DBInterface db) {
db.connect();
db.close();
}
}
介面使用的注意事項:
1)介面不能被例項化
2)介面中所有的方法是public方法,介面中抽象方法,可以不用abstract修飾;
3)一個普通類實現介面,就必須將該介面的所有方法都實現。
4)抽象類實現介面,可以不用實現介面的方法。
5)一個類同時可以實現多個介面
6)介面中的屬性,只能是final的,而且是public static final修飾符。
7)介面中屬性的訪問形式:介面名.屬性名
8)介面不能繼承其他的類,但可以繼承多個別的介面
interface A extends B,C{}
9)介面的修飾符只能是public和預設,這點和類的修飾符是一樣的。
6.內部類
如果定義類在區域性位置(方法或程式碼塊):(1)區域性內部類 (2)匿名內部類
定義在成員位置:(1)成員內部類 (2)靜態內部類
基本介紹:
一個類的內部又完整的嵌套了另一個類的結構。被巢狀的類稱為內部類,巢狀其他類的類稱為外部類。是我們類的第五大成員【類的五大成員:屬性,方法,構造器,程式碼塊,內部類】,內部類最大的特點解釋可以直接訪問私有屬性,並且可以體現類與類之間的包含關係。
基本語法:
class Outer{ //外部類
class Inner{ //內部類
}
}
class Other{ //外部其他類
}
內部類的分類
定義在外部類區域性位置上(比如方法內):
1)區域性內部類(有類名)
2)匿名內部類(沒有類名)
定義在外部類的成員位置上
1)成員內部類(沒用static修飾)
2)靜態內部類(使用static修飾)
區域性內部類
區域性內部類是定義在外部類的區域性位置,比如方法中,並且有類名。
1.可以直接訪問外部類的所有成員,包括私有的。
2.不能新增訪問修飾符,因為它的地位就是一個區域性變數。區域性變數是不能使用修飾符的。但是可以使用final修飾,因為區域性變數也可以使用final
3.作用域:僅僅是在定義它的方法或程式碼塊中。
4.外部類訪問區域性內部類的成員需要在作用域內,建立物件再訪問。
5.如果外部類和區域性內部類的成員重名時,預設遵循就近原則,如果想訪問外部類的成員,則可以使用(外部類名.this.成員)去訪問。
public class LocalInnerClass {//
public static void main(String[] args) {
//演示一遍
Outer02 outer02 = new Outer02();
outer02.m1();
System.out.println("outer02 的 hashcode=" + outer02);
}
}
class Outer02 {//外部類
private int n1 = 100;
private void m2() {
System.out.println("Outer02 m2()");
}//私有方法
public void m1() {//方法
//1.區域性內部類是定義在外部類的區域性位置,通常在方法
//3.不能新增訪問修飾符,但是可以使用 final 修飾
//4.作用域 : 僅僅在定義它的方法或程式碼塊中
final class Inner02 {//區域性內部類(本質仍然是一個類)
//2.可以直接訪問外部類的所有成員,包含私有的
private int n1 = 800;
public void f1() {
//5. 區域性內部類可以直接訪問外部類的成員,比如下面 外部類 n1 和 m2()
//7. 如果外部類和區域性內部類的成員重名時,預設遵循就近原則,如果想訪問外部類的成員,
// 使用 外部類名.this.成員)去訪問
// Outer02.this 本質就是外部類的物件, 即哪個物件呼叫了 m1, Outer02.this 就是哪個物件
System.out.println("n1=" + n1 + " 外部類的 n1=" + Outer02.this.n1);
System.out.println("Outer02.this hashcode=" + Outer02.this);
m2();
}
}
//6. 外部類在方法中,可以建立 Inner02 物件,然後呼叫方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
}
}
匿名內部類:
(1)本質是類 (2)內部類(3)該類沒有名字(4)同時還是一個物件
說明:匿名內部類是定義在外部類的區域性位置,比如方法中,並且沒有類名
基本語法:
new 類或介面(引數列表){
• 類體
};
/**
* 演示匿名內部類的使用
*/
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
class Outer04 { //外部類
private int n1 = 10;//屬性
public void method() {//方法
//基於介面的匿名內部類
//老韓解讀
//1.需求: 想使用 IA 介面,並建立物件
//2.傳統方式,是寫一個類,實現該介面,並建立物件
//3.需求是 Tiger/Dog 類只是使用一次,後面再不使用
//4. 可以使用匿名內部類來簡化開發
//5. tiger 的編譯型別 ? IA
//6. tiger 的執行型別 ? 就是匿名內部類 Outer04$1
/*
我們看底層 會分配 類名 Outer04$1
class Outer04$1 implements IA {
@Override
public void cry() {
System.out.println("老虎叫喚...");
}
}
*/
//7. jdk 底層在建立匿名內部類 Outer04$1,立即馬上就建立了 Outer04$1 例項,並且把地址
// 返回給 tiger
//8. 匿名內部類使用一次,就不能再使用
IA tiger = new IA() {