物件導向
-
物以類聚,分類的思維模式,思考問題首先解決問題需要哪些分類,然後對這些分類進行單獨思考,最後對各個分類下的過程進行思考。
-
對於描述複雜問題的事物,為了從巨集觀上把握,從整體上合理分析,我們需要使用物件導向來分析整個系統,但是,具體的微觀操作,仍然需要使用程式導向的思路去處理。
-
以類的方式組織程式碼,以物件的組織(封裝)陣列
三大特性:
封裝
繼承
多型
類內包含兩部分: 屬性和方法。
物件是類的例項化,
語法:類名 物件名=new 類名();
預設情況下物件的屬性都有預設值,int型別為零,String型別為null等等
構造器 (構造方法)
- new物件本質就是呼叫構造器。(無返回值)
- 構造器一般用來初始化值。
構造器在生成物件時預設呼叫,分為有參和無參,當有參存在時,無參必須顯示定義(寫出來),當我們有參無參均未寫時,系統自動新增無參構造(預設隱藏)。構造器只能是public修飾,因為在main()中定義物件時選需要呼叫構造器。
使用 this.屬性名 用來訪問呼叫的物件的屬性。有多個屬性時可以過載多個構造器。
在IDEA中使用Alt+Insert可以選擇construct可以快速建立構造器。
eg:
package Creat;//類一
public class Creat01 {
public String name;
int age;
public Creat01()
{
this.age=10;
this.name="待輸入";
}
public Creat01(String name) {//一個引數
this.name = name;
}
public Creat01(String name, int age) {//兩個引數
this.name = name;
this.age = age;
}
}
import Creat.Creat01;
public class Application { //類二
public static void main(String[] args) {
Creat01 xiaoming=new Creat01();//建立時呼叫無參構造器
Creat01 xiaohong=new Creat01("xiaohong");//建立時呼叫一個引數的構造器
Creat01 xiaohei=new Creat01("xiaohei",18);//建立時呼叫兩個引數的構造器
System.out.println(xiaoming.name);
System.out.println(xiaohong.name);
System.out.println(xiaohei.name);
}
}
注:
main方法在棧裡,main()結束程式也就結束了,
static靜態方法區,類呼叫的時候和類一起載入。存放在堆中。
引用型別在沒有賦值的情況下預設為null
封裝:
我們的程式設計要追求 高內聚,低耦合,高內聚就是指類的內部資料操作細節自己完成,不允許外部干涉;低耦合:僅僅暴露少量的方法給外部用
屬性私有:get/set
可以理解為不再對屬性直接修改,將屬性賦予私有屬性,通過定義方法對屬性修改。get為得到屬性,set為修改屬性。
在IDEA中,Alt+Insert可以自動生成get和set對屬性進行修改。(getter setter)
在定義類中屬性(變數),方法時,一般使用public,private,protected修飾,在這之中只有public作用下可以在main()方法中直接訪問。
public:可以被繼承,可以直接在main()中通過對像直接訪問和修改
private:不可被繼承,不可再main()中通過物件直接訪問,通過方法進行修改和訪問
protected:可被繼承,不可直接通過物件訪問,通過方法修改訪問
default:不作任何修飾時系統預設為此修飾。可被繼承,不可直接通過物件訪問,通過方法修改訪問。
繼承:類之間的關係
繼承的本質是對某一批類的抽象。
extends的意思是擴充套件,子類是父類的擴充套件,子類會繼承父類的屬性和方法,private屬性下的東西無法繼承,預設下的屬性default。
super關鍵字與this類似,super指代的是父類中所繼承的與子類中同名的屬性區分方法。例如super.name;指代的是繼承自父類的name屬性,this.name指代的是子類原本的那麼屬性,他們可能同名但是並非同一個值。同樣的super();是呼叫父類的構造器(預設情況下,隱式的寫在子類構造器的第一行,當我們人為寫出時只能放在第一行,否則報錯),this();指的是子類構造器,方法也是同理的。
tip:
this();和super();不能同時在子類構造器中顯式的寫出,因為兩者都要求要寫在第一行,否則會報錯,因此直接不寫出即可,自動隱式生成。父類沒有無參構造。子類生成時也會報錯!除非寫出super(引數);
super只能出現在子類的構造器或者方法中。只有繼承才可以使用。
注:
java中只有單繼承,沒有多繼承。在java中所有類預設繼承object類。
在IDEA中Ctrl+H可以檢視繼承的分級情況。
使用final修飾的類不能再被繼承
public final class father{ //不能被繼承
}
eg:
//父類
package Inherit;
public class Inherit01 {
String name="father";//default屬性下的變數
public int age=52; //public 下的
private double high=170.0; //private下的不能被繼承
protected double weight=69;//protected
public Inherit01()
{
name="Tom";
age=53;
high=171;
weight=68;
}
}
//子類
package Inherit;
public class Inherit02 extends Inherit01{
public Inherit02 ()
{
// super();//呼叫父類構造器
}
String name="son";
int age=21;
double high=181.0;
double weight=70;
public void test01(String name){ //如果在引數中定義的有同名變數,那麼單寫變數名指代的是引數中的變數
//想要指代自己定義的需要使用this指標
System.out.println("自己定義的:"+this.name+" "+age+" "+high+" "+weight);
System.out.println("繼承獲得的:"+super.name+" "+super.age+" "+super.weight);
//私有private下的high未能得到繼承
System.out.println("傳入引數的同名變數:"+name);
}
}
//應用
import Inherit.Inherit02;
public class Application {
public static void main(String[] args) {
//繼承的測試程式碼
Inherit02 inherit02=new Inherit02();
inherit02.test01("傳入的name");
}
}
重寫:
重寫必須要有繼承關係,是子類對父類方法的重寫。
- 方法名必須相同
- 引數列表必須相同
- 修飾符的範圍只能擴大不能縮小 public>protected>default>private
- 丟擲異常的範圍只能縮小不能擴大
不能是static的靜態函式
子類和父類的方法名一致,但是方法體不同。
為什麼要重寫?
父類的方法子類不一定需要,或者不一定滿足需求
IDEA中的重寫快捷鍵: Alt+insert----->override
靜態方法的呼叫中,僅僅和左邊的定義有關。例如:A類繼承自B類。若兩者都含有靜態方法test()
A a=new A();
B b=new A(); //父類的引用指向子類的,僅可呼叫父類中有的方法。
a.test(); //呼叫的是A中寫的test()
b.test(); //呼叫的時B中 的方法test()
若不是靜態方法,而是普通的方法,則test在A中的定義直接實現了test方法的重寫。
不能重寫的方法:
- static 方法,屬於類的,不屬於例項
- final 常量的,在常量池
- private 方法
多型:
同一方法根據傳送物件不同而採取不同的欣行為方式
一個物件的實際型別是確定的,但是可以指向物件的引用型別(父類,有關係的類)有很多。
多型是方法的多型,屬性沒有多型
存在條件:繼承關係,方法需要重寫,父類的引用指向子類的物件 father f1=new son();
instanceof:
使用比較x和Y的關係,x為物件,Y為一個類。
如果X和Y存在父子關係則可以通過編譯,否則無法通過編譯,比較返回結果的true或false
如果物件X屬於類Y或者其父類產生的物件則為true,否則為false
要進行強制的了型別轉換:
子類轉換為父類可能丟失自己本身的一些方法。
只能是父類引用指向子類的物件。
父類轉換為子類需要強制轉換,通過強制的轉換,通過降級或升級使其能夠呼叫它本身的一些其他方法
((Student)object).方法(); //強制轉換的方法