内部类和泛型

内部类:
实例内部类
静态内部类
匿名内部类
本地内部类–》基本不会使用到在方法里定义的一个类。
实例内部类:
面试问题: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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章