Java进阶 泛型(二)

347 阅读3分钟

上一篇文章大表哥简单的带小表弟介绍了下泛型的作用以及简单的使用场景。 接下来会具体的带着小表弟学习下具体的泛型使用有那些。

小表弟: 大表哥之前了解的,泛型可以再方法,存储类型比如List、Map上进行类型约束,之外还有那些使用场景喃。

大表哥:泛型不仅仅之前所了解的那些,泛型还可以使用在 类、接口、方法已经变量上使用。下面我们来具体讲解下。


  • 顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
  • 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类泛型接口泛型方法

1. 泛型类

// 示例代码
public class NormalGeneric<T> {
    private T data;
    public NormalGeneric() {
    }
    public NormalGeneric(T data) {
        this.data = data;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public static void main(String[] args) {
        NormalGeneric<String> stringGeneric = new NormalGeneric<>();
        stringGeneric.setData("Hello World!");
        System.out.println(stringGeneric.getData());

        NormalGeneric<Integer> intGeneric = new NormalGeneric<>();
        intGeneric.setData(1314);
        System.out.println(intGeneric.getData());
    }
}

疑问1

小表弟:泛型使用的时候定义可以使用多个吗?

大表哥:泛型类是允许有多个类型变量的。来一起看个栗子🌰

public class ManyGeneric<A,V,XX,OO> {
    public A adult;
    public V video;
    public XX xx;
    public OO oo;

    // Setter and Getter
    ...

    public static void main(String [] args){
        ManyGeneric<String,Integer,Float,Double> manyGeneric = new ManyGeneric<>();
        manyGeneric.setAdult("苍井井");
        manyGeneric.setVideo(36);
        manyGeneric.setXx(120.00f);
        manyGeneric.setOo(240.00d);
        System.out.println("Adult:" + manyGeneric.getAdult());
        System.out.println("Video:" + manyGeneric.getVideo());
        System.out.println("XX:" + manyGeneric.getXx());
        System.out.println("OO:" + manyGeneric.getOo());
    }
}
结果:
Adult:苍井井
Video:36
XX:120.0
OO:240.0

疑问2

小表弟:表哥泛型类的使用是了解,有一个疑惑,例如泛型引入的类型变量这种写法是固定的吗??

大表哥:当然不是固定的,其实引入的类型变量和你平时用的代码里写的变量是一样的。例如我们常用的ArrayList、HashMap他们使用的就不是T,具体使用什么,可以根据使用场景其泛型含义而定。

// ArrayList 泛型使用的 E 其实表示的是 Element的首字母缩写
public class ArrayList<E> extends AbstractList<E> implements List<E>...{
...
}

// HashMap 泛型使用的 K,V 其实表示的 Key Value 的字母缩写
public class HashMap<K,V> extends AbstractMap<K,V> implements ...{
...
}

2. 泛型接口

对于泛型接口的使用和类的使用同理,废话不多说请看👇👇👇

public interface Genertor<T> {
    public T next();
}

// 普通的类实现泛型接口 并把泛型接口参数化的<T>用String 约束,同样接口的方法返回值也是String
public class ImplGenertor implements Genertor<String> {
    @Override
    public String next() {
        return "string";
    }
}

// 这里不难看出 若果用泛型类来实现泛型接口 和 普通的泛型类没什么区别
public class ImplGenertor<T> implements Genertor<T> {
    private T data;

    // Setter and Getter
     ...

    @Override
    public T next() {
        return data;
    }
}

public static void main(String [] args){
    ImplGenertor implGenertor = new ImplGenertor<>();
    implGenertor.setData("");
    System.out.println(implGenertor.next().getClass().getName());
    implGenertor.setData(1);
    System.out.println(implGenertor.next().getClass().getName());
    implGenertor.setData(1f);
    System.out.println(implGenertor.next().getClass().getName());
    implGenertor.setData(1d);
    System.out.println(implGenertor.next().getClass().getName());

    ImplGenertor2 implGenertor2 = new ImplGenertor2();
    System.out.println(implGenertor2.next().getClass().getName());
}
结果:
java.lang.String
java.lang.Integer
java.lang.Float
java.lang.Double
java.lang.String

疑问3

小表弟:表哥若我用泛型类来实现泛型结构 泛型接口上的泛型参数可不可以不用泛型类上的泛型参数??

大表哥:这个是当然可以选择不去使用泛型类的参数,但是必须明确实现的泛型接口的类型。不可以在实现的泛型接口上使用新的泛型参数。🙋🌰 👇👇👇

// ❌错误代码❌
public class ImplGenertor<T> implements Genertor<M>{
    private T data;
    // Setter and Getter
    ...

    @Override
    public M next(){
        return null;
    }
}

// ✔ 正确代码 ✔
public class ImplGeertor<T> implements Genertor<Stirng>{
    private T data;
    //Setter and Getter
    ...
    @Override
    public String next(){
        return "";
    }
}

3. 泛型方法

4. 泛型类型变量