day 09 01_final關鍵字,02_多型的概述和講解,03_抽象類的概述和講解,04_介面的概述和講解
01_final關鍵字
/*
final可以修飾類,方法,變數
特點:
final可以修飾類,該類不能被繼承。
final可以修飾方法,該方法不能被重寫。(覆蓋,複寫)
final可以修飾變數,該變數不能被重新賦值。因為這個變數其實常量。
常量:
A:字面值常量
"hello",10,true
B:自定義常量
final int x = 10;
*/
//final class Fu //無法從最終Fu進行繼承
class Fu {
public int num = 10;
public final int num2 = 20;
/*
public final void show() {
}
*/
}
class Zi extends Fu {
public void show() {
num = 100;
System.out.println(num);
//無法為最終變數num2分配值
//num2 = 200;
System.out.println(num2);
}
}
class FinalDemo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
/*
面試題:final修飾區域性變數的問題
基本型別:基本型別的值不能發生改變。
*/
class Student {
int age = 10;
}
class FinalTest {
public static void main(String[] args) {
//區域性變數是基本資料型別
int x = 10;
x = 100;
System.out.println(x);
final int y = 10;
//無法為最終變數y分配值
//y = 100;
System.out.println(y);
System.out.println("--------------");
//區域性變數是引用資料型別
Student s = new Student();
s.age = 100;
System.out.println(s.age);
System.out.println("--------------");
final Student ss = new Student();
System.out.println(ss.age);
ss.age = 100;
System.out.println(ss.age);
//重新分配記憶體空間
//無法為最終變數ss分配值
ss = new Student();
}
}
/*
final修飾變數的初始化時機
A:被final修飾的變數只能賦值一次。
B:在構造方法執行完畢前。(非靜態的常量) (只能在定義時/構造程式碼塊/建構函式中賦值)
*/
class Demo {
//int num = 10;
//final int num2 = 20;
int num;
final int num2;
{
//num2 = 10;
}
public Demo() {
num = 100;
//可以最終變數num2分配值
num2 = 200;
}
}
class FinalTest2 {
public static void main(String[] args) {
Demo d = new Demo();
System.out.println(d.num);
System.out.println(d.num2);
}
}
/*
繼承的程式碼體現
由於繼承中方法有一個現象:方法重寫 (@Override)。
所以,父類的功能,就會被子類給覆蓋調。
有些時候,我們不想讓子類去覆蓋掉父類的功能,只能讓他使用。
這個時候,針對這種情況,Java就提供了一個關鍵字:final
final:最終的意思。常見的是它可以修飾類,方法,變數。
*/
class Fu {
public final void show() {
System.out.println("這裡是絕密資源,任何人都不能修改");
}
}
class Zi extends Fu {
//Zi中的show()無法覆蓋Fu中的show(),這裡會報錯 - Cannot override the final method
public void show() {System.out.println("這是一堆垃圾");
}
}
class ZiDemo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
02_多型的概述和講解
/*
多型:同一個物件(事物),在不同時刻體現出來的不同狀態。
舉例:
貓是貓,貓是動物。
水(液體,固體,氣態)。
多型的前提:
A:要有繼承關係。
B:要有方法重寫。
其實沒有也是可以的,但是如果沒有這個就沒有意義。
動物 d = new 貓();
d.show();
動物 d = new 狗();
d.show();
C:要有父類引用指向子類物件。
父 f = new 子();
用程式碼體現一下多型。
多型中的成員訪問特點:
A:成員變數
編譯看左邊,執行看左邊。
B:構造方法
建立子類物件的時候,訪問父類的構造方法,對父類的資料進行初始化。
C:成員方法
編譯看左邊,執行看右邊。
D:靜態方法
編譯看左邊,執行看左邊。
(靜態和類相關,算不上重寫,所以,訪問還是左邊的)
由於成員方法存在方法重寫,所以它執行看右邊。
*/class Fu {
public int num = 100;
public void show() {
System.out.println("show Fu");
}
public static void function() {
System.out.println("function Fu");
}
}
class Zi extends Fu {
public int num = 1000;
public int num2 = 200;
public void show() {
System.out.println("show Zi");
}
public void method() {
System.out.println("method zi");
}
public static void function() {
System.out.println("function Zi");
}
}
class DuoTaiDemo {
public static void main(String[] args) {
//要有父類引用指向子類物件。
//父 f = new 子();
Fu f = new Zi();
System.out.println(f.num);
//找不到符號
//System.out.println(f.num2);
f.show();
//找不到符號
//f.method();
f.function();
}
}
/*
多型的好處:
A:提高了程式碼的維護性(繼承保證)
B:提高了程式碼的擴充套件性(由多型保證)
貓狗案例程式碼
*/
class Animal {
public void eat(){
System.out.println("eat");
}
public void sleep(){
System.out.println("sleep");
}
}
class Dog extends Animal {
public void eat(){
System.out.println("狗吃肉");
}
public void sleep(){
System.out.println("狗站著睡覺");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("貓吃魚");
}
public void sleep() {
System.out.println("貓趴著睡覺");
}
}
class Pig extends Animal {
public void eat() {
System.out.println("豬吃白菜");
}
public void sleep() {
System.out.println("豬側著睡");
}
}
//針對動物操作的工具類
class AnimalTool {
private AnimalTool(){}
/*
//呼叫貓的功能
public static void useCat(Cat c) {
c.eat();
c.sleep();
}
//呼叫狗的功能
public static void useDog(Dog d) {
d.eat();
d.sleep();
}
//呼叫豬的功能
public static void usePig(Pig p) {
p.eat();
p.sleep();
}
*/
public static void useAnimal(Animal a) {
a.eat();
a.sleep();
}
}
class DuoTaiDemo2 {
public static void main(String[] args) {
//我喜歡貓,就養了一隻
Cat c = new Cat();
c.eat();
c.sleep();
//我很喜歡貓,所以,又養了一隻
Cat c2 = new Cat();
c2.eat();
c2.sleep();
//我特別喜歡貓,又養了一隻
Cat c3 = new Cat();
c3.eat();
c3.sleep();
//...
System.out.println("--------------");
//問題來了,我養了很多隻貓,每次建立物件是可以接受的
//但是呢?呼叫方法,你不覺得很相似嗎?僅僅是物件名不一樣。
//我們準備用方法改進
//呼叫方式改進版本
//useCat(c);
//useCat(c2);
//useCat(c3);
//AnimalTool.useCat(c);
//AnimalTool.useCat(c2);
//AnimalTool.useCat(c3);
AnimalTool.useAnimal(c);
AnimalTool.useAnimal(c2);
AnimalTool.useAnimal(c3);
System.out.println("--------------");
//我喜歡狗
Dog d = new Dog();
Dog d2 = new Dog();
Dog d3 = new Dog();
//AnimalTool.useDog(d);
//AnimalTool.useDog(d2);
//AnimalTool.useDog(d3);
AnimalTool.useAnimal(d);
AnimalTool.useAnimal(d2);
AnimalTool.useAnimal(d3);
System.out.println("--------------");
//我喜歡寵物豬
//定義一個豬類,它要繼承自動物,提供兩個方法,並且還得在工具類中新增該類方法呼叫
Pig p = new Pig();
Pig p2 = new Pig();
Pig p3 = new Pig();
//AnimalTool.usePig(p);
//AnimalTool.usePig(p2);
//AnimalTool.usePig(p3);
AnimalTool.useAnimal(p);
AnimalTool.useAnimal(p2);
AnimalTool.useAnimal(p3);
System.out.println("--------------");
//我喜歡寵物狼,老虎,豹子...
//定義對應的類,繼承自動物,提供對應的方法重寫,並在工具類新增方法呼叫
//前面幾個必須寫,我是沒有意見的
//但是,工具類每次都改,麻煩不
//我就想,你能不能不改了
//太簡單:把所有的動物都寫上。問題是名字是什麼呢?到底哪些需要被加入呢?
//改用另一種解決方案。
}
/*
//呼叫貓的功能
public static void useCat(Cat c) {
c.eat();
c.sleep();
}
//呼叫狗的功能
public static void useDog(Dog d) {
d.eat();
d.sleep();
}
*/
}
/*
多型的弊端:
不能使用子類的特有功能。
*/
class Fu {
public void show() {
System.out.println("show fu");
}
}
class Zi extends Fu {
public void show() {
System.out.println("show zi");
}
public void method() {
System.out.println("method zi");
}
}
class DuoTaiDemo3 {
public static void main(String[] args) {
//測試
Fu f = new Zi();
f.show();
f.method();
}
}
/*
多型的弊端:
不能使用子類的特有功能。
我就想使用子類的特有功能?行不行?
行。
怎麼用呢?
A:建立子類物件呼叫方法即可。(可以,但是很多時候不合理。而且,太佔記憶體了)
B:把父類的引用強制轉換為子類的引用。(向下轉型)
物件間的轉型問題:
向上轉型:
Fu f = new Zi();
向下轉型:
Zi z = (Zi)f; //要求該f必須是能夠轉換為Zi的。
*/
class Fu {
public void show() {
System.out.println("show fu");
}
}
class Zi extends Fu {
public void show() {
System.out.println("show zi");
}
public void method() {
System.out.println("method zi");
}
}
class DuoTaiDemo4 {
public static void main(String[] args) {
//測試
Fu f = new Zi();
f.show();
//f.method();
//建立子類物件
//Zi z = new Zi();
//z.show();
//z.method();
//你能夠把子的物件賦值給父親,那麼我能不能把父的引用賦值給子的引用呢?
//如果可以,但是如下
Zi z = (Zi)f;
z.show();
z.method();
}
}
/*
ClassCastException:型別轉換異常
一般在多型的向下轉型中容易出現
*/
class Animal {
public void eat(){}
}
class Dog extends Animal {
public void eat() {}
public void lookDoor() {
}
}
class Cat extends Animal {
public void eat() {
}
public void playGame() {
}
}
class DuoTaiDemo5 {
public static void main(String[] args) {
//記憶體中的是狗
Animal a = new Dog();
Dog d = (Dog)a;
//記憶體中是貓
a = new Cat();
Cat c = (Cat)a;
//記憶體中是貓
Dog dd = (Dog)a; //ClassCastException
}
}
/*
多型練習:貓狗案例
*/
class Animal {
public void eat(){
System.out.println("吃飯");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃肉");
}
public void lookDoor() {
System.out.println("狗看門");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("貓吃魚");
}
public void playGame() {
System.out.println("貓捉迷藏");
}
}
class DuoTaiTest {
public static void main(String[] args) {
//定義為狗
Animal a = new Dog();
a.eat();
System.out.println("--------------");
//還原成狗
Dog d = (Dog)a;
d.eat();
d.lookDoor();
System.out.println("--------------");
//變成貓
a = new Cat();
a.eat();
System.out.println("--------------");
//還原成貓
Cat c = (Cat)a;
c.eat();
c.playGame();
System.out.println("--------------");
//演示錯誤的內容
//Dog dd = new Animal();
//Dog ddd = new Cat();
//ClassCastException
//Dog dd = (Dog)a;
}
}
/*
不同地方飲食文化不同的案例
*/
class Person {
public void eat() {
System.out.println("吃飯");
}
}
class SouthPerson extends Person {
public void eat() {
System.out.println("炒菜,吃米飯");
}
public void jingShang() {
System.out.println("經商");
}
}
class NorthPerson extends Person {
public void eat() {
System.out.println("燉菜,吃饅頭");
}
public void yanJiu() {
System.out.println("研究");
}
}
class DuoTaiTest2 {
public static void main(String[] args) {
//測試
//南方人
Person p = new SouthPerson();
p.eat();
System.out.println("-------------");
SouthPerson sp = (SouthPerson)p;
sp.eat();
sp.jingShang();
System.out.println("-------------");
//北方人
p = new NorthPerson();
p.eat();
System.out.println("-------------");
NorthPerson np = (NorthPerson)p;
np.eat();
np.yanJiu();
}
}
/*
看程式寫結果:先判斷有沒有問題,如果沒有,寫出結果
*/
class Fu {
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu {
public void show() {
System.out.println("zi show");
}
public void method() {
System.out.println("zi method");
}
}
class DuoTaiTest3 {
public static void main(String[] args) {
Fu f = new Zi();
//找不到符號
//f.method();
f.show();
}
}
/*
看程式寫結果:先判斷有沒有問題,如果沒有,寫出結果
多型的成員訪問特點:
方法:編譯看左邊,執行看右邊。
繼承的時候:
子類中有和父類中一樣的方法,叫重寫。
子類中沒有父親中出現過的方法,方法就被繼承過來了。
*/
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
/*
public void show() {
show2();
}
*/
public void show2() {
System.out.println("愛");
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");
}
}
public class DuoTaiTest4 {
public static void main(String[] args) {
A a = new B();
a.show();
B b = new C();
b.show();
}
}
03_抽象類的概述和講解
/*
抽象類的概述:
動物不應該定義為具體的東西,而且動物中的吃,睡等也不應該是具體的。
我們把一個不是具體的功能稱為抽象的功能,而一個類中如果有抽象的功能,該類必須是抽象類。
抽象類的特點:
A:抽象類和抽象方法必須用abstract關鍵字修飾
B:抽象類中不一定有抽象方法,但是有抽象方法的類必須定義為抽象類
C:抽象類不能例項化
因為它不是具體的。
抽象類有構造方法,但是不能例項化?構造方法的作用是什麼呢?
用於子類訪問父類資料的初始化
D:抽象的子類
a:如果不想重寫抽象方法,該子類是一個抽象類。
b:重寫所有的抽象方法,這個時候子類是一個具體的類。
抽象類的例項化其實是靠具體的子類實現的。是多型的方式。
Animal a = new Cat();
*/
//abstract class Animal //抽象類的宣告格式
abstract class Animal {
//抽象方法
//public abstract void eat(){} //空方法體,這個會報錯。抽象方法不能有主體
public abstract void eat();
public Animal(){}
}
//子類是抽象類
abstract class Dog extends Animal {}
//子類是具體類,重寫抽象方法
class Cat extends Animal {
public void eat() {
System.out.println("貓吃魚");
}
}
class AbstractDemo {
public static void main(String[] args) {
//建立物件
//Animal是抽象的; 無法例項化
//Animal a = new Animal();
//通過多型的方式
Animal a = new Cat();
a.eat();
}
}
/*
抽象類的成員特點:
成員變數:既可以是變數,也可以是常量。
構造方法:有。
用於子類訪問父類資料的初始化。
成員方法:既可以是抽象的,也可以是非抽象的。
抽象類的成員方法特性:
A:抽象方法 強制要求子類做的事情。
B:非抽象方法 子類繼承的事情,提高程式碼複用性。
*/
abstract class Animal {
public int num = 10;
public final int num2 = 20;
public Animal() {}
public Animal(String name,int age){}
public abstract void show();
public void method() {
System.out.println("method");
}
}
class Dog extends Animal {
public void show() {
System.out.println("show Dog");
}
}
class AbstractDemo2 {
public static void main(String[] args) {
//建立物件
Animal a = new Dog();
a.num = 100;
System.out.println(a.num);
//a.num2 = 200;
System.out.println(a.num2);
System.out.println("--------------");
a.show();
a.method();
}
}
/*
一個類如果沒有抽象方法,可不可以定義為抽象類?如果可以,有什麼意義?
A:可以。
B:不讓建立物件。
abstract不能和哪些關鍵字共存?
private 衝突
final 衝突
static 無意義
*/
abstract class Fu {
//public abstract void show();
//非法的修飾符組合: abstract和private
//private abstract void show();
//非法的修飾符組合
//final abstract void show();
//非法的修飾符組合
static abstract void show();
public static void method() {
System.out.println("method");
}
}
class Zi extends Fu {
public void show() {}
}
class AbstractDemo3 {
public static void main(String[] args) {
Fu.method();
}
}
/*
貓狗案例
具體事物:貓,狗
共性:姓名,年齡,吃飯
分析:從具體到抽象
貓:
成員變數:姓名,年齡
構造方法:無參,帶參
成員方法:吃飯(貓吃魚)
狗:
成員變數:姓名,年齡
構造方法:無參,帶參
成員方法:吃飯(狗吃肉)
因為有共性的內容,所以就提取了一個父類。動物。
但是又由於吃飯的內容不一樣,所以吃飯的方法是抽象的,
而方法是抽象的類,類就必須定義為抽象類。
抽象動物類:
成員變數:姓名,年齡
構造方法:無參,帶參
成員方法:吃飯();
實現:從抽象到具體
動物類:
成員變數:姓名,年齡
構造方法:無參,帶參
成員方法:吃飯();
狗類:
繼承自動物類
重寫吃飯();
貓類:
繼承自動物類
重寫吃飯();
*/
//定義抽象的動物類
abstract class Animal {
//姓名
private String name;
//年齡
private int age;
public Animal() {}
public Animal(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//定義一個抽象方法
public abstract void eat();
}
//定義具體的狗類
class Dog extends Animal {
public Dog() {}
public Dog(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("狗吃肉");
}
}
//定義具體的貓類
class Cat extends Animal {
public Cat() {}
public Cat(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("貓吃魚");
}
}
//測試類
class AbstractTest {
public static void main(String[] args) {
//測試狗類
//具體類用法
//方式1:
Dog d = new Dog();
d.setName("旺財");
d.setAge(3);
System.out.println(d.getName()+"---"+d.getAge());
d.eat();
//方式2:
Dog d2 = new Dog("旺財",3);
System.out.println(d2.getName()+"---"+d2.getAge());
d2.eat();
System.out.println("---------------------------");
Animal a = new Dog();
a.setName("旺財");
a.setAge(3);
System.out.println(a.getName()+"---"+a.getAge());
a.eat();
Animal a2 = new Dog("旺財",3);
System.out.println(a2.getName()+"---"+a2.getAge());
a2.eat();
//練習:測試貓類
}
}
/*
老師案例
具體事物:基礎班老師,就業班老師
共性:姓名,年齡,講課。
分析:
基礎班老師
姓名,年齡
講課。
就業班老師
姓名,年齡
講課。
實現:
老師類
基礎班老師
就業班老師
*/
//定義抽象的老師類
abstract class Teacher {
//姓名
private String name;
//年齡
private int age;
public Teacher() {}
public Teacher(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//抽象方法
public abstract void teach();
}
//基礎班老師類
class BasicTeacher extends Teacher {
public BasicTeacher(){}
public BasicTeacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println("基礎班老師講解JavaSE");
}
}
//就業班老師類
class WorkTeacher extends Teacher {
public WorkTeacher(){}
public WorkTeacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println("就業班老師講解JavaEE");
}
}
class AbstractTest2 {
public static void main(String[] args) {
//具體的類測試,自己玩
//測試(多型)
//基礎班老師
Teacher t = new BasicTeacher();
t.setName("劉意");
t.setAge(30);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
t = new BasicTeacher("劉意",30);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
//就業班老師
t = new WorkTeacher();
t.setName("林青霞");
t.setAge(27);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
t = new WorkTeacher("林青霞",27);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
}
}
/*
學生案例
具體事務:基礎班學員,就業班學員
共性:姓名,年齡,班級,學習,吃飯
分析:
基礎班學員
成員變數:姓名,年齡,班級
成員方法:學習,吃飯
就業班學員
成員變數:姓名,年齡,班級
成員方法:學習,吃飯
得到一個學員類。
成員變數:姓名,年齡,班級
成員方法:學習,吃飯
實現:
學員類
基礎班學員
就業班學員
*/
//定義抽象學員類
abstract class Student {
//姓名
private String name;
//年齡
private int age;
//班級
private String grand;
public Student() {}
public Student(String name,int age,String grand) {
this.name = name;
this.age = age;
this.grand = grand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGrand() {
return grand;
}
public void setGrand(String grand) {
this.grand = grand;
}
//學習
public abstract void study();
//吃飯
public void eat() {
System.out.println("學習累了,就該吃飯");
}
}
//具體基礎班學員類
class BasicStudent extends Student {
public BasicStudent() {}
public BasicStudent(String name,int age,String grand) {
super(name,age,grand);
}
public void study() {
System.out.println("基礎班學員學習的是JavaSE");
}
}
//具體就業班學員類
class WorkStudent extends Student {
public WorkStudent() {}
public WorkStudent(String name,int age,String grand) {
super(name,age,grand);
}
public void study() {
System.out.println("就業班學員學習的是JavaEE");
}
}
class AbstractTest3 {
public static void main(String[] args) {
//我僅僅測試基礎班學員
//按照多型的方式測試
Student s = new BasicStudent();
s.setName("林青霞");
s.setAge(27);
s.setGrand("1111");
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());
s.study();
s.eat();
System.out.println("--------------");
s = new BasicStudent("武鑫",48,"1111");
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());
s.study();
s.eat();
//就業班測試留給自己玩
}
}
/*
假如我們在開發一個系統時需要對員工類進行設計,員工包含3個屬性:姓名、工號以及工資。
經理也是員工,除了含有員工的屬性外,另為還有一個獎金屬性。
請使用繼承的思想設計出員工類和經理類。要求類中提供必要的方法進行屬性訪問。
分析:
普通員工類
成員變數:姓名、工號以及工資。
成員方法:工作
經理類:
成員變數:姓名、工號以及工資,獎金屬性
成員方法:工作
實現:
員工類:
普通員工類:
經理類:
*/
//定義員工類
abstract class Employee {
//姓名、工號以及工資
private String name;
private String id;
private int salary;
public Employee() {}
public Employee(String name,String id,int salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
//工作
public abstract void work();
}
//普通員工類
class Programmer extends Employee {
public Programmer(){}
public Programmer(String name,String id,int salary) {
super(name,id,salary);
}
public void work() {
System.out.println("按照需求寫程式碼");
}
}
//經理類
class Manager extends Employee {
//獎金
private int money; //bonus 獎金
public Manager(){}
public Manager(String name,String id,int salary,int money) {
super(name,id,salary);
this.money = money;
}
public void work() {
System.out.println("跟客戶談需求");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
class AbstractTest4 {
public static void main(String[] args) {
//測試普通員工
Employee emp = new Programmer();
emp.setName("林青霞");
emp.setId("czbk001");
emp.setSalary(18000);
System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());
emp.work();
System.out.println("-------------");
emp = new Programmer("林青霞","czbk001",18000);
System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());
emp.work();
System.out.println("-------------");
/*
emp = new Manager();
emp.setName("劉意");
emp.setId("czbk002");
emp.setSalary(8000);
emp.setMoney(2000);
*/
//由於子類有特有的內容,所以我們用子類來測試
Manager m = new Manager();
m.setName("劉意");
m.setId("czbk002");
m.setSalary(8000);
m.setMoney(2000);
System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
m.work();
System.out.println("-------------");
//通過構造方法賦值
m = new Manager("劉意","czbk002",8000,2000);
System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
m.work();
}
}
04_介面的概述和講解
/*
介面的特點:
A:介面用關鍵字interface表示
interface 介面名 {}
B:類實現介面用implements表示
class 類名 implements 介面名 {}
C:介面不能例項化
那麼,介面如何例項化呢?
按照多型的方式來例項化。
D:介面的子類
a:可以是抽象類。但是意義不大。
b:可以是具體類。要重寫介面中的所有抽象方法。(推薦方案)
由此可見:
A:具體類多型(幾乎沒有)
B:抽象類多型(常用)
C:介面多型(最常用)
*/
//定義動物培訓介面
interface AnimalTrain {
public abstract void jump();
}
//抽象類實現介面
abstract class Dog implements AnimalTrain {
}
//具體類實現介面
class Cat implements AnimalTrain {
public void jump() {
System.out.println("貓可以跳高了");
}
}
class InterfaceDemo {
public static void main(String[] args) {
//AnimalTrain是抽象的; 無法例項化
//AnimalTrain at = new AnimalTrain();
//at.jump();
AnimalTrain at = new Cat();
at.jump();
}
}
/*
介面成員特點
成員變數;只能是常量,並且是靜態的。
預設修飾符:public static final
建議:自己手動給出。
構造方法:介面沒有構造方法。
成員方法:只能是抽象方法。
預設修飾符:public abstract
建議:自己手動給出。
所有的類都預設繼承自一個類:Object。
類 Object 是類層次結構的根類。每個類都使用 Object 作為超類。
*/
interface Inter {
public int num = 10;
public final int num2 = 20;
public static final int num3 = 30;
//錯誤: 需要<識別符號>
//public Inter() {} //報錯 - Interfaces cannot have constructors
//介面方法不能帶有主體
//public void show() {}
//abstract void show(); //預設public
public void show(); //預設abstract
}
//介面名+Impl這種格式是介面的實現類格式
/*
class InterImpl implements Inter {
public InterImpl() {
super(); //此處呼叫的是Object的構造方法,任何類的根類都是Object
}
}
*/
class InterImpl extends Object implements Inter {
public InterImpl() {
super(); //此處呼叫的是Object的構造方法,任何類的根類都是Object
}
public void show() {}
}
//測試類
class InterfaceDemo2 {
public static void main(String[] args) {
//建立物件
Inter i = new InterImpl();
System.out.println(i.num);
System.out.println(i.num2);
//i.num = 100;
//i.num2 = 200;
//System.out.println(i.num); //無法為最終變數num分配值
//System.out.println(i.num2);//無法為最終變數num2分配值
System.out.println(Inter.num);
System.out.println(Inter.num2);
System.out.println("--------------");
}
}
/*
類與類:
繼承關係,只能單繼承,可以多層繼承。
類與介面:
實現關係,可以單實現,也可以多實現。
並且還可以在繼承一個類的同時實現多個介面。
介面與介面:
繼承關係,可以單繼承,也可以多繼承。
*/
interface Father {
public abstract void show();
}
interface Mother {
public abstract void show2();
}
interface Sister extends Father,Mother {
}
//class Son implements Father,Mother //多實現
class Son extends Object implements Father,Mother {
public void show() {
System.out.println("show son");
}
public void show2() {
System.out.println("show2 son");
}
}
class InterfaceDemo3 {
public static void main(String[] args) {
//建立物件
Father f = new Son();
f.show();
//f.show2(); //報錯
Mother m = new Son();
//m.show(); //報錯
m.show2();
}
}
/*
貓狗案例,加入跳高的額外功能
分析:從具體到抽象
貓:
姓名,年齡
吃飯,睡覺
狗:
姓名,年齡
吃飯,睡覺
由於有共性功能,所以,我們抽取出一個父類:
動物:
姓名,年齡
吃飯();
睡覺(){}
貓:繼承自動物
狗:繼承自動物
跳高的額外功能是一個新的擴充套件功能,所以我們要定義一個介面
介面:
跳高
部分貓:實現跳高
部分狗:實現跳高
實現;
從抽象到具體
使用:
使用具體類
*/
//定義跳高介面
interface Jumpping {
//跳高功能
public abstract void jump();
}
//定義抽象類
abstract class Animal {
//姓名
private String name;
//年齡
private int age;
public Animal() {}
public Animal(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//吃飯();
public abstract void eat();
//睡覺(){}
public void sleep() {
System.out.println("睡覺覺了");
}
}
//具體貓類
class Cat extends Animal {
public Cat(){}
public Cat(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("貓吃魚");
}
}
//具體狗類
class Dog extends Animal {
public Dog(){}
public Dog(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("狗吃肉");
}
}
//有跳高功能的貓
class JumpCat extends Cat implements Jumpping {
public JumpCat() {}
public JumpCat(String name,int age) {
super(name,age);
}
public void jump() {
System.out.println("跳高貓");
}
}
//有跳高功能的狗
class JumpDog extends Dog implements Jumpping {
public JumpDog() {}
public JumpDog(String name,int age) {
super(name,age);
}
public void jump() {
System.out.println("跳高狗");
}
}
class InterfaceTest {
public static void main(String[] args) {
//定義跳高貓並測試
JumpCat jc = new JumpCat();
jc.setName("哆啦A夢");
jc.setAge(3);
System.out.println(jc.getName()+"---"+jc.getAge());
jc.eat();
jc.sleep();
jc.jump();
System.out.println("-----------------");
JumpCat jc2 = new JumpCat("加菲貓",2);
System.out.println(jc2.getName()+"---"+jc2.getAge());
jc2.eat();
jc2.sleep();
jc2.jump();
//定義跳高狗並進行測試的事情自己完成。
}
}
/*
老師和學生案例,加入抽菸的額外功能
分析:從具體到抽象
老師:姓名,年齡,吃飯,睡覺
學生:姓名,年齡,吃飯,睡覺
由於有共性功能,我們提取出一個父類,人類。
人類:
姓名,年齡
吃飯();
睡覺(){}
抽菸的額外功能不是人或者老師,或者學生一開始就應該具備的,所以,我們把它定義為介面
抽菸介面。
部分老師抽菸:實現抽菸介面
部分學生抽菸:實現抽菸介面
實現:從抽象到具體
使用:具體
*/
//定義抽菸介面
interface Smoking {
//抽菸的抽象方法
public abstract void smoke();
}
//定義抽象人類
abstract class Person {
//姓名
private String name;
//年齡
private int age;
public Person() {}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//吃飯();
public abstract void eat();
//睡覺(){}
public void sleep() {
System.out.println("睡覺覺了");
}
}
//具體老師類
class Teacher extends Person {
public Teacher() {}
public Teacher(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("吃大白菜");
}
}
//具體學生類
class Student extends Person {
public Student() {}
public Student(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("吃紅燒肉");
}
}
//抽菸的老師
class SmokingTeacher extends Teacher implements Smoking {
public SmokingTeacher() {}
public SmokingTeacher(String name,int age) {
super(name,age);
}
public void smoke() {
System.out.println("抽菸的老師");
}
}
//抽菸的學生
class SmokingStudent extends Student implements Smoking {
public SmokingStudent() {}
public SmokingStudent(String name,int age) {
super(name,age);
}
public void smoke() {
System.out.println("抽菸的學生");
}
}
class InterfaceTest2 {
public static void main(String[] args) {
//測試學生
SmokingStudent ss = new SmokingStudent();
ss.setName("林青霞");
ss.setAge(27);
System.out.println(ss.getName()+"---"+ss.getAge());
ss.eat();
ss.sleep();
ss.smoke();
System.out.println("-------------------");
SmokingStudent ss2 = new SmokingStudent("劉意",30);
System.out.println(ss2.getName()+"---"+ss2.getAge());
ss2.eat();
ss2.sleep();
ss2.smoke();
//測試老師留給自己練習
}
}
抽象類和介面的區別:
A:成員區別
抽象類:
成員變數:可以變數,也可以常量
構造方法:有
成員方法:可以抽象,也可以非抽象
介面:
成員變數:只可以常量
成員方法:只可以抽象
B:關係區別
類與類
繼承,單繼承
類與介面
實現,單實現,多實現
介面與介面
繼承,單繼承,多繼承
C:設計理念區別
抽象類 被繼承體現的是:”is a”的關係。抽象類中定義的是該繼承體系的共性功能。
介面 被實現體現的是:”like a”的關係。介面中定義的是該繼承體系的擴充套件功能。
1:final關鍵字(掌握)
(1)是最終的意思,可以修飾類,方法,變數。
(2)特點:
A:它修飾的類,不能被繼承。
B:它修飾的方法,不能被重寫。
C:它修飾的變數,是一個常量。
(3)面試相關:
A:區域性變數
a:基本型別 值不能發生改變
b:引用型別 地址值不能發生改變,但是物件的內容是可以改變的
B:初始化時機
a:只能初始化一次。
b:常見的給值
定義的時候。(推薦)
構造方法中。
2:多型(掌握)
(1)同一個物件在不同時刻體現出來的不同狀態。
(2)多型的前提:
A:有繼承或者實現關係。
B:有方法重寫。
C:有父類或者父介面引用指向子類物件。
多型的分類:
a:具體類多型
class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
b:抽象類多型
abstract class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
c:介面多型
interface Fu {}
class Zi implements Fu {}
Fu f = new Zi();
(3)多型中的成員訪問特點
A:成員變數
編譯看左邊,執行看左邊
B:構造方法
子類的構造都會預設訪問父類構造
C:成員方法
編譯看左邊,執行看右邊
D:靜態方法
編譯看左邊,執行看左邊
為什麼?
因為成員方法有重寫。
(4)多型的好處:
A:提高程式碼的維護性(繼承體現)
B:提高程式碼的擴充套件性(多型體現)
(5)多型的弊端:
父不能使用子的特有功能。
現象:
子可以當作父使用,父不能當作子使用。
(6)多型中的轉型
A:向上轉型
從子到父
B:向下轉型
從父到子
(7)孔子裝爹的案例幫助大家理解多型
(8)多型的練習
A:貓狗案例
B:老師和學生案例
3:抽象類(掌握)
(1)把多個共性的東西提取到一個類中,這是繼承的做法。
但是呢,這多個共性的東西,在有些時候,方法宣告一樣,但是方法體。
也就是說,方法宣告一樣,但是每個具體的物件在具體實現的時候內容不一樣。
所以,我們在定義這些共性的方法的時候,就不能給出具體的方法體。
而一個沒有具體的方法體的方法是抽象的方法。
在一個類中如果有抽象方法,該類必須定義為抽象類。
(2)抽象類的特點
A:抽象類和抽象方法必須用關鍵字abstract修飾
B:抽象類中不一定有抽象方法,但是有抽象方法的類一定是抽象類
C:抽象類不能例項化
D:抽象類的子類
a:是一個抽象類。
b:是一個具體類。這個類必須重寫抽象類中的所有抽象方法。
(3)抽象類的成員特點:
A:成員變數
有變數,有常量
B:構造方法
有構造方法
C:成員方法
有抽象,有非抽象
(4)抽象類的練習
A:貓狗案例練習
B:老師案例練習
C:學生案例練習
D:員工案例練習
(5)抽象類的幾個小問題
A:抽象類有構造方法,不能例項化,那麼構造方法有什麼用?
用於子類訪問父類資料的初始化
B:一個類如果沒有抽象方法,卻定義為了抽象類,有什麼用?
為了不讓建立物件
C:abstract不能和哪些關鍵字共存
a:final 衝突
b:private 衝突
c:static 無意義
4:介面(掌握)
(1)回顧貓狗案例,它們僅僅提供一些基本功能。
比如:貓鑽火圈,狗跳高等功能,不是動物本身就具備的,
是在後面的培養中訓練出來的,這種額外的功能,java提供了介面表示。
(2)介面的特點:
A:介面用關鍵