Java(面向物件)
(一)類和物件
1、(1)面向過程就是分析出解決問題所需要的步驟,然後用函式把這些步驟一步一步實現,使用的時候一個一個依次呼叫就可以。
(2)面向物件是把構成問題事務分解成各個物件,建立物件的目的不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題的步驟中的行為。
2、全域性宣告其實只是可以公用一個指定型別的變數,而全域性變數則是已經初始化並且分配了唯一的地址並且在任何地方都可以
使用,區域性變數則只能在方法內部使用,其它地方不能使用。全域性變數是一個容器,而區域性變數只能是容器裡的一部分。
(1)成員變數(全域性變數:JAVA中沒有全域性變數的定義,這是C中的),當前類的所有方法和一些其他類)
(2)區域性變數(當前方法使用)
兩者區別:
(1)作用域不同:區域性變數僅限於定義它的方法,而成員變數在整個類內部都是可見的;
(2)初始值不同:Java會給成員變數一個初始值,不會給區域性變數賦予初始值;
(3)在同一方法中,不允許有同名區域性變數,在不同方法中,可以有同名區域性變數;
(4)兩類變數同名時,區域性變數具有更高優先順序。
3、構造方法(建立物件,並初始化物件的值)
(1)通過無參構造方法可以建立物件
(2)通過有參構造方法可以建立物件並給物件中的例項變數賦初值
(3)構造方法過載
(4)有參構造傳值控制
4、使用static可以修飾變數、方法和程式碼塊
【靜態變數】(靜態成員或類成員)
Java 中被 static 修飾的成員稱為靜態成員或類成員,屬於整個類所有,而不是某個物件所有(即被類的所有物件所共享)
(1)靜態成員可以使用類名直接訪問(省略類名),也可以使用物件名進行訪問)
(2)靜態成員屬於整個類,當系統第一次使用該類時,就會為其分配記憶體空間直到該類被解除安裝才會進行資源回收
【靜態方法】(靜態方法或類方法)
靜態變數一樣,也可以使用 static 修飾方法,稱為靜態方法或類方法。其實之前我們一直寫的 main 方法就是靜態方法。
(1)靜態方法中可以直接呼叫同類中的靜態成員,但不能直接呼叫非靜態成員或呼叫非靜態方法(需要通過物件來訪問
非靜態方法);
(2) 在普通成員方法中,則可以直接訪問同類的非靜態變數和靜態變數。
靜態變數和成員變數有什麼區別:
靜態變數靜態變數也稱作類變數,是在類之中,方法之外,以static關鍵字申明的變數,其獨立在物件之外,有許多物件共
享的變數。靜態變數在物件產生之前產生,並長駐於記憶體,其在JVM關閉時銷燬。成員變數成員變數也稱作例項變數、屬性, 申
明在類之中,方法之外的變數,隨物件銷燬而銷燬。
【靜態初始化塊】
(1)靜態初始化塊只在類載入時執行,且只會執行一次,同時靜態初始化塊只能給靜態變數賦值,不能初始化普通的成員變數。
(2)程式執行時靜態初始化塊最先被執行,然後執行普通初始化塊,最後才執行構造方法。由於靜態初始化塊只在類載入時執行
一次
(二)封裝(隱藏屬性)
1、概念:將類的某些資訊隱藏在類內部,不允許外部程式直接訪問,而是通過該類提供的方法來實現對隱藏資訊的操作和訪問。
2、好處:只能通過規定的方法訪問資料;隱藏類的例項細節,方便修改和實現。
3、封裝的實現步驟:
(1)修改屬性的可見性(設為private)
(2)建立getter/setter方法(用於屬性的讀寫)
(3)在getter/setter方法中加入屬性控制語句(對屬性值的合法性進行判斷)
【訪問修飾(控制)符】:可以修飾屬性和方法的訪問範圍(屬性通常用private修飾,方法用public修飾)
(1)private修飾:本類(訪問範圍最小)
(2)預設修飾(不寫):本類、同包
(3)protected修飾:本類、同包、子類
(4)public修飾:本類、同包、子類、其它(任何)
【this關鍵字】(當前物件)
(1)this.屬性 操作當前物件的屬性
(2)this.方法 呼叫當前物件的方法
【內部類】:內部類( Inner Class )就是定義在另外一個類裡面的類。與之對應,包含內部類的類被稱為外部類(內部類也
是一個類,可以有自己的成員方法和成員變數)
內部類的主要作用如下:
(1)內部類提供了更好的封裝,可以把內部類隱藏在外部類之內,不允許同一個包中的其他類訪問該類
(2)內部類的方法可以直接訪問外部類的所有資料,包括私有的資料
(3)內部類所實現的功能使用外部類同樣可以實現,只是有時使用內部類更方便
內部類有幾種呢?
(1)成員內部類(普通內部類,最常見):定義了成員內部類後,必須使用外部類物件來建立內部類物件,而不能直接去
new一個內部類物件,即:內部類 物件名 = 外部類物件.new 內部類( );
1)外部類是不能直接使用內部類的成員和方法(可先建立內部類的物件,然後通過內部類的物件來訪問其成員變數和
方法)
2)如果外部類和內部類具有相同的成員變數或方法,內部類預設訪問自己的成員變數或方法,如果要訪問外部類的成
員變數,可以使用 this 關鍵字
(2)靜態內部類(靜態內部類是 static 修飾的內部類)
1)靜態內部類不能直接訪問外部類的非靜態成員,但可以通過 new 外部類().成員 的方式訪問
2)如果外部類的靜態成員與內部類的成員名稱相同,可通過“類名.靜態成員”訪問外部類的靜態成員;如果外部類的
靜態成員與內部類的成員名稱不相同,則可通過“成員名”直接呼叫外部類的靜態成員
3)建立靜態內部類的物件時,不需要外部類的物件,可以直接建立 內部類 物件名= new 內部類();
(3)方法內部類:內部類定義在外部類的方法中,方法內部類只在該方法的內部可見,即只在該方法內可以使用。
(4)匿名內部類(學習介面時會提到)
(三)繼承(子類擁有父類的所有屬性和方法)
1、概念:繼承是類與類的一種關係,是一種“is a”的關係(Java中的繼承是單繼承,只有一個父類)
2、好處:子類擁有父類的所有屬性和方法(private修飾的無效),實現程式碼複用
3、語法:class 子類 extends 父類
子類/派生類 父類/基類
【方法的重寫】(重寫父類繼承的方法)
1、概念:如果子類對繼承父類的方法不滿意,是可以重寫父類繼承的方法的,當呼叫方法時會優先呼叫子類的方法。
2、語法規則:(1)返回值型別 (2)方法名 (3)引數型別及個數 都要與父類繼承的方法相同,才叫方法的重寫。
3、@Override標籤的作用 :
@Override是虛擬碼,所以是可寫可不寫的,它表示方法重寫,寫上會給我們帶來好處.
(1)可以當註釋用,方便閱讀.
(2)告訴閱讀你程式碼的人,這是方法的複寫.
(3)編譯器可以給你驗證@Override下面的方法名是否是你父類中所有的,如果沒有則報錯.
總結:過載與覆蓋的區別:
1)過載是在同一個類中,為了滿足不同的需求
2)覆蓋是在子類中進行重寫,為了更加具體化
【繼承的初始化順序】(初始化父類再初始化子類)
(1)初始化父類再初始化子類
(2)先執行 初始化物件中屬性,再執行構造方法中的初始化
即:父類物件(屬性初始化->構造方法)->子類物件(屬性初始化->構造方法)
【final關鍵字】(最終的,可以修飾類,方法,屬性和變數)
(1)final修飾類,則該類不能被繼承(最終類)
(2)final修飾方法,則該方法可以被繼承,但不能被覆蓋(重寫)
(3)final修飾屬性,則該屬性在定義時需要初始化,或者在構造方法中初始化(二選一初始化)
(4)final修飾變數,該變數只能進行一次賦值(包括初始化),而後值不可更改,相當於常量
【super關鍵字】(父類物件)
在物件的內部使用(子類物件方法內),可以代表父類物件。
(1)訪問父類的屬性:super.age;(2)訪問父類的方法:super.eat();
super應用:super關鍵字和構造方法有緊密關係
(1)子類的構造過程中必須呼叫起父類的構造方法
(2)如果子類的構造方法中沒有顯式呼叫父類的構造方法,則系統預設呼叫父類無參的構造方法(隱式顯示)
(3)如果顯式的呼叫構造方法,必須在子類構造方法的第一行(子類構造方法第一行)
(4)如果子類構造方法中既沒有顯式的呼叫父類構造方法,而父類又沒有無參的構造方法,則編譯出錯
【Object類】(所有類的父類,預設繼承該類)
如果一個類沒有使用extends關鍵字明確標識繼承另外一個類,那麼這個類預設繼承Object類。Object類中的方法,適合
所有子類。
1、toString()方法:
在Object類裡面定義toString()方法的時候返回物件的雜湊code碼(物件地址字串)
可以通過重寫toString()方法表示出物件的屬性。source->generate to String()
2、equals()方法:
equals()方法,比較的是物件的引用是否指向同一塊記憶體地址(其實是比較是否是一個手機,即為同一個物件),
其實我們建立的Dog dog = new Dog()只是一塊地址,類似於遙控器,類物件更關注類的程式碼資訊(Object.getClass() 返回一個
類物件,描述的是一個類的資訊,包括屬性,方法,程式碼等等),new 類是類的物件,更關注類的屬性的值的資訊。
總結:java中的資料型別,可分為兩類:
1)基本資料型別,也稱原始資料型別。byte,short,char,int,long,float,double,boolean
他們之間的比較,應用雙等號(==),比較的是他們的值。
2)複合資料型別(String、Integer、Date,物件)
當他們用(==)進行比較的時候,比較的是他們在記憶體中的存放地址,所以,除非是同一個new出來的物件,他們的比較後的結果為true,否則比較後結果為false。因為每次new都會開闢新的記憶體空間,故指向的記憶體地址不相同。
JAVA當中所有的類都是繼承於Object這個基類的,在Object中的基類中定義了一個equals的方法,這個方法的初始行為是比
較物件的記憶體地 址,但在一些類庫當中這個方法被覆蓋掉了,如String,Integer,Date在這些類當中equals有其自身的實現,而
不再是比較類在堆記憶體中的存放地址了。
對於複合資料型別之間進行equals比較,在沒有覆寫equals方法的情況下,他們之間的比較還是基於他們在記憶體中的存放位置的地址值的,因為Object的equals方法也是用雙等號(==)進行比較的,所以比較後的結果跟雙等號(==)的結果相同。
如需比較複合資料型別則需重新equals 方法使用eclipse工具----source-------Generate hashcode()-----andequals()自動
重寫
String str1 = new String("hello"); // Java中,只要使用new關鍵字來建立物件,則一定會(在堆區或棧
區)建立一個新的物件
String str2 = "hello"; // 因為它們都是從緩衝池取出來的,由於string類比較特殊,jdk專門做了快取
優化
String str3="hello";
System.out.println("str1==str2: " + (str1 == str2));
System.out.println("str2==str3"+(str2==str3));
System.out.println("str1.equals(str2): " + str1.equals(str2));
(四)多型(物件 多種形態,繼承是實現多型的基礎)
1、引用多型
父類的引用可以指向本類的物件(Animal obj1 = new Animal();)
父類的引用可以指向子類的物件(Animal obj2 = new Dog();)
2、方法多型
建立本類物件時,呼叫的方法為本類方法
建立子類物件時,呼叫的方法為子類重寫的方法或者繼承的方法(父類的引用不能呼叫子類獨有的方法)
【引用的型別轉換】
1、向上型別轉換(隱式/自動型別轉換),是小型別打大型別的轉換。
2、向下型別轉換(強制型別轉換),是大類想到小型別。
3、instanceof運算子,來解決引用物件的型別,避免型別轉換的安全性問題、如記憶體溢位(判斷一個型別是否是某個類
型或者某個型別的子型別,返回Boolean值)
如: class dog entends animal class animal class cat
Dog dog=new Dog(); Animal animal=dog;//向下型別轉換,自動型別。
Dog dog=(Dog)animal; //強制型別轉換。
Cat cat=(Cat )animal //因為編譯時時Cat型別,執行時Dog型別會報錯。
改為: if(animal instanceof Cat)
{ Cat cat=(Cat )animal//依然無法轉換,但是不會報錯。 }
https://blog.csdn.net/leo_24/article/details/78044586
【抽象類】(有抽象方法的一定是抽象類,但是抽象類不一定有抽象方法)
1、語法定義:抽象類前使用abstract關鍵字修飾,則該類為抽象類( abstract class A)。
2、應用場景:
(1)在某些情況下,某個子類只是知道其子類應該包含怎樣的辦法,但無法準確知道這些子類如何實現這些方法。
(2)從多個具有相同特徵的類中抽象出一個抽象類,以這個抽象類作為子類的模板,從而避免了子類設計的隨機性。
3、作用:限制規定子類必須實現某些方法,但不關注實現細節(不關注子類的實現,但必須約束子類的特徵(約束子類))
4、使用規則:
(1)abstract定義抽象類
(2)abstract定義抽象方法,只有宣告,不需要實現
(3)包含抽象方法的類是抽象類
(4) 抽象類中可以包含普通的方法,也可以沒有抽象方法
(5) 抽象類可以有構造方法,但不能直接例項化,只能用來繼承
(6)在抽象類中可以定義抽象方法,也可以定義具體方法,如果一個類繼承抽象類,那麼必須重寫抽象類中定義的所
有抽象方法。
【介面】(規範,約束類)
1、介面概念:介面可以理解為一種特殊的類,有全域性常量和公共的抽象方法所組成。類是一種具體實現體,而介面定義了
某一批類所需要遵守的規範,介面不關心這些類的內部資料,也不關心這些類裡方法的實現細節,它只規定這些類裡必須提供某
些方法。
2、介面定義:和類定義不用,定義介面不再使用class關鍵字,而是使用interfaca關鍵字。
基本語法:[修飾符](abstract系統預設)interface 介面名 extends [父介面1.2.3]
{
零個到多個常量定義...
零個到多個抽象方法的定義...
}
介面就是用來被繼承,被(其他類)實現的,修飾符一般建議用public (注意:不能使用private和protected修飾接
口)
3、介面定義
(1)常量:介面中的屬性是常量(即使定義時不新增 public static final 修飾符,系統也會自動加上)
(2)方法:介面中的方法只能是抽象方法(即使定義時不新增public abstract修飾符,系統也會自動加上,不能是方
法體)
4、使用介面:一個類可以實現一個或多個介面,實現介面使用implements關鍵字。Java中一個類只能繼承一個父類,是不
夠靈活的,通過實現多個介面可以做補充。
繼承父類實現介面的語法為:
[修飾符] class 類名 extends 父類 implements 介面1,介面2..(如果要繼承父類,繼承父類必須在實現介面之前)
{
類體部分//如果繼承了抽象類,需要實現繼承的抽象方法;要實現介面中的抽象方法。
}
5、使用介面:經常與匿名內部類配合使用(匿名內部類就是沒有名字的內部類,多用於關注實現而不關注實現類的名字(
Android經常使用)
IplayGame iplayGame=new SmartPhone();
iplayGame.playGame();
IplayGame iplayGame2=new IplayGame() {
@Override
public void playGame() {
// TODO Auto-generated method stub
System.out.println("使用匿名內部類的方式實現介面");
}
};
iplayGame2.playGame();
new IplayGame() {
@Override
public void playGame() {
// TODO Auto-generated method stub
System.out.println("使用匿名內部類的方式實現介面2");
}
}.playGame();
總結:
相同點:(1)介面和抽象類都不能被例項化(用於被其他類繼承和實現)
(2)都可以包含抽象方法(實現介面或繼承抽象類的普通子類必須實現這些抽象方法)
不同點:(1)口裡只能包含抽象方法,靜態方法和預設方法,不能為普通方法提供方法實現,抽象類則完全可以包含普通方
法。
(2)接口裡只能定義靜態常量,不能定義普通成員變數,抽象類裡則既可以定義普通成員變數,也可以定義靜態常
量。
(3)介面不能包含構造器,抽象類可以包含構造器,抽象類裡的構造器並不是用於建立物件,而是讓其子類呼叫這
些構造器來完成屬於抽象類的初始化操作。
(4)接口裡不能包含初始化塊,但抽象類裡完全可以包含初始化塊。
(5)一個類最多隻能有一個直接父類,包括抽象類,但一個類可以直接實現多個介面,通過實現多個介面可以彌補
Java單繼承不足。