Java笔记(十二)——泛型

1 泛型是什么

让一个类 / 方法,能够支持多种不同类型的数据。这样就不用一遍又一遍的写,很简洁方便,一个代码可以使用多次。

2 使用 Object

使用 Object 来完成 “ 泛型 ”效果,是比较麻烦的。一方卖弄,需要写一些类型转换的代码;另一方面,类型转换的代码容易出错,缺少一些必要的类型检查。

public class MyArray {
    private Object[] data = null;
    private int size = 0;
    private int capacity = 10;

    public MyArray() {
        data = new Object[capacity];
    }

    public void add(Object data){
        if (size >= capacity){
            return;
        }
        this.data[size++] = data;
    }

    public Object get(int index){
        return data[index];
    }

    public static void main(String[] args) {
        MyArray myArray = new MyArray();
        myArray.add(new Person("奈奈生",18));
        myArray.add(new Person("鞍马",19));
        myArray.add(new Person("瑞希",19));
        Person person = (Person) myArray.get(0);

        MyArray myArray2 = new MyArray();
        myArray2.add("hello");
        myArray2.add("java");
        String str = (String) myArray2.get(0);

        MyArray myArray3 = new MyArray();
        myArray3.add(1);
        Integer integer = (Integer)myArray3.get(0);
    }
}
public class Person {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

3 使用泛型

泛型包括:泛型类、泛型方法、泛型接口。
类名后面加上 泛型参数,<> 表示当前这个类是个泛型类,E相当于是一个形参,表示某一具体的类型,会在实例化的时候具体确定是什么类型。

public class MyArray2<E> {
    private E[] data = null;
    private int size = 0;
    private int capacity = 10;

    public MyArray2() {
// 错误
//        data = new E[capacity];
        data = (E[])new Object[capacity];
    }

    public void add(E data){
        if (size >= capacity){
            return;
        }
        this.data[size++] = data;
    }
    public E get(int index){
        return this.data[index];
    }
    public static void main(String[] args) {
        MyArray2<String> myArray2 = new MyArray2<>();
        myArray2.add("hello");
        String str = myArray2.get(0);

        MyArray2<Integer> myArray3 = new MyArray2<>();
        myArray3.add(1);
        myArray3.add(2);
        Integer ret = myArray3.get(0);
    }
}

使用泛型之后,在针对对象实例化的时候,需要填写泛型参数的实际类型,然后所有的 泛型参数 E 就都被替换成我们实例化时填进去的类型了。
本质上还是一个 Object[] ,只是帮我们完成了类型校验 和 类型转化。

4 类型边界

定义泛型类的时候,对未来实例化时,传入的参数的类型做出限制,类型不能随便写,做出一些约束和限制。

public class MyArray2<E extends Animal> {
    private E[] data = null;
    private int size = 0;
    private int capacity = 10;

    public MyArray2() {
        // 错误
//        data = new E[capacity];
	data.eat();
	data = (E[])new Object[capacity];
    }

    public void add(E data){
        if (size >= capacity){
            return;
        }
        this.data[size++] = data;
    }

    public E get(int index){
        return this.data[index];
    }

    public static void main(String[] args) {
    // String 错误,因为 String 不是 Animal 的子类
//        MyArray2<String> myArray2 = new MyArray2<>();
//        myArray2.add("hello");
//        String str = myArray2.get(0);
    // Integer 错误,因为 Integer 不是 Animal 的子类
//        MyArray2<Integer> myArray3 = new MyArray2<>();
//        myArray3.add(1);
//        myArray3.add(2);
//        Integer ret = myArray3.get(0);

//  正确
	MyArray2<Animal> myArray2 = new MyArray2<>();
	MyArray2<Cat> myArray21 = new MyArray2<>();
    }
}
public class Animal {
}
public class Cat extends Animal{
}

泛型边界是在创建时设计的。

5 通配符

也是限制泛型参数传入的条件,是在泛型类使用时涉及的,尤其是泛型类作为某个方法的参数时。

//  创建
public class MyArray<E> {
...
}

// 调用
public static void printAll(MyArray<?> m) 
// 此处的 ? 就是通配符
// 意思是 调用printAll时,参数类型填什么都可以
// 以下调用都是正确的
printAll(new MyArray<String>());
printAll(new MyArray<Integer>());
printAll(new MyArray<Double>());
printAll(new MyArray<Number>());
printAll(new MyArray<Object>()); 

E 只能是在创建的时候使用的,在调用的时候不能实用 E ,用 “ ? ”。

5.1 通配符上界

// 传入类型实参是 Animal 子类的任意类型的 MyArray
public static void printAll(MyArray<? extends Animal> arr) {
...
}
// 以下调用都是正确的
printAll(new MyArray<Cat>());
printAll(new MyArray<Animal>());
// 以下调用是编译错误的
printAll(new MyArray<String>());
printAll(new MyArray<Object>()); 

5.2 通配符下界

// 可以传入类型实参是 Cat 父类的任意类型的 MyArray
public static void printAll(MyArray<? super Animal> arr) {
...
}
// 以下调用都是正确的
printAll(new MyArrayList<Animal>());
printAll(new MyArrayList<Object>());
// 以下调用是编译错误的
printAll(new MyArrayList<String>());
printAll(new MyArrayList<Cat>()); 

5.3 泛型中的父子关系

public class MyArray<E> { ... }
// MyArray<Object> 不是 MyArray<Animal> 的父类型
// MyArray<Animal> 也不是 MyArray<Cat> 的父类型
// 需要使用通配符来确定父子类型
// MyArray<?> 是 MyArray<? extends Animal> 的父类型
// MyArray<? extends Animal> 是 MyArrayList<Dog> 的父类型 
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值