Java基礎---面向物件
面向物件
面向物件程式設計的本質:以類的方式組織程式碼,以物件的組織(封裝)資料
四大特徵:封裝、繼承、多型、抽象(具有相同特徵和行為的物件抽象成類)
方法的深入
-
方法的定義
-
修飾符
-
返回型別
-
break和return的區別
break用於switch或迴圈中跳出整個迴圈體
return表示方法結束,返回一個結果,必須與返回值型別相同;
-
方法名
-
引數列表(引數型別,引數名)
-
異常丟擲 ???(以後講)
-
-
方法的呼叫
- 靜態方法--可以直接通過類名.方法名呼叫
--兩個靜態方法可互相呼叫;兩個非靜態方法也可以互相呼叫
-
非靜態方法--不可直接呼叫,
---需要例項化(new一個物件),物件型別 物件名 = 物件值(new 物件型別)通過物件名.方法名來呼叫
public class student { //新建一個學生類 //非靜態方法 public void say(){ System.out.println("學生說話了"); } }
student zxy = new student(); //例項化 zxy.say(); //物件名.方法
-
形參和實參
-
值傳遞和引用傳遞
-
this關鍵字
物件的建立和分析
類和物件的關係
--類是一種抽象的資料型別,對一類事物整體的描述,不能代表某一具體事務
--物件是抽象概念的具體例項
--建立物件:new關鍵字--本質是呼叫構造器
使用new時,除了分配空間外,還會給物件預設初始化以及對類中構造方法的呼叫;
student zxy = new student(); //呼叫了構造器 public student(){ } //預設無參構造器 student wzh = new student(wangzihe); //呼叫構造器,有參構造 public student(String name){ this.name = name; //this.name指的是當前類中定義的name;第二個name是引數傳進來的 } //如果定義了有參構造,那麼無參構造必須顯示寫出來
--構造方法(構造器):與類名相同;沒有返回值型別,也不能寫void;完成資料初始化操作;
--記憶體分析:物件通過引用來操作:棧---->堆
封裝
- 資料的隱藏,應禁止直接訪問一個物件的資料的實際表示,通過操作介面來訪問
- 屬性私有(private)---get/set
- 提供一些操作這些屬性的方法:get(獲取這個資料) set(給資料賦值)
繼承
-
本質:對某一批類的抽象,是類和類之間的關係,子類和父類之間
-
關鍵字:extends(擴充套件)---子類是父類的擴充套件
-
Java中類只有單繼承,沒有多繼承;----一個兒子只能有一個爸爸,一個爸爸有多個兒子
-
私有的東西無法繼承
-
在Java中,所有類都預設直接或間接繼承Object類
-
在執行時,子類會預設呼叫父類的無參構造;
-
被final修飾的類不能被繼承;--final之後斷子絕孫。。。
-
public class person //父類 public class student extends person //子類/派生類--學生 is 人 public class teacher extends person //子類/派生類--老師 is 人
super
//主函式所在--測試類 public class test { public static void main(String[] args) { student zxy = new student(); zxy.test("hhhzxy"); }}
父類 public class person { protected String name = "張二白"; }
子類 public class student extends person { private String name = "zhangxiaoyang"; public void test(String name){ System.out.println(name); //輸出的是(hhhzxy)主函式中傳的引數 System.out.println(this.name); //輸出的是(zhangxiaoyang)當前類中的name值 System.out.println(super.name);//輸出的是(張二白)父類的name值 } }
注意點:
1)super呼叫父類的構造方法,必須在構造方法的第一個
2)super必須只能出現在子類的方法中或構造方法中
3)super和this不能同時呼叫構造方法
與this的區別:
1)代表物件不同:
this:本身呼叫這個物件
super:代表父類物件的應用
2)前提:
this:沒有繼承也可以用
super:只能在繼承條件下可用
3)構造方法
this():本類的構造
super():父類的構造
方法重寫
需要有繼承關係,子類重寫父類的方法;子類和父類的方法必須一致,只是內容不同(方法體不同)
- 方法名必須相同
- 引數列表必須相同
- 修飾符:範圍可以擴大 public>protected>default>private
- 丟擲的異常:範圍可以被縮小,但不能擴大--(父親欠了50萬,你還了10萬,還剩40萬,你不能再欠了。。。)
-為什麼要重寫???---父類的功能,子類不一定需要或不一定滿足;子類重寫了父類的方法,執行時執行子類的
-什麼方法不能重寫:
1)static方法,屬於類,不屬於例項
2)被final(常量)修飾的方法
3)private方法
多型
什麼是多型---同一個方法根據傳送物件的不同而採用多種不同的行為方式
一個物件的實際型別是確定的---new student(); new person();
但可以指向物件的引用型別就不確定了,父類的引用指向子類
student s1 = new student(); //s1能呼叫的方法是自己的或繼承父類的
person s2 = new student(); //person可以指向子類,但不能呼叫子類獨有的方法
Object s3 = new student();
//物件能執行哪些方法,主要看物件左邊的型別
s1.run();
s2.run(); //子類重寫了父類的方法,執行子類的方法
s2.eat(); //s2是person型別,無法呼叫student類裡獨有的方法
((student)s2).eat(); //把s2強制轉化成student型別,可以呼叫student裡獨有的方法
注意事項:
-
多型是方法的多型
-
父類和子類,有聯絡,型別轉換可能發生異常-- ClassCastException!
-
存在條件:繼承關係,方法需要重寫,父類引用指向子類物件-father f1 = new son()
instanceof (型別轉換)
Object >person >teacher Object >person >student System.out.println(X instanceof Y);//能不能編譯通過,看X與Y是否有父子關係 System.out.println(Object instanceof student); //true System.out.println(student instanceof Object); //true System.out.println(student instanceof teacher); //false
子類轉成父類,向上轉型,自動;--可能丟失自己本來的一些方法
父類轉成子類,向下轉型,強制轉換;
型別轉換方便方法的呼叫,減少重複程式碼
static詳解
-
靜態屬性
private static int age; //靜態屬性 private double score; //非靜態 public static void main(String[] args) { student s1 = new student(); System.out.println(student.age); //靜態屬性可直接用類名呼叫 System.out.println(student.score); //非靜態不能用類名直接呼叫 System.out.println(s1.age); System.out.println(s1.score);
-
靜態方法
public void run() { go(); } //靜態方法和類一起載入,非靜態方法裡可以呼叫靜態方法 public static void go() { } student.run(); //報錯--非靜態方法不能用類.方法名呼叫 s1.run(); student.go(); //靜態方法可直接用類呼叫
!!!是類的載入機制的問題,非靜態都還沒載入進來,自然不能直接用類呼叫,但靜態和類一起載入,故可以呼叫
3.靜態程式碼塊--最先執行(先於匿名程式碼塊和構造方法),只執行一次
4.匿名程式碼塊和物件同時產生,在構造方法之前,可以賦一些初始值
5.靜態匯入包-
import static java.lang.Math.random; //把Java.lang包中的Math的random()方法匯入 System.out.println(Math.random());//不匯入的寫法 System.out.println(random()); //可以直接呼叫Math中的random()方法
-
抽象類和介面
抽象類(abstract class)
-
對於抽象類的所有方法,繼承了抽象類的子類,都必須要實現他的方法,除非子類也是抽象類,那就由下一代來實現。。。
-
不能new這個抽象類,即不能建立例項;只能靠子類去實現它;
-
抽象類裡可以寫普通方法,但抽象方法必須寫在抽象類裡;
-
抽象類不能new,那存在構造器嗎? ----存在,編譯器新增預設的無參建構函式,只是不能直接建立抽象類的例項物件
-
抽象類存在的意義?
-
//抽象類 public abstract class Action { public abstract void dosomething(); //抽象方法--沒有方法體,即具體的實現 }
介面(interface)
-
普通類:只有具體實現
-
抽象類:具體實現和規範(抽象方法)都有!
-
介面:只有規範!自己無法寫方法~專業的約束!約束和實現分離:面向介面程式設計
-
介面就是規範,定義一組規則---定義一些方法,讓不同的人實現;
-
介面不能被例項化~,介面沒有構造方法(他連類都不是。。。)
-
介面的本質是契約,像法律一樣,制定好後大家遵守
-
其實設計模式所研究的實際上就是如何合理的去抽象,所以設計模式都只針對具備抽象能力的語言(c++,java,c#等)
-
//通過interface定義一個介面,只宣告方法,不實現(型別 方法名) public interface timeService { void timer(); } public interface UserService{ void add(String nam); void delete(String nam); void update(String nam); void query(String nam); } //類 通過關鍵字implements實現介面,實現了介面的類必須重寫介面中的方法(可以通過idea自動生成) public class UserServiceImpl implements UserService{ } //多繼承---利用介面來實現 public class UserServiceImpl implements UserService,timeService{}
內部類
-
成員內部類
public class Outer { private int id = 10; public void out(){ System.out.println("這是外部類的方法");} class Inner{ public void in(){ System.out.println("這是內部類的方法"); } //內部類可以獲得外部類的私有屬性 public void getId(){ System.out.println(id); } } }
//在測試類中 public class test { public static void main(String[] args) { Outer outer = new Outer(); //外部類new一個物件 Outer.Inner inner = outer.new Inner(); //通過外部類來例項化內部類。。。 inner.in(); inner.getId(); } }
-
靜態內部類
public static class Inner{ public void in(){ System.out.println("這是內部類的方法"); } //內部類可以獲得外部類的私有屬性 public void getId(){ System.out.println(id); //若類變成靜態內部類,就無法獲得私有屬性了。。。還是類的載入機制 } }
-
區域性內部類
public class Outer { //區域性內部類---在一個方法裡面定義的類 public void method(){ class Inner{ } }
-
匿名內部類
class Apple { public void eat() { System.out.println("1"); } }
public class test { public static void main(String[] args) { new Apple().eat(); //沒有名字初始化類,不用把例項存在變數裡 //正常情況下:Apple apple = new Apple(); apple.eat(); }
- 一個java類中可以有多個class類,但是隻能有一個public class類