java泛型的一些常见用法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aitangyong/article/details/54932183

本文主要参考下面几篇文章:

http://blog.csdn.net/seu_calvin/article/details/52230032

http://blog.csdn.net/orzlzro/article/details/7017435

http://sharewind.iteye.com/blog/1622164

https://www.zhihu.com/question/20400700


1、 泛型类(接口)的写法以及继承

// 类似java.util.function.Function
public interface GenericInterface<T, R> {
    public R apply(T t);
}

// 类似java.util.stream.IntStream
public interface InheritGeneric0 extends GenericInterface<String, Integer> {
}

// 类似java.util.function.UnaryOperator
public interface InheritGeneric1<T> extends GenericInterface<T, T> {
}

// 类似java.util.HashMap
public interface InheritGeneric2<T, R> extends GenericInterface<T, R> {

}

// JDK库尚未找到类似的
public interface InheritGeneric3<V, T, R> extends GenericInterface<T, R> {
    public V apply2(T t, R r);
}



2、泛型方法的写法
public class Retryer<T> {
    private T value;

    private int id = 0;

    public Retryer() {

    }

    public Retryer(int id) {
        this.id = id;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

// 泛型的声明:方法的修饰符(public,static,final,abstract等)之后, 返回值(void,int等)之前
public class SpecificClass {

    // 入参泛型,返回值非泛型
    public <L, R> int sum(L[] left, R[] right) {
        return left.length + right.length;
    }

    // 入参非泛型,返回值泛型
    public static <T> Retryer<T> build() {
        return new Retryer<T>();
    }

    // 入参泛型,返回值泛型
    public <L, R, V> Retryer<V> buildLength(L[] left, R[] right) {
        return new Retryer<V>(left.length + right.length);
    }

    // 限制泛型: 只能是某个类的子类或者只能是实现了某些接口的类
    // <T extends Comparable>
    // <T extends Number&Serializable>
    // <T extends Comparable&Serializable>
    public <L extends Number, R extends Number> double add(L left, R right) {
        return left.doubleValue() + right.doubleValue();
    }

}


3、泛型的一些基本特性:不能实例化对象和数组

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class GenericBasicFeature {
    public static void main(String[] args) {
        test1();

        String[] stringArray = (String[]) Array.newInstance(String.class, 5);
        System.out.println("stringArray.length=" + stringArray.length);

        String[] stringArray2 = GenericBasicFeature.test2(5, String.class);
        System.out.println("stringArray2.length=" + stringArray2.length);
    }

    // 泛型只在编译期有效
    // http://blog.csdn.net/seu_calvin/article/details/52230032
    public static void test1() {
        List<String> stringList = new ArrayList<String>();
        stringList.add("aaa");

        // 编译报错
        // stringList.add(new Object());

        // 运行时通过反射添加元素
        try {
            Class clazz = stringList.getClass();
            Method method = clazz.getMethod("add", Object.class);
            method.invoke(stringList, 100);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // [aaa, 100]
        System.out.println(stringList);
    }

    // java不支持创建泛型数组
    // http://blog.csdn.net/orzlzro/article/details/7017435
    public static <T> T[] test2(int length, Class<T> newType) {
        // T t = new T(); 编译错误
        // T[] wrong = new T[length]; 编译错误
        // T[] newArray = (T[]) new Object[length]; 运行时ClassCastException

        // 参考Arrays.copyOf
        T[] newArray = (T[]) Array.newInstance(newType, length);
        return newArray;
    }

}

4、泛型的super和extend的PECS原则

// PECS(Producer Extends Consumer Super)
public class Demo {
    static class Food {
    }

    static class Fruit extends Food {
    }

    static class Apple extends Fruit {
    }

    public void testExtend() {
        List<? extends Food> flist = new ArrayList<Food>();
        flist.add(new Apple());  //compile error
        flist.add(new Fruit()); //compile error
        flist.add(new Object()); //compile error

        Food fruit = flist.get(0); //ok
    }

    public void testSuper() {
        List<? super Food> flist = new ArrayList<Food>();
        flist.add(new Food()); //ok
        flist.add(new Fruit()); //ok
        flist.add(new Apple()); //ok

        Food f = flist.get(0);// compile error
    }
}



5、一种使用例子
public class ExtendsContainer<T> {

    private T data;

    public ExtendsContainer(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

public class Demo {
    static class Food {
    }

    static class Fruit extends Food {
    }

    static class Apple extends Fruit {
    }

    public static void main(String[] args) {
        ExtendsContainer<Food> food = new ExtendsContainer<Food>(new Food());
        ExtendsContainer<Fruit> fruit = new ExtendsContainer<Fruit>(new Fruit());
        ExtendsContainer<Apple> apple = new ExtendsContainer<Apple>(new Apple());
        ExtendsContainer<String> string = new ExtendsContainer<String>("abc");

        getDataNoLimit(food);
        getDataNoLimit(fruit);
        getDataNoLimit(apple);
        getDataNoLimit(string);

        getDataOnlyFood(food);
        getDataOnlyFood(fruit);
        getDataOnlyFood(apple);
        getDataOnlyFood(string);

        getDataAnyFood(food);
        getDataAnyFood(fruit);
        getDataAnyFood(apple);
        getDataAnyFood(string);
    }

    public static void getDataNoLimit(ExtendsContainer<?> container) {
        System.out.println("data:" + container.getData());
    }

    public static void getDataOnlyFood(ExtendsContainer<Food> container) {
        System.out.println("data:" + container.getData());
    }

    public static void getDataAnyFood(ExtendsContainer<? extends Food> data) {
        System.out.println("data :" + data.getData());
    }

}



猜你喜欢

转载自blog.csdn.net/aitangyong/article/details/54932183