面向物件02
7.繼承
- 繼承的本質是對某一批類的抽象,從而實作對現實世界更好地建模
- extends的意思是“擴展”,子類是父類的擴展,
- Java類中只有單繼承,沒有多繼承!(一個兒子只能有一個爸爸,一個爸爸可以有多個兒子)
- 繼承是類和類之間的一種關系,除此之外,類和類之間的關系還有依賴、組合、聚合等,
- 繼承關系的兩個類,一個為子類(派生類),一個為父類(基類),子類繼承父類,使用關鍵字extends表示
- 子類和父類之間,從意義上講應該具有“is a”的關系
- object類
- super
- 方法重寫
子類繼承了父類,就會有父類的全部方法!(私有的東西無法被繼承)
例子1:
package li.oop.demo05;
//父類:Person 人
public class Person {
//public
//protected
//default
//private
public int money = 10_0000_0000;
public void say(){
System.out.println("說了一句話");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
package li.oop.demo05;
//學生 is 人
//派生類(子類),子類繼承了父類,就會有父類的全部方法
public class Student extends Person{
}
package li.oop;
import li.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();//說了一句話
System.out.println(student.money);// 1000000000
}
}
7.1Object類
在Java中,所有的類都默認直接或者間接繼承Object類
7.2Super關鍵字
-
super. 大部分情況下是可以省略的,
當父中類有,子類中又有,如果想在子中訪問“父的特征”,super. 不能省略,
在父和子中有同名的屬性,或者說有相同的方法,如果此時想在子類中訪問父中的資料,必須使用“super.”加以區分,-
super.屬性名 --->訪問父類的屬性
-
super.方法名(實參) --->訪問父類的方法
-
super(實參) ---->呼叫父類的構造方法
-
-
子類繼承父類,子類的構造方法必須呼叫super()即父類的構造方法,而且必須放在構造方法的第一行,
子類構造方法第一行都有呼叫父類無參的構造方法,如果你不顯示地寫出了,系統會自己加上;
但是如果你的父類多載了一個或多個構造方法,系統將不再默認加上無參的構造方法,必須自己加上,
- super呼叫父類的構造方法,必須在構造方法中的第一行
- super必須只能出現在子類的方法或者構造方法中
- super和this不能同時呼叫構造方法
- super&&this
- 代表的物件不同:
- this:代表本身呼叫者這個物件
- 代表當前類的父類物件的參考
- 前提:
- this:沒有繼承也可以使用
- super:只能在繼承條件下才可以使用
- 構造方法的區別:
- this(); 本類的構造
- super(); 父類的構造
- 代表的物件不同:
7.3方法重寫
例子1:
package li.oop.demo05;
//重寫都是方法的重寫,和屬性無關
public class B {
public static void test(){
System.out.println("B==>test");
}
}
package li.oop.demo05;
public class A extends B{
public static void test(){
System.out.println("A==>test");
}
}
package li.oop;
import li.oop.demo05.A;
import li.oop.demo05.B;
public class Application {
public static void main(String[] args) {
//靜態方法:方法的呼叫只和左邊定義的型別有關
A a = new A();
a.test();//呼叫的是A類方法
//父類的參考指向了子類
B b = new A();
b.test();//呼叫的是B類方法
}
}
靜態方法:方法的呼叫只和左邊定義的型別有關
例子2:
package li.oop.demo05;
//重寫都是方法的重寫,和屬性無關
public class B {
public void test(){
System.out.println("B==>test");
}
}
package li.oop.demo05;
public class A extends B{
//Override 重寫
@Override // 注解:有功能的注解!
public void test(){
System.out.println("A==>test");
}
}
package li.oop;
import li.oop.demo05.A;
import li.oop.demo05.B;
//靜態方法和非靜態方法區別很大!
//靜態方法:方法的呼叫只和左邊定義的型別有關
//非靜態:重寫
public class Application {
public static void main(String[] args) {
A a = new A();
a.test();
//父類的參考指向了子類
B b = new A();//子類重寫了父類的方法
b.test();
}
}
總結:
重寫 :子類的方法和父類的方法必須要一致,方法體不同
-- 重寫前提:需要有繼承關系,子類重寫父類的方法
- 方法名必須相同
- 引數串列必須相同
- 修飾符:范圍可擴大,但不能縮小:public>protected>default>private
- 拋出的例外:范圍可以被縮小,但不能擴大,例如:ClassNotFoundException(范圍小)-->Exception(范圍大)
為什么需要重寫?:父類的功能,子類不一定需要,或者不一定滿足!
快捷鍵:Alt+insert:Override;
8.多型
8.1多型的定義和使用
-
即同一方法可以根據發送物件的不同而采取多種不同的行為方式
-
一個物件的實際型別是確定的,但可以指向物件的參考型別有很多
這里的參考一般指父類或者有關系的類
-
多型存在的條件:
- 有繼承關系
- 子類重寫父類方法
- 父類參考指向子類物件
-
注意:多型是方法的多型,屬性沒有多型性
-
instanceof (型別轉換)參考型別
例子1:
package li.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
package li.oop.demo06;
public class Student extends Person{
}
package li.oop;
import li.oop.demo06.Person;
import li.oop.demo06.Student;
public class Application {
public static void main(String[] args) {
//一個物件的實際型別是確定的
//new Student();
//new Person();
//但是可以指向的參考型別就不確定了
Student s1 = new Student();
Person s2 = new Student();//父類的參考指向子類
Object s3 = new Student();//父類的參考指向子類
s2.run();//這里雖然new的是Student,但是是它依舊走的是父類的方法,因為子類繼承了父類的全部方法
}
}
這里的 s2 雖然new的是Student,但是是s2.run() 依舊走的是父類的方法,因為子類繼承了父類的全部方法
例子2
package li.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
package li.oop.demo06;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
package li.oop;
import li.oop.demo06.Person;
import li.oop.demo06.Student;
public class Application {
public static void main(String[] args) {
//一個物件的實際型別是確定的
//new Student();
//new Person();
//但是可以指向的參考型別就不確定了
//Sudent能呼叫的方法都是自己的或者繼承父類的
Student s1 = new Student();
//Person父型別:可以指向子類,但是不能呼叫子類獨有的方法
Person s2 = new Student();//父類的參考指向子類
Object s3 = new Student();//父類的參考指向子類
s2.run();//子類重寫了父類的方法,執行子類的方法
s1.run();
//s2.eat 不能呼叫 s2為Person父型別:可以指向子類,但是不能呼叫子類獨有的方法
((Student) s2).eat();//強制型別轉換后才可以使用
//物件能夠執行的方法主要看物件左邊的型別和右邊關系不大
}
}
物件能夠執行的方法主要看物件左邊的型別和右邊關系不大
如
//Person父型別:可以指向子類,但是不能呼叫子類獨有的方法
Person s2 = new Student();//父類的參考指向子類
//子類Sudent能呼叫的方法都是自己的或者繼承父類的
Student s1 = new Student();
多型注意事項:
- 多型是方法的多型,屬性沒有多型
- 父類和子類,有聯系
- 多型存在的必要條件:
- 有繼承關系
- 方法需要重寫
- 不能重寫的方法:
- 1.static 方法,屬于類,它不屬于實體
- final 常量
- private 方法
- 不能重寫的方法:
- 父類的參考指向子類物件
8.2instanceof
instanceof(型別轉換)參考型別,判斷一個物件是什么型別
例子1:
package li.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
package li.oop.demo06;
public class Student extends Person{
}
package li.oop.demo06;
public class Teacher extends Person{
}
package li.oop;
import li.oop.demo06.Person;
import li.oop.demo06.Student;
import li.oop.demo06.Teacher;
public class Application {
public static void main(String[] args) {
//Object > Person > Student
//Object > Person > Teacher
//Object > String
Object object = new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
System.out.println("==============");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
// 編譯就報錯了 System.out.println(person instanceof String);
System.out.println("==============");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
// 編譯就報錯了 System.out.println(student instanceof Teacher);
//編譯就報錯了 System.out.println(student instanceof String);
}
}
總結:
System.out.println(X instanceof Y);
能不能編譯通過,取決于X與Y之間是否存在直系繼承關系
8.3類的型別轉換
- 基本型別轉換
- 高容量轉換成低容量:強制型別轉換
- 低容量轉換成高容量:自動型別轉換
- 類之間的轉化:父類代表高的,子類代表低的
- 父轉子:強制轉換
- 子轉父:自動轉換
例子:
package li.oop.demo06;
public class Person {
}
package li.oop.demo06;
public class Student extends Person{
public void go(){
System.out.println("go");
}
}
package li.oop;
import li.oop.demo06.Person;
import li.oop.demo06.Student;
public class Application {
public static void main(String[] args) {
/*型別之間的轉換:
1.基本型別轉換-->高容量轉換成低容量:強制型別轉換
低容量轉換成高容量:自動型別轉換
2.類之間的轉化:父類代表高的,子類代表低的
*/
//高 <--- ---- --- 低
Person student = new Student();
//這里只有在子類Student類中才有go()方法,
// 而student物件是Person型別的,因此不能直接呼叫,需要強制型別轉換成子型別別才能使用go()方法
//高 --- ---- --- > 低
((Student) student).go();//go
//或者
Person obj = new Student();
Student student1 = (Student) obj;//強制轉換
student1.go();//go
/*
子類轉換成父類可能會丟失自己本來的一些方法
*/
Student student2 = new Student();
student2.go();//go
Person person = student2;//自動轉換 低-->高
//這里的 person物件就不能使用原本子類的go()方法了
}
}
總結:
-
父類的參考指向子類的物件(子類的參考不能指向父類的物件)
-
把子類轉換為父類,向上轉型(自動型別轉換)
-
把父類轉換為子類,向下轉型(強制轉換)
基本資料型別的強制轉換可能會丟失精度,類的強制轉換可能會丟失一些方法
-
為什么會存在類的型別轉換?方便方法的呼叫,減少重復代碼,更簡潔
9.static關鍵字詳解
9.1靜態變數和靜態方法
例子1:靜態變數盡量使用類名來訪問
package li.oop.demo07;
//static
public class Student {
private static int age;//靜態的變數
private double score;//非靜態的變數
public static void main(String[] args) {
Student s1 = new Student();
//1.靜態變數盡量使用類名來訪問
//通過類來使用
System.out.println(Student.age);//0
//通過物件來使用
System.out.println(s1.age);//0
System.out.println(s1.score);//0.0
}
}
例子2:靜態方法
-
呼叫非靜態方法需要通過實體物件來呼叫
-
呼叫靜態方法可以直接通過類呼叫,如果如果靜態方法和main方法在同一個類中,甚至可以直接呼叫
-
非靜態方法可以去呼叫靜態方法里的所有東西,而靜態方法不能調非靜態方法
package li.oop.demo07;
//static
public class Student {
private static int age;//靜態的變數
private double score;//非靜態的變數
public void run(){
System.out.println("run");
}
public static void go(){
System.out.println("go");
}
public static void main(String[] args) {
//2.靜態方法
//呼叫非靜態方法需要通過實體物件來呼叫
Student s2 = new Student();
s2.run();
//呼叫靜態方法可以直接通過類呼叫,如果如果靜態方法和main方法在同一個類中,甚至可以直接呼叫
Student.go();
go();
//3.非靜態方法可以去呼叫靜態方法里的所有東西,而靜態方法不能調非靜態方法
//比如在靜態方法main()中不能直接呼叫非靜態方法run()
}
}
9.2靜態代碼塊
package li.oop.demo07;
public class Person {
{
//代碼塊(匿名代碼塊)
}
static{
//靜態代碼塊
}
}
-
如上所示,在類中用大括號括起來的一段沒有名字的代碼塊稱為匿名代碼塊,在括號前加上static關鍵字的代碼塊稱為靜態代碼塊,
-
匿名代碼塊沒有名字,程式在執行時并不能主動去呼叫這些模塊,在創建物件的時候匿名代碼塊自動創建,并且在構造器之前
-
靜態代碼塊是類加載的同時就直接執行,永久只執行一次
例子:匿名代碼塊、靜態代碼塊、構造方法的加載順序
package li.oop.demo07;
public class Person {
{
System.out.println("匿名代碼塊");//代碼塊(匿名代碼塊)
}
static{
System.out.println("靜態代碼塊");//靜態代碼塊
}
public Person() {
System.out.println("構造方法");
}
public static void main(String[] args) {
System.out.println("==========111");
Person person1 = new Person();
System.out.println("==========222");
Person person2 = new Person();
}
}
加載順序:
靜態代碼塊>匿名代碼塊>建構式
靜態代碼塊在person1實體化前就執行了,靜態代碼塊是在類加載的同時就執行了,并且只執行一次
9.3靜態匯入包
package li.oop.demo07;
//靜態匯入包~
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
PS:被final修飾的類不能被其他類繼承
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/500703.html
標籤:其他
上一篇:IOS OpenGL ES GPUImage 影像閥值素描,形成有噪點的素描 GPUImageThresholdSketchFilter
下一篇:Python基礎-23列舉
