09 三大特性

weixin_45729114發表於2020-12-13

封裝

高內聚(類的內部資料操作細節自己完成),低耦合(僅暴露少量的方法給外部使用)

封裝:資料的隱藏:應禁止直接訪問一個物件中資料的實際表示,而應通過操作介面來訪問

屬性私有 get/set private

Alt+Insert自動跳出get和set

public class Demo07定義一個類

public String getName()定義一個方法

public void setName(String name)有了void 不用return 沒有 void 應該就需要 int string 等其他型別

public class Demo04 {

    //屬性私有
    private String name;
    private int id;
    private char sex;

    //提供一些可以操作這個屬性的方法
    //提供一些public的get set方法
    //get 獲得這個資料  set  給這個資料設定值
    public String getName(){
        return this.name;
    }
    public void setName(String name){
        this.name = name;
    }
}
在set裡面做安全性驗證的判斷
import oop.Demo04;

public class Application {
    public static void main(String[] args) {
        Demo04 s1 = new Demo04();

        s1.setName("hxh");

        System.out.println(s1.getName());
    }
}

意義:

  1. 提高程式的安全性,保護資料
  2. 隱藏程式碼的實現細節
  3. 統一介面
  4. 系統可維護增加了

package oop;

public class Demo04 {

//屬性私有
private String name;
private int id;
private int age;
private char sex;

//提供一些可以操作這個屬性的方法
//提供一些public的get set方法
//get 獲得這個資料  set  給這個資料設定值
public String getName(){
    return this.name;
}
public void setName(String name){
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    if (age>120 || age < 0){
        this.age = 3;
    }else{
        this.age = age;
    }

}

}

import oop.Demo04;

public class Application {
    public static void main(String[] args) {
        Demo04 s1 = new Demo04();

        s1.setName("hxh");

        System.out.println(s1.getName());

        s1.setAge(-2);
        System.out.println(s1.getAge());
    }
}

繼承

class 子類名 extends 父類名{

extends:擴充套件 子類是父類的擴充套件,子類繼承父類就會擁有父類的全部方法

public class Student extends Person {}

繼承是類和類之間的一種關係

public—protected—default—private

Java中只有單繼承。一個子只有一個父,一個父可以有多個子

private 私有的東西無法繼承

ctrl+h可以看到樹的結構

系統預設繼承object

父類:

package oop.demo05;

//父類
public class Person {
    protected String name = "hxh";
}

子類:

//派生類 子類
public class Student extends Person {
    private String name = "Han";
    public void test(String name){
        System.out.println(name);
        System.out.println(this.name);//this 呼叫自己
        System.out.println(super.name);//super 呼叫父類
    }
}

主函式:

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.test("韓");
    }
}

輸出結果: 韓
Han
hxh

super注意點

  1. super呼叫父類的構造方法,必須在構造方法的第一個
  2. super只能出現在子類的方法或者構造方法中!
  3. super和this不能同時呼叫構造方法(兩個都要在第一行)

super與this的區別(筆試)

  1. 代表的物件不同:this本身呼叫這個物件 super代表父類物件的引用
  2. 前提:this沒有繼承關係也可以使用 super只能在繼承關係下使用
  3. 構造方法:this本類構造 super父類構造

方法過載

過載(Overload)是指:在一個類裡面,名字相同,而引數不同(引數的數量不同或者數量相同而型別和次序不同)的多個方法。

class ceshi{
	public static void main(String[] args){
		System.out.println(add(2,3));
		System.out.println(add(2,3,10));
	}
	
	//求兩個數的和
	public static int add(int a,int b){
		return a+b;
	}
	
	//求三個數的和
	public static int add(int a,int b,int c){
		return a+b+c;
	}
}
  • 被過載的方法必須引數不同;
  • 被過載的方法可以改變返回值型別;
  • 被過載的方法可以改變訪問修飾符;
  • 方法能夠在同一個類中或者在一個子類中被過載;
  • 無法以返回值型別作為過載函式的區分標準。

方法重寫

在我們認知的繼承關係中,子類可以繼承父類到中的方法而不需要單獨編輯,但是有時候,子類不想原封不動的繼承父類的方法,而是想做一定的修改,這就是所謂的方法重寫;

重寫都是方法的重寫,與屬性無關。

重寫只與非靜態有關,不能用static靜態的

重寫關鍵詞是public。

public class B {
    public void  test(){
        System.out.println("B=>test()");
    }
}

public class A extends B {
    @Override//重寫(註解:有功能的註釋)
    public void test() {
        System.out.println("A=>test()");
    }
}

public class Application {

    //靜態方法和費靜態方法區別很大
    public static void main(String[] args) {
        //方法的呼叫只和左邊定義的資料型別有關
        A a = new A();
        a.test();//A

        //父類的引用指向了子類
        B b = new A();//子類重寫了父類的方法
        b.test();//B
    }
}

結果: A=>test()
A=>test()

重寫:需要有繼承關係,子類重寫父類的方法

  1. 方法名必須相同
  2. 引數列表必須相同
  3. 修飾符:範圍可以擴大,但是不能縮小。public>protected>default>private
  4. 丟擲的異常:範圍可以被縮小,但不能擴大:ClassNoteFoundException----->Exception(大)

重寫子類的方法和父類必須要一致,方法體不同

返回型別與被重寫方法的返回型別可以不相同,但是必須是父類返回值的派生類;
訪問許可權不能比父類中被重寫的方法的訪問許可權更低。(public>protected>預設的>private)
父類的成員方法只能被它的子類重寫;
宣告為 final 的方法不能被重寫;
宣告為 static 的方法不能被重寫,但是能夠被再次宣告;
子類和父類在同一個包中,那麼子類可以重寫父類所有方法,除了宣告為 private 和 final 的方法;
子類和父類不在同一個包中,那麼子類只能夠重寫父類的宣告為 public 和 protected 的非 final 方法;

呼叫的位置看左邊

alt+insert重寫

過載與重寫的區別

概念上:過載是一個類裡面相同名稱不同引數的方法;重寫是繼承中的子類對父類方法的構造;
範圍上:過載在一個類裡,重寫是在有繼承關係的類裡;
許可權要求:過載沒有許可權要求,子類重寫許可權必要>=父類(比如父類是default。子類就只能是public或者default)。

多型

  • **概念:**同一個方法可以根據傳送物件的不同而採用多種不同的行為方式
  • 一個物件的實際型別是確定的,但是可以指向物件的引用的型別有很多
//實際型別均為Student  指向的引用型別卻一個為Student一個為Person
Person person = new Student();
Student student = new Student();
//Student繼承了Person且Student重寫了Person的run方法
person.run();
student.run();
//均為呼叫子類student的方法
//物件能執行哪些方法,主要看物件左邊的型別,和右邊關係不太大,優先執行子類重寫的方法

  • 子類呼叫的方法都是自己的或者繼承父類的!
  • 父類 可以指向子類,但是不能呼叫子類獨有的方法!即可以呼叫子類重寫的方法

注意事項:

  1. 多型是方法的多型屬性沒有多型
  2. 父類和子類有聯絡,型別轉換異常:ClassCastException!
  3. 存在關係:繼承關係,方法需要重寫,父類引用指向子類物件!Father f1=new Son();
    • static靜態方法,屬於類,它不屬於例項
    • final 常量
    • private方法

instanceof和型別轉換

判斷型別是否相似

Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();

System.out.println("s1 instance Student");//true
System.out.println("s2 instance Teacher");//編譯報錯
System.out.println("s1 instance Person");//true
System.out.println("s1 instance Object");//true
System.out.println("s3 instance String");//編譯報錯
System.out.println("==================");
System.out.println("s2 instance Student");//true
System.out.println("s2 instance Teacher");//false
System.out.println("s2 instance Person");//true
System.out.println("s2 instance Object");//true
System.out.println("s3 instance String");//編譯報錯
System.out.println("==================");
System.out.println("s3 instance Student");//true
System.out.println("s3 instance Teacher");//false
System.out.println("s3 instance Person");//true
System.out.println("s3 instance Object");//true
System.out.println("s3 instance String");//false

型別轉換從高到低

型別轉換

  1. 父類引用指向子類的物件
  2. 把子類轉換為父類,向上轉型;自動
  3. 把父類轉換為子類,向下轉型;強制轉換
  4. 方便方法的呼叫,減少重複的程式碼!

詳解static方法

  • 靜態程式碼塊:只執行一次!!!
  • 匿名程式碼塊:賦初值
public class Person{
    {
        System.out.println("匿名程式碼塊")
    }
    static{
        System.out.println("靜態程式碼塊")
    }
    public Person(){
        System.out.println("構造方法")
    }
    public static void main(String[] args){
        Person p1 = new Person();
        System.out.println("=====================")
        Person p2 = new Person();
    }
}

在這裡插入圖片描述

靜態匯入包~

import static java.lang.Math.random;
import static java.lang.Math.PI;
//可以直接使用PI 和random()函式

注意點

  1. 父類的引用指向子類的物件,反之則不能
  2. 把子類轉換為父類,向上轉換,不用強制轉換
//型別之間的轉化 : 父---子
//高               低
Person s1 = new Student();
//高轉低可以直接轉;低轉高,需要強制轉
//
Student s2 = (Student) s1;
s2.go();
//或((Student) s1).go();

  1. 把父類轉換為子類,向下轉換,需要強制轉換

  2. 方便方法的呼叫,減少重複的程式碼

final

final關鍵字宣告類可以把類定義為不能繼承的,即最終類;

final class A{
}
final關鍵字用於修飾方法,該方法不能被子類重寫;

修飾符(public/private) final 返回值型別 方法名(){
}
final關鍵字用於修飾變數,被修飾的變數不能重新賦值,用final修飾相當於將這個量變為常量。

不用強制轉換

//型別之間的轉化 : 父---子
//高               低
Person s1 = new Student();
//高轉低可以直接轉;低轉高,需要強制轉
//
Student s2 = (Student) s1;
s2.go();
//或((Student) s1).go();

  1. 把父類轉換為子類,向下轉換,需要強制轉換

  2. 方便方法的呼叫,減少重複的程式碼

final

final關鍵字宣告類可以把類定義為不能繼承的,即最終類;

final class A{
}
final關鍵字用於修飾方法,該方法不能被子類重寫;

修飾符(public/private) final 返回值型別 方法名(){
}
final關鍵字用於修飾變數,被修飾的變數不能重新賦值,用final修飾相當於將這個量變為常量。