說明 繼面向對象 之一 續寫
12,面向對象的初始化過程
看代碼分析
public class Person {
private String name="zhangsan";
private int age;
private static String country = "cn";
{
System.out.println("name"+name+"age:"+age);
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void speak() {
System.out.println(this.name + ".." + this.age);
}
public static void showCountry() {
System.out.println("country=" + country);
}
}
Person p=new Person("zhang",20);
該句話都做了什麼事情?
1,因爲new 用到了Person.class所以會先找到Person.class文件並加載到內存中。
2,會執行該類中的靜態代碼塊,如果有的話,給Person.class類進行初始化
3,在堆內存中開闢空間,分配內存地址。
4,在堆內存中建立對象的特有屬性。並進行默認初始化。
5,對屬性進行顯示初始化
6,對對象進行構造代碼塊初始化
7,對對象進行對應的構造函數初始化
8,將內存地址賦給棧內存的p變量
13,單例設計模式
設計模式:解決某一類問題最行之有效的方法
java中23種設計模式
單例設計模式:解決一個類在內存中只存在一個對象
想要保證對象唯一
1,爲了避免其他程序過多建立該類對象。先禁止其他程序建立該類對象
2,還爲了讓其他程序可以訪問該類對象,只好定義在本類中,自定義一個對象
3,爲了方便其他程序對自定義對象的訪問,可以對外提供一些訪問方式。
這三部怎麼用代碼體現呢?
1,將構造函數私有化。
2,在類中創建一個本類對象。
3,提供一個方法可以獲取到該對象。
先初始化 :餓漢式 先初始化對象。
public class Single {
private Single() {
}
private static Single s = new Single();
public static Single getInstance() {
return s;
}
}
class SingleDemo {
public static void main(String[] args) {
Single.getInstance();
}
}
對於事物該怎麼描述,還怎麼描述
當需要將該事物的對象保證在內存中的唯一時,或將以上的三步加上即可
懶漢式
/*
* 對象是方法被調用時,才初始化,也叫做對象的演示加載。稱爲懶漢式。
* 稱爲:餓漢式
* Single類金內存 ,對象還沒有存在,只有調用了getInstance(),才建立對象
*/
public class Single {
private Single() {
}
private static Single s = null;
/**
* 加同步鎖 效率變低
*
* @return
*/
public static synchronized Single getInstance() {
/*
* if(s==null){ s=new Single(); } return s;
*/
// 雙重判斷,但是代碼變多了,餓漢式 是最好用的,而且是沒有問題的。
// 原則,定義單例時候,使用餓漢式
if (s == null) {
synchronized (Single.class) {
if (s == null) {
s = new Single();
}
}
}
return s;
}
}
class SingleDemo {
public static void main(String[] args) {
Single.getInstance();
}
}
14,面向對象 繼承
繼承:
1,提高了代碼的複用性。
2,讓類與類之間產生了關係,有了這個關係,纔有了多態的特性。
注意:千萬不要爲了獲取其他類的功能。簡化代碼而繼承。
必須是類與類之間有所屬關係纔可以繼承。所屬關係 is a.
父類的由來是子類不斷的向上抽取而來。
java語言中,java只支持單繼承,不支持多繼承。
因爲多繼承容易帶來安全隱患:當父類中定義了相同內容時,當功能內容不同時,子類不確定要運行哪一個。
但是java保留了這種機制,並用另一種體現形式來完成表示。多實現。
java支持多層繼承。也就是一個繼承體系
如何實現一個繼承體系中的功能呢?
想要使用體系中,先查閱體系中父類的描述。因爲父類中定義的是該體系中的共性內容。
通過了解共性功能,就可以知道該體系的基本功能。
那麼這個體系已經可以基本使用了。具體調用時,要創建最子類的對象,爲什麼呢?一是因爲有可能父類不能創建對象。
二是創建子類對象可以使用更多的功能,包括基本的也包括特有的。
簡單一句話就是:查閱父類功能,創建子類對象使用功能。
補充:
類與類之間的關係,對象與對象的關係。
聚集:has a
聚合:一員。球員和球隊。
組合:事物的聯繫程度更緊密。手是身體的一部分。
子父類中變量的特點:
如果子類中出現非私有的同名成員變量時,
子類訪問本類中的變量,用this
子類要訪問父類中的同名變量,用super.
super的使用和this使用幾乎一致。
this代表本類對象的引用
super是父類的對象引用。
子父類中函數的特點:
當子類出現和父類一模一樣的函數時,當子類對象調用該函數時,會運行子類函數的內容。
如同父類函數的函數被覆蓋一樣。 這種情況是函數的另一個特性:重寫(覆蓋)
當子類繼承父類,沿襲了父類的功能,到子類中,
但是子類雖具備該功能,但是功能的內容卻和父類不一致,
這時,沒有必要定義新功能,而是使用覆蓋,保留父類的功能定義,並重寫功能內容,
覆蓋:
1,子類覆蓋父類,必須保證子類權限大於等於父類權限,纔可以覆蓋,否則編譯失敗。
2,靜態只能覆蓋靜態。
記住:
重載:只看同名函數的參數列表。
重寫:字符類方法要一模一樣。包括返回值類型。
子父類的構造函數的特點
在對子類對象進行初始化時,父類的構造函數也會運行,
那是因爲子類的構造函數默認第一行有一天隱式的語句super();
super():會訪問父類中空參數的構造函數,而且子類中所有的構造函數默認第一行都是super();0
爲什麼子類一定要訪問父類中的構造函數。
因爲父類中的數據子類可以直接獲取,所以子類對象在建立時,需要查看父類是如何對這些數據進行初始化的。
所以子類在對象初始化時,要訪問以下父類中的構造函數
如果要訪問父類中指定的構造函數,可以通過手動定義super語句的方式來指定。
注意:super語句一定定義在子類構造函數的第一行。
子類的實例化過程:
結論:
子類的所有構造函數,默認都會訪問父類中空參數的構造函數。
因爲子類每一個構造函數內的第一行都有一句隱事super();
當父類中沒有空參數的構造函數時,子類必須手動通過super或者this語句形式來指定要訪問的構造函數
當然,子類的構造函數第一行也可以手動指定this語句來訪問本類中的構造函數。子類中至少會有一個構造函數會訪問父類中的構造函數
15,final
final:最終。作爲一個修飾符,
1,可以修飾類,函數,變量。
2,被final修飾的類不可以被繼承。爲了避免被繼承,被子類複寫功能。
3,被final修飾的方法不可以被複寫。
4,final修飾的變量是一個常量只能賦值一次,即可以修飾成員變量,又可以修飾局部變量。
當在描述數據時,一些數據出值是固定的,那麼這時爲了增強閱讀性,都給這些值起個名字,方便閱讀
而這些值不需要改變。加上final修飾。作爲常量:所有的字母都大寫。如果由多個單詞組成,單詞間由下劃線連接。
5,內部類定義在類中局部位置上是,只能訪問該局部被修飾final修飾的局部變量。
16,抽象類
當多個類出現相同功能,但是功能主體不同,這時候可以進行向上抽取,這時,只抽取功能定義,不抽取功能主體。
抽象:看不懂
抽象類的特點:
1,抽象方法一定定義在抽象類中。
2,抽象方法和抽象類都必須被abstract關鍵字修飾。
3,抽象類不可以用new 創建對象,因爲調用抽象方法沒意義。
4,抽象類中的方法要被使用,必須由子類複寫其所有的抽象方法後,建立子類對象調用。
如果子類只覆蓋了部分抽象方法,那麼該子類還是一個抽象類。
抽象類和一般類沒有太大的不同。
該怎麼樣描述事物就如何描述事物。只不過,該事物出現了一些看不懂的東西。
這些不確定的部分,也是該事物的功能,需要明確出現。但是無法定義主體。
抽象類比一般類多個抽象函數。就是在類中可以定義抽象方法。
抽象類不可以實例化。
特殊: 抽象類中可以不定義抽象方法。這樣做僅僅是不讓該類建立對象。
模板方法設計模式:
在定義功能時,功能的一部分是確定的,但是有一部分是不確定的,而確定的部分在使用不確定的部分。
那麼這個時候,不確定的部分暴露出去。由該類的子類去完成。
獲取程序運行時間。模板設計模式
public abstract class GetTime {
public final void getTime() {
long strattime = System.currentTimeMillis();
runCode();
long endtime = System.currentTimeMillis();
}
public abstract void runCode();
}
class SubTime extends GetTime {
@Override
public void runCode() {
// TODO Auto-generated method stub
for (int x = 0; x < 100; x++) {
System.out.println(x);
}
}
}
class Test {
public static void main(String[] args) {
GetTime g = new SubTime();
g.getTime();
}
}
17,接口
初期理解:可以認爲是一個特殊的抽象類。
當抽象類中的方法都是抽象的,那麼該類可以通過接口的形式來表示。
interface 用於定義接口。
接口定義時,格式特點:
1,接口中常見定義:常量,抽象方法。
2,接口中的成員都有固定修飾符。
常量:public static final
方法:public abstract
記住:接口中的成員都是public的。
接口:是不可以創建對象的,因爲有抽象方法。
需要被子類實現,子類對接口中的抽象方法全都覆蓋後,子類纔可以實例化
否則子類時一個抽象類。
接口可以被類多實現。
一個類可以實現多個接口。也是對多繼承不支持的轉換形式。java支持多實現。
接口與接口的關係:繼承
接口的特點
接口是對外暴露的規則。
接口是程序的功能擴展。
接口可以用來多實現。
類與接口之間是實現關係而且類可以繼承一個類的同時實現多個接口。
接口與接口之間可以有繼承關係。