java基礎學習筆記 - 面向物件課時1
p67 封裝詳解
1、封裝的好處:
1)程式設計要追求“高內聚 低耦合”,高內聚就是類的內部資料操作細節自己完成,不許外部干涉;低耦合即僅暴露少量的方法給外部使用
2)複雜性封裝,只對外提供簡單的操作入口, 隱藏程式碼的實現細節,看不到實物複雜的那一面,只展示事物簡單的一面
3)封裝之後形成真正的“物件”,真正的“獨立體”,增強了系統的可維護性
4)封裝之後提高了程式碼的安全性,保護了資料
5)封裝意味著有統一介面,程式可以重複使用,適應性強
2、封裝的實現:屬性私有-get/set
1)類的所有屬性私有化,外部程式不能直接訪問,使用private關鍵字修飾,private修飾的資料只能在當前類中訪問
2)對外提供簡單的操作入口,以後外部程式想要方問物件,必須通過這些簡單的入口進行訪問:
- 對外提供兩個公開的方法作為入口,get/set方法
-set/get方法必須是 public修飾的
- 呼叫set方法修改屬性,set方法只負責修改資料,沒有返回值,通過傳參修改例項變數的值
- 呼叫get方法讀取屬性,有返回值型別,get方法負責返回該型別的資料
- 可以在get/set的方法體中進行安全過濾
3、get/set 的語法:
public 返回值型別 getName(){return field;}
public void setName(形參){ }
public returntype getName(){
return field; }
public void setName(type variable){
this.field = value;
... ... }
//示例3-1
public class D03{ public static void main(String[] args){ Student s = new Student(); //通過方法傳參設定值 s.setName("小明",13,'男'); //列印返回的資料 System.out.println(s.getName()); System.out.println(s.getAge()); System.out.println(s.getSex()); } }View Code//Student類 public class Student{ //屬性私有 private String name; private int age; private char sex; //提供一些可以操作類的屬性的方法 //提供一些 public的 get、set方法 //給資料設定值 public void setName(String name,int age,char sex){ this.name = name; this.age = age; this.sex = sex; } //獲取這個資料 public String getName(){ return this.name; } public int getAge(){ return this.age; } public char getSex(){ return this.sex; } }
//示例3-2:構造器測試,過載,get/set測試
//構造器類 public class Constructor{ public static void main(String[] args){ //呼叫無參構造 Account act1 = new Account(); //通過入口訪問物件的屬性 System.out.println("賬號:" + act1.getActno()); System.out.println("餘額:" + act1.getBalance()); //呼叫有參構造 Account act2 = new Account("110",10000); //訪問物件的屬性 System.out.println("賬號:" + act2.getActno()); System.out.println("餘額:" + act2.getBalance()); //通過入口修改物件的屬性 act2.setActno("act-110"); act2.setBalance(200000); System.out.println("賬號:" + act2.getActno()); System.out.println("餘額:" + act2.getBalance()); } } //定義賬戶類 public class Account{ private String actno; private double actbalance; //構造方法過載 //構造方法初始化例項變數手動或預設 public Account(){ //actno = null; //actbalance = 0.0; } public Account(String s){ actno = s; //actbalance = 0.0; } public Account(double d){ //actno = null; actbalance = d; } public Account(String s, double d){ actno = s; actbalance = d; } //訪問入口get/set public String getActno(){ return actno; } public void setActno(String actno){ this.actno = actno; } public double getBalance(){ return actbalance; } public void setBalance(double balance){ this.actbalance = balance; } }View Code
p68 繼承 extends關鍵字
- 繼承是類和類之間的一種關係,此外類和類之間的關係還有依賴、組合、聚合等
- 繼承的本質是對一批類的抽象,從而實現對現實世界更好的建模
- 繼承關係的兩個類,子類是派生類,父類的基類
- 子類繼承父類,子類是父類的擴充套件,子類擁有父類的全部的屬性和方法
- java中類只有單繼承沒有多繼承,一個子類只能繼承一個父類,一個父類可以擴充套件多個子類
- java中所有的類都預設繼承 Object類
public class 子類名 extends 父類名{ }
2、有 final 修飾的類將不能被繼承
如:pubic final class person{} //該類將不能被繼承
示例4:
public class D04{ public static void main(String[] args){ Student student = new Student(); student.say(); //說了一句話 System.out.println(student.money); //10_0000_0000 } } //Person類 public class Person{ public int money = 10_0000_0000; public void say(){ System.out.println("說了一句話"); } } //Student類 public class Student extends Person{}View Code
p70 重寫override
1、重寫與父類引用的邏輯
-在繼承關係中,子類可以重寫父類的方法,屬性不存在重寫
- 重寫的方法通常是非靜態的、public的
- 父型別的引用可以指向子類物件,但子類的引用不能指向父類物件
- 父型別的引用指向子類物件,相當於建立了一個新的隱藏的子型別的物件,但它沒有該子類的元素,而是隻繼承父類的所有屬性和方法,被重寫的方法在這裡被覆蓋,因此通過父類引用呼叫重寫的方法,相當於呼叫了子類的方法,父類引用也無法真正訪問子類物件
- 如果重寫的方法是靜態的,父類的引用仍然呼叫父類的方法,靜態的方法無法被重寫
2、重寫的語法
- 重寫的方法名、引數列表都必須相同
- 重寫的方法體不同,執行的功能不同
- 修飾符:範圍可以擴大但不能縮小 public>protected>default>private
- 丟擲的異常:範圍可以被縮小但不能擴大 ClassNotFoundException < Exception
3、為什麼需要重寫
- 父類的功能,子類不一定需要或者不一定滿足
4、以下情況不能重寫:
- static 修飾的方法
- private 修飾的方法
- final 定義的常量
//示例7-1:重寫靜態方法的呼叫
public class T07{ public static void main(String[] args){ A a = new A(); B b = new A(); a.test(); //相當於A.test(); b.test(); //相當於B.test(); } } //子類重寫父類的方法 public class A extends B{ public static void test(){ System.out.println("A=>test()"); } } //父類 public class B{ public static void test(){ System.out.println("B=>test()"); } }View Code
//示例7-2:重寫非靜態方法的呼叫
public class T07{ public static void main(String[] args){ A a = new A(); B b = new A(); //非靜態方法的重寫,通過引用呼叫的方法是物件的方法 a.test(); //A=>test() b.test(); //A=>test() } } //子類重寫 public class A extends B{ public void test(){ System.out.println("A=>test()"); } } //父類 public class B{ public void test(){ System.out.println("B=>test()"); } }View Code
//示例7-3:重寫的辯證 父類引用指向子類物件的情況
public class T07{ public static void main(String[] args){ //非靜態方法的重寫 A a = new A(); B b = new A(); //相當於隱藏建立了一個父類物件 //重寫方法時,父類的引用預設呼叫子類的方法 a.test(); //A=>test() b.test(); //A=>test() //顯示建立父類物件,呼叫被重寫的父類方法 B c = new B(); c.test(); //b=>test() //不能呼叫子類獨有的方法 //b.test1(); //可以訪問父類的屬性 、方法 System.out.println(b.name); b.test2(); } } //子類繼承父類 public class A extends B{ //重寫方法 public void test(){ System.out.println("A=>test()"); } //獨有方法 public void test1(){ System.out.println("A1=>test()"); } } //父類 public class B{ String name; public void test(){ System.out.println("B=>test()"); } public void test2(){ System.out.println("B2=>test()"); } }View Code
p71 多型:
- 多型是方法的現象,屬性沒有多型性
- 多型存在於有繼承關係的類中,父類引用指向子類物件
- 一個物件的實際型別是確定的,但指向它的引用的型別可以有多個父類型別
- 子類能呼叫的方法都是它自己的或者繼承父類的
- 父型別的引用可以指向子類物件,但是不能呼叫子類獨有的屬性和方法,只能呼叫子類重寫的方法
- 用強制轉換型別的辦法,使父類引用s2的型別降級,就可以得到一個指向子類物件的子類引用,這時該引用可以完全訪問子類物件
例:Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
((Student)s2).eat();
//示例8:
//測試類 public class T08{ public static void main(String[] args){ //指向物件的引用型別是多種的 Student s1 = new Student(); Person s2 = new Student(); Object s3 = new Student(); s1.run(); //Student run //子類重寫了父類run()方法,S2預設呼叫子類的方法 s2.run(); //Student run //s2不能呼叫子類獨有的方法 //s2.eat(); //用強制轉換型別的辦法,使s2型別降級,可以訪問子類物件,可能會丟失什麼 ((Student)s2).eat(); } } //子類 public class Student extends Person{ //重寫run()方法 public void run(){ System.out.println("Student run"); } //子類的獨有方法 public void eat(){ System.out.println("Student eat"); } } //父類 public class Person{ public void run(){ System.out.println("Person run"); } }View Code
//即使再小的帆也能遠航2021-11-13