內部類:
實例內部類
靜態內部類
匿名內部類
本地內部類–》基本不會使用到在方法裏定義的一個類。
實例內部類:
面試問題: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 我們的類型只能選擇數字類型