day02【final、靜態、多態】

day02【final、靜態、多態】

昨日反饋和回顧
能夠寫出類的繼承格式
    public class 子類 extends 父類{
        
    }
能夠說出Java繼承的特點
    a.單繼承(一個子類只能有一個父類,一個父類可以有多個子類)
    b.多層繼承(一個子類可以有一個父類,該父類也可以有自己的父類)
能夠說出子類調用父類的成員特點
    如果子父類中有同名的成員變量/成員方法,根據Java就近原則,優先調用子類自己成員
    如果子父類中不同名的成員變量/成員方法,根據變量或者方法名字調用,不存在歧義
    構造方法,a.父類的構造子類無法繼承 b.在子類的任何構造第一行,默認調用父類的無參構造,super()
夠說出方法重寫的概念
    方法重載(overload): 在同一個類中,方法名一樣的,參數列表不一樣
    方法重寫(override): 在繼承關係中,子類中有一個和父類除了方法體(權限修飾符),其他一模一樣的方法
能夠說出this可以解決的問題
    在本類中使用:
		this.xxx  訪問本類的成員變量
        this.xxx()    調用本類的成員方法
        this(...) 調用本類的其他構造
         
能夠說出super可以解決的問題
     在子類中使用:
		super.xxx	訪問父類繼承的成員變量
        super.xxx() 調用父類繼承的成員方法
        super(...)  調用父類構造方法  
描述抽象方法的概念
     抽象方法: 只有方法的聲明,沒有方法的實現(加上關鍵字abstract)
     抽象類: 含有抽象方法的類一定是一個抽象類
         	如果是一個抽象類,其中不一定含有抽象方法     
寫出抽象類的格式
     public abstract class 抽象類名{
      	抽象方法
        正常方法    
     }
寫出抽象方法的格式
    public abstract void 抽象方法名();
能夠說出父類抽象方法的存在意義
    抽象類的意義: 給其他子類繼承的,爲子類提供模板(模板設計模式)
    抽象方法的意義: 要求子類必須重寫(如果不重寫,子類還是一個抽象類)    
今日內容介紹
a.關鍵字final
b.關鍵字static 
c.引用類型_接口(重點)    

第一章 final關鍵字

1.1 final關鍵字
final什麼意思: 最終的,不可變的
final在Java中是一個修飾符:
		修飾類,修飾方法,修飾局部變量,修飾成員變量,修飾引用類型變量
1.2 final的作用介紹
  • final修飾類

    final修飾的類,我們稱爲太監類,不能被繼承
    /**
     * 父類
     */
    public final class Fu {
    }
    
    /**
     * 子類報錯了,因爲父類是final類,不能被繼承
     */
    public class Zi extends Fu {
    }
    
    注意: final修飾的類沒有子類,並不是說它不能繼承別的類
    
  • final修飾方法

    final修飾的方法,不能被重寫!! 
    /**
     * 父類
     */
    public class Fu {
        //final修飾方法
        public final void show() {
            System.out.println("show...");
        }
    }
    
    /**
     * 子類
     */
    public class Zi extends Fu{
        //重寫報錯!!!
        //因爲父類的show方法是final修飾的,子類不允許重寫
        @Override
        public void show() {
            System.out.println("重寫後的show...");
        }
    }
    
  • final修飾局部變量

    final修飾的局部變量,表示該變量只能賦值一次
        
    public class TestDemo {
        public static void main(String[] args) {
            //定義一個局部變量
            //給它加上final修飾
            final int num = 10;
            //報錯了!! 因爲final修飾的局部變量,只能賦值一次
            num = 20;
            num = 30;
            num = 40;
            System.out.println(num);
        }
    }    
    注意: 
    	final int num = 10;
    		這句代碼也可以寫出以下兩句
        final int num;
    	num = 10;
        	這也是OK的!!
    

    思考:如下兩種寫法,哪種可以通過編譯?

    寫法1: 報錯!!
    final int c = 0; //只能賦值一次
    for (int i = 0; i < 10; i++) { 
        c = i; // 第二次賦值了,報錯!!!
        System.out.println(c); 
    }
    
    寫法2: 編譯通過!
    for (int i = 0; i < 10; i++) { 
        final int c = i; //c也是final修飾的
        				//因爲c是在循環體中定義的,每次循環都是新的一個c
        System.out.println(c); 
    }
    
  • final修飾引用類型的變量

    final修飾引用類型的變量,表示該引用類型變量中保存的地址值不能改變量
    public class Dog {
        int age = 10;
        String name = "旺財";
    }
    public class TestDog {
        public static void main(String[] args) {
            //1.創建一個引用類型的變量
            // 給引用類型的變量也叫上final
            final Dog d = new Dog(); // d中是對象的地址 0x111
    		//報錯的!!!!因爲final修飾d,表示d中地址值不能改變
            d = new Dog(); //將d中的對象地址 改爲 0x222
        }
    }    
    注意:
    	final修飾d只表示d中地址不能改變,並不代表d中的成員變量值不能改變,
    	以下寫法是正確的:
    		d.age = 20;
            d.name = "來福";
    
  • final修飾成員變量

    final修飾的成員變量,只能賦值一次,必須賦值
    但是賦值可以有兩種選擇:
    	a.定義該成員變量的時候賦值
         public class Student {
            //使用final修飾成員變量
            final int age = 10;
        }
       
            
        b.或者在構造方法中給該成員變量賦值  
         public class Student {
            //使用final修飾成員變量
            final int age;
            //在構造方法中賦值
            public Student(){
                this.age = 20;
            }
        }
    	總之,final修飾的成員變量,必須在創建對象之前有值
    
    

第二章 static關鍵字

2.1 概述
static什麼意思: 靜態關鍵字
static也是一個修飾符,用於修飾類中成員變量/成員方法,static修飾的成員我們稱之爲靜態成員/類成員
    
"被static修飾的成員,不屬於任何一個對象,屬於整個類,被所有對象共享"    

2.2 定義和使用格式
  • 類變量

    類變量:就是使用static修飾的成員變量,我們稱爲類變量/靜態變量
        "被static修飾的成員變量,不屬於任何一個對象,屬於整個類,被所有對象共享" 
    /**
     * 學生類
     */
    public class Student {
        int age;
        String name;
        //靜態變量,類變量,在內存的方法區中的靜態區,只有一份(所有對象共享它)
        static String school = "黑馬程序員";
    
    
        public void show(){
            System.out.println("姓名:"+name+",年齡:"+age+",學校:"+school);
        }
    }
       
    
    public class TestStudent {
        public static void main(String[] args) {
            //1.第一個學生
            Student s1 = new Student();
            s1.name = "孫嘉華";
            s1.age = 18;
    
            s1.show();
    
            System.out.println("============");
            //2.第二個學生
            Student s2 = new Student();
            s2.name = "趙廣順";
            s2.age = 35;
    
            s2.show();
    
            System.out.println("=============");
            //孫嘉華同學去了"傳智專修學院"
            //修改了靜態區中的共享變量,所有對象訪問時,都能看到修改後的結果
            s1.school = "傳智專修學院";
    
            System.out.println("=============");
    
            s1.show();
            s2.show();
    
        }
    } 
    
    

    在這裏插入圖片描述

  • 靜態方法

    靜態方法也叫類方法,static修飾的方法
    特點: 正常的方法必須通過對象才能調用,靜態方法不需要通過對象,通過類名就可以直接調用
     
    /**
     * 計算器類
     */
    public class Calculator {
    
        //計算兩個數的和
        //這就是靜態方法/類方法
        public static int getSum(int a, int b) {
            return a + b;
        }
    }
    public class TestCalculator {
        public static void main(String[] args) {
            //1.創建對象
    //        Calculator cc = new Calculator();
    //        int sum = cc.getSum(111, 999);
    //        System.out.println("求和爲:"+sum);
            //2.靜態方法,直接通過類名調用即可
            int sum = Calculator.getSum(111, 999);
            System.out.println("求和爲:"+sum);
        }
    }    
    
    
2.3 靜態和非靜態之間的相互調用
靜態成員變量
靜態成員方法
    與類是同級,只要類加載到內存,靜態的成員變量/成員方法就存在(對象不一定存在)
    
非靜態成員變量    
非靜態成員方法
    必須創建對象之後才能訪問/調用
    
生命週期看:
	靜態出現的比非靜態要早!!!!
 
 結論:
	a.靜態與靜態之間,非靜態與非靜態之間是可以相互訪問的
    b.非靜態可以訪問靜態,但是靜態不能訪問非靜態       
    靜態的: 秦始皇(出現早)
    非靜態: 我們(出現晚)    

2.4 建議調用格式
靜態的成員變量
    對象名.靜態的成員變量 【可以訪問的,但是我們不建議】
    類名.靜態的成員變量 【建議訪問的方式】
    
靜態的成員方法    
    對象名.靜態的成員方法() 【可以訪問的,但是我們不建議】
    類名.靜態的成員方法() 【建議訪問的方式】
總結: 靜態成員雖然可以通過對象名去訪問/調用,但是我們更建議直接使用類名去訪問/調用    

第三章 接口【重要】

3.1 概述
什麼是接口:
	也是一種引用類型,接口是方法的集合(接口中主要寫方法)       

3.2 定義格式
定義類: class
定義接口: interface   
定義枚舉: enum 【以後講解】
定義註解: @interface 【以後講解】
    
格式:
	public interface 接口名{
          //抽象方法【JDK7】
          //默認方法和靜態方法【JDK8】
          //私有方法和私有靜態方法【JDK9瞭解】 	
    }

/**
 * 定義接口的格式
 */
public interface MyInterface {
    //抽象方法【主要】,只有接口中抽象方法 public abstract 關鍵字可以省略(省略不代表沒有,編譯器會自動添加)
    public abstract void abs1();
    public abstract void abs2();
    //默認方法
    //使用一個關鍵字修飾 default
    public default void m1(){
        System.out.println("接口中的默認方法1");
    }
    public default void m2(){
        System.out.println("接口中的默認方法2");
    }
    //靜態方法
    //使用一個關鍵字 static
    public static void s1(){
        System.out.println("接口中的靜態方法1");
    }
    public static void s2(){
        System.out.println("接口中的靜態方法2");
    }
}

3.3 接口的使用
a.和抽象類類似,接口也是不能創建的對象的
b.接口也是作爲父接口使用的,用於被其他類"實現"的 
c.繼承使用extends關鍵字,實現使用"implements"關鍵字
    
使用方式:
	public class 實現類 implements 接口名{
        //a.必須重寫接口中所有的抽象方法
        //b.選擇性重寫接口中的默認方法,但是重寫後不能有default
        //c.靜態方法沒有重寫的說法,因爲它是通過所在類/接口的名字直接調用的
    }

/**
 * 實現類
 */
public class MyClass implements MyInterface {
    //a.實現類 必須 重寫接口中的所有抽象方法
    @Override
    public void abs1() {
        System.out.println("重寫後的abs1...");
    }

    @Override
    public void abs2() {
        System.out.println("重寫後的abs2...");
    }
    //b.實現類 可以 選擇性重寫默認方法,但是重寫後不能加default
    @Override
    public void m1() {
        System.out.println("重寫後的m1方法..");
    }
    //c.靜態方法通過類名/接口名 直接調用的,沒有重寫這種說法
    public static void s1(){
        System.out.println("實現類中的靜態方法1");
    }
}

測試類
public class TestDemo {
    public static void main(String[] args) {
        //1.創建實現類對象
        MyClass mc = new MyClass();
        //2.抽象方法
        mc.abs1();
        mc.abs2();
        //3.默認方法
        mc.m1(); //調用實現類的重寫方法
        mc.m2(); //調用接口中的默認方法
        //4.靜態方法
        MyInterface.s1(); // 接口的s1
        MyClass.s1(); // 實現類的s1
    }
}    

3.4 接口的多實現
格式:
	public class 實現類 implements 接口1,接口2,..{
        //a.實現類需要重寫所有接口中的所有抽象方法
    		//如果有抽象方法是一樣的,那麼實現類只需要重寫一次
        //b.實現類可以選擇性重寫所有接口中的默認方法
    		//如果接口中有一樣的默認方法,實現類必須重寫一次
        //c.靜態方法沒有重寫的概念,就算多個接口中有一樣的靜態方法
    		//也不衝突,通過各位所在的接口名調用,沒有歧義
    }

/**
 * 實現類:多實現
 */
public class MyClass implements MyInter1,MyInter2{
    //1.抽象方法
    //實現類必須重寫所有接口中的所有抽象方法
    //如果有抽象方法是一樣的,那麼實現類只需要重寫一次
    @Override
    public void abs1() {
        System.out.println("實現類重寫後的抽象方法1..");
    }

    @Override
    public void abs2() {
        System.out.println("實現類重寫後的抽象方法2...");
    }
    //abs方法
    @Override
    public void abs() {
        System.out.println("實現類重寫後的抽象方法s");
    }
    //2.默認方法
    //實現類可以選擇性重寫所有接口中的默認方法
    //如果接口中有一樣的默認方法,實現類必須重寫一次
    @Override
    public void show() {
        System.out.println("實現類重寫後的默認方法show...");
    }
    //3.靜態方法
    //靜態方法沒有重寫的概念,就算多個接口中有一樣的靜態方法
    //也不衝突,通過各位所在的接口名調用,沒有歧義
    //通過MyInter1.s()和通過MyInter2.s()
    public static void s(){
        System.out.println("實現類自己的s方法");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        //創建實現類對象
        MyClass mc = new MyClass();
        //1.抽象方法
        mc.abs1();
        mc.abs2();
        mc.abs();
        //2.默認方法
        mc.show1(); //調用接口1的默認方法show1
        mc.show2(); //調用接口2的默認方法show2
        mc.show(); //調用實現類重寫後的show
        //3.靜態方法
        MyInter1.s();
        MyInter2.s();
        MyClass.s();
    }
}


3.5 實現和繼承的優先級問題
一個類 可以在繼承一個父類的同時實現多個接口(繼承和實現可以同時存在)
格式:
	public class 子類/實現類 extends 父類 implements 接口,...{
        
    }
繼承的優先級 高於 實現,所以必須先extendsimplements
 
public interface MyInter {
    //默認方法
    public default void show(){
        System.out.println("接口的默認方法");
    }
}

public class Fu {
    //正常方法
    public void show(){
        System.out.println("父類的show方法");
    }
}

public class Zi extends Fu implements MyInter{
    //如果父類中的正常方法和接口中的默認方法一樣了
    //a.那麼子類需要不需要對同名的show方法進行重寫呢??
    	//子類可以不重寫該方法,調用優先調用父類中的show
    //b.那麼子類能不能重寫show方法呢???
    	//可以重寫,重寫後,優先調用子類重寫後的方法
    @Override
    public void show() {
        System.out.println("子類重寫後的show...");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        //1.創建子類對象
        Zi zz = new Zi();
        zz.show();
    }
}

3.6 接口的多繼承【瞭解】
類和類之間: 單繼承
類和接口之間: 多實現
接口和接口之間: 多繼承
格式:    
    public interface MyInter extends Inter1,Inter2{
        MyInter接口包含Inter1和Inter2接口所有東西
    }
接口多繼承我們只做瞭解即可,我們在開會中很少寫這種代碼   
    public class MyClass implements MyInter{
        
    }public class MyClass implements Inter1,Inter2{
        
    } 
	效果是一樣

3.7 接口中其他成員特點
a.接口中,無法定義成員變量,但是可以定義常量(字面值常量,public static fina修飾的常量)
    	其值不可以改變,默認使用public static final修飾(可省略,但是編譯器會自動添加)
    【public static final】 數據類型 常量名 =; 【常量名一般純大寫,多個單詞之間使用_分隔】
b.接口中,沒有構造方法,不能創建對象。      
c.接口中,沒有靜態代碼塊【明後天講解】          

3.8 抽象類和接口的練習
案例介紹:

在這裏插入圖片描述

代碼實現
/**
 * 狗類,所有狗的共性內容
 */
public class Dog {
    int age;
    String name;

    public void bark(){
        System.out.println("小狗汪汪~~~");
    }

    public void run(){
        System.out.println("小狗旺旺~~~");
    }
}

/**
 * 緝毒接口,其中包含緝毒抽象方法
 */
public interface JiDu {
    //緝毒抽象方法
    public abstract void jiDu();
}

/**
 * 超級狗(緝毒狗)
 */
public class SuperDog extends Dog implements JiDu{
    //必須重寫接口的緝毒方法
    @Override
    public void jiDu() {
        System.out.println("旺旺,站住,別跑,否則老子開搶了...");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        //1.創建一個緝毒狗
        SuperDog superDog = new SuperDog();
        //2.調用方法
        superDog.bark();
        superDog.run();
        superDog.jiDu();
    }
}

總結

描述final
    修飾類: 該類不能被繼承
    修飾方法: 該方法不能被重寫
    修飾變量: 該變量只能賦值一次
        局部變量: 可以在定義時賦值,可以先定義後賦值
		成員變量: 可以在定義時賦值,可以在構造方法中賦值
		引用類型變量: 表示該引用類型變量的地址值不能改變,但是地址內成員變量的值是可以改變
能夠掌握static關鍵字修飾的變量調用方式
         類名.成員變量名【建議的使用方式】   
能夠掌握static關鍵字修飾的方法調用方式
         類名。成員方法名() 【建議的使用方式】   
            
能夠寫出接口的定義格式
        public interface 接口名{
            //抽象方法【我們最最最常寫】
            //默認方法
            //靜態方法
        }
能夠寫出接口的實現格式
    	public class 實現類 implements 接口名,...{
             //a.重寫所有抽象方法,如果有相同只需要重寫一次
             //b.選擇性重寫默認方法,如果相同必須重寫一次
             //c.靜態方法沒有重寫的概念
        }
能夠說出接口中的其他成員特點
    a.沒有成員變量,只有常量
    		[public static final] 數據類型 常量名 =;
	b.沒有構造方法,也不能創建對象
    c.也沒有靜態代碼塊[明後天搞定!]    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章