內部類和泛型

內部類:
實例內部類
靜態內部類
匿名內部類
本地內部類–》基本不會使用到在方法裏定義的一個類。
實例內部類:
面試問題:1.如何拿到實例內部類的對象?

		/*OuterClass 外部類
         InnerClass內部類
         外部類名.實例內部類類名 in=外部類對象的引用.new 內部類對象
        **/
        OuterClass outerClass=new OuterClass();
        //訪問實例內部類我們需要通過外部類的引用,包括類名去訪問
        OuterClass.InnerClass in=outerClass.new InnerClass();

2.在實例內部類當中,是否可以定義static的數據成員?
不能!是錯誤的
可以添加的是 static final在實例成員內部必須是在編譯時期內就確定的(常量) 不能僅添加 static
3.內部類可以訪問所有的外部類成員包括私有的。
4.實例內部類是否有額外的開銷?
有額外開銷,因爲內部類中包含了外部類的 this
InnerClass是OuterClass 成員
OuterClass .this->拿到外部類名.this拿到外部類的引用。可以在內部類中訪問到外部類的對象。因爲用類名可以 . 證明是一個靜態的。this從本質上說是靜態的
一個class會生成一個class文件。java高效率,使用哪一個纔會去加載。
內部類生成的字節碼文件文件名是:OuterClass$InnerClass.class
靜態內部類:

  //此時我們拿到靜態內部類的對象,被static修飾只需要通過類名獲取即可
        OuterClass2.InnerClass2 in=new OuterClass2.InnerClass2();

靜態內部類-》static 頂級嵌套類
1.如何拿到靜態內部類的實例對象?
外部類名 . 靜態內部類名 in = new 外部類類名 . 內部類();
靜態的內部類,訪問外部的靜態量。我們只需要使用OuterClass2.InnerClass2 .即可。
2.靜態內部類能否訪問外部類的成員?
可以直接訪問到外部類的靜態成員,不能直接訪問實例成員但可以間接進行訪問,
訪問方法,我們在內部類中建一個帶一個參數的構造方法

public InnerClass2 ( OuterClass2 out ){ }

然後在main函數中我們先獲取外部類的對象。
OuterClass2 outerClass2=new OuterClass2();
獲取到之後可以以傳參的形式將外部類的引用傳入到內部類中
OuterClass2.InnerClass2 in=new OuterClass2.InnerClass2(outerClass2);
此時我們去接收外部類傳入的對象。
OuterClass2 o=null;定義一個接收值。
public InnerClass2(OuterClass2 out){
this.o=out;
};
//現在o就是我們外部類的引用可以進行一個訪問到外部類的
// 實例成員

匿名內部類:(線程)

class MyThread{
  public void func(){
      System.out.println("out::MyThread::func");
  }
}
public class TestDemo1 {
    public static void main(String[] args) {
    //new MyThread();匿名對象
    new MyThread(){
      //這東西就是匿名內部類需要重寫
        @Override
        public void func() {
            super.func();//有繼承關係可以看做是外部類MyThread的子類
        }
    }.func();
}
}

泛型:
1.實現一個通用的ArrayList
2.泛型:TestMyArrayList:他只是一個佔位符
證明當前的類是一個泛型類
3.泛型的坑:泛型不能被new 坑2 :泛型的參數必須是引用類型不能是簡單類型。
4.泛型的意義
1.可以進行自動類型檢查
2.可以自動進行類型轉換
5.泛型到底是怎麼被編譯的?
最重要的 類型的擦除機制-》object 並不是替換
只是將等進行擦除爲object 也就是將
@SuppressWarnings(“unchecked”) 代表強制壓制警告
6.泛型參數是不參與類型的組成的。
瞭解
類型形參一般使用一個大寫字母表示,常用的名稱有:
E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
T 表示 Type
S, U, V 等等 - 第二、第三、第四個類型

public class TestMyArrayList<T> {
    public T []elem;
    public int usedSize;
    public TestMyArrayList(){
        //this.elem=new T[10] 錯誤的
        this.elem=(T[])new Object[10];//泛型不能被new,我們進行強轉
        this.usedSize=0;
    }
    public void add(T data){
        this.elem[this.usedSize]=data;
        this.usedSize++;
    }
    public T get(){
        T a=this.elem[this.usedSize-1];
        this.usedSize--;
        return a ;
    }
}

測試代碼:

public class TestMain {
    public static void main(String[] args) {
        TestMyArrayList<Integer> tA=new TestMyArrayList<>();
        tA.add(10);
        double ret=tA.get();//報錯原因   沒有類型轉換

        TestMyArrayList<String> tA1=new TestMyArrayList<>();
        tA1.add("zhangsan");

    }
}

類型擦除:

package com.bit.src;

import java.util.ArrayList;

//這裏的extends就是我們泛型的上界 就是我們傳入的T一定是需要實現了Comparable接口的
//寫一個這樣的類相當於是一個萬能的類   我們只需要在main函數中定義它的類型即可
//當我們只有整形數字之間我們的使用><來比較   如果類型不確定  我們是需要將T類型本來是往
// Object的方面擦除   我們手動引導至compareTo 進行實現比較
class Algorithm<T extends Comparable<T>> {//T extends Number 呢我們只能傳入的是數字類型的比如Integer
    //double等
    public T MaxNum(T[]array){
        T max=array[0];
        for (int i = 1; i < array.length ; i++) {
            if (array[i].compareTo(max)>0){//此時因爲我們是一個T類型的數組 不能直接使用>號進行比較
                //使用Compare To
                max=array[i];
            }
        }
        return max;
    }
}
class Algorithm2 {//我們現在需要的是不需要通過對象的引用進行訪問。  我們需要添加static
        public static<T extends Comparable<T>> T MaxNum(T[]array){
        T max=array[0];
        for (int i = 1; i < array.length ; i++) {
            if (array[i].compareTo(max)>0){//此時因爲我們是一個T類型的數組 不能直接使用>號進行比較
                //使用Compare To
                max=array[i];
            }
        }
        return max;
    }
}
class Algorithm3{
    public static <T> void print(ArrayList<T> array){
        for (int i = 0; i <array.size() ; i++) {
            System.out.print(array.get(i));
        }
    }
    //指定就是我們的通配符
    public static  void print2(ArrayList<?> array){
        //Object說明該類型的基類就是Object
        for (Object obj: array) {
            System.out.print(obj+" ");
        }
        System.out.println();
    }
}
/*泛型:指定
通配符:代表 只讀的
* */
public class TestDemo {
    public static void main(String[] args) {
        ArrayList<Double> array=new ArrayList<>();
        array.add(1.0 );
        array.add(2.0);
        array.add(3.0);
        Algorithm3.print2(array);
    }
    public static void main2(String[] args) {
        //Integer[]array={1,3,5,7,9};  會有一個推演的過程
        String[]array1={"abc","def","ghk"};
        String a=Algorithm2.MaxNum(array1);//這裏我們沒有去指定一個<T> 這樣直接進行引用的話
        //我們會自動先去檢測你數組中的內容
        System.out.println(a);
    }
    public static void main1(String[] args) {
        Algorithm<Integer> algorithm=new Algorithm<>();
        Integer[]array={1,3,5,7,9};//在這裏我們需要使用包裝類進行定義我們的數組
        Integer a=algorithm.MaxNum(array);//接收類型就是T類型  我們目前所定義的即爲Integer
        System.out.println(a);
        Algorithm<String> algorithm1=new Algorithm<>();
        String[]array1={"abc","def","ghk"};
        String str=algorithm1.MaxNum(array1);
        System.out.println(str);
    }
}

在這裏插入圖片描述
泛型中的父子類型:

在平常來說我們Object 使我們所有類的父類 但是隻要一牽扯到泛型
我們泛型是有一個擦除機制,在編譯過程中會將所有類擦除爲Object 所有泛型中不會有父子類型關係
我們需要使用通配符來確定父子關係
在這裏插入圖片描述
泛型只有上界。
在通配符中是有上下界的:
<?extends number> 這種來說上界就是number 我們的類型只能選擇數字類型

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