Java泛型

引入泛型

//Object是所有类的父类,所以我们不知道类型的时候使用Obejct
public class Demo1 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("abc");
        list.add(1);
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
}
//输出
abc
1
//如果我们List集合中的元素只想放String型的,接下来我们如此变量
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("abc");
        list.add(1);
        for (Object obj : list) {
            //强转为String
            System.out.println((String)obj);
        }
    }
//结果
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
为什么会报错:
    我们不小心在集合中添加了Integer型元素,如何在我们编写的代码的时候避免这种错误,我们可以使用泛型。
//添加List<String>
List<String> list = new ArrayList();
list.add("abc");
list.add(1);//编译的时候报错

泛型的命名规范

各种常用泛型参数的意义如下:
E — Element,常用在java Collection里,如:List<E>,Iterator<E>,Set<E>
K,V — Key,Value,代表Map的键值对
N — Number,数字
T — Type,类型,如String,Integer等等
S,U,V,和T的用法一样

泛型类

public class Demo2 {
    private Object object;

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    public static void main(String[] args) {
        Demo2 demo2 = new Demo2();
        demo2.setObject("abc");
        Integer a = (Integer)demo2.getObject();
    }
}
//结果
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

//泛型类
public class Demo3<T> {
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }

    public static void main(String[] args) {
        Demo3<Integer> demo3 = new Demo3<Integer>();
        demo3.setObj(1);
        demo3.setObj("123");//编译的时候报错
    }
}

//多个泛型
public class Container<K, V> {
    private K key;
    private V value;

    public K getKey() {
        return key;
    }

    public void setKey(K key) {
        this.key = key;
    }

    public V getValue() {
        return value;
    }

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

    public Container(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public static void main(String[] args) {
        Container<String,String> container1 = new Container<String, String>("a","b");
        Container<Integer,Integer> container2 = new Container<Integer, Integer>(1,2);
        System.out.println(container1.getKey() + container1.getValue());
        System.out.println(container2.getKey() + container2.getValue());
    }
}

泛型接口

//定义泛型接口
public interface Generator<T> {
    T next();
}

public class FruitsGenerator implements Generator {
    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};
    //重写next()方法的时候定义返回值类型
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }

    public static void main(String[] args) {
        FruitsGenerator fruitsGenerator = new FruitsGenerator();
        System.out.println(fruitsGenerator.next());
        System.out.println(fruitsGenerator.next());
        System.out.println(fruitsGenerator.next());
    }

}

泛型数组

public class Demo4 {
    //输出数组中的元素
    public static <T> void fun1(T... args) {
        for (T t : args) {
            System.out.println(t);
        }
    }
    //传入的参数转换为数组
    public static <T> T[] fun2(T... args) {
        return args;
    }

    public static void main(String[] args) {
        Integer i[] = fun2(1, 2, 3, 4);
        String j[] = fun2("a", "b", "c");
        fun1(i);
        fun1(j);
    }
}

受限泛型

受限泛型是指一个泛型对象的上限和下限

//下限
// <T extends BoundingType>BoundingType可以是接口也可以是类,这个extends表示子类型不同与继承。
public class Demo7<T> {
    private T t;

    public void set(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }

    public <U extends Number> void inspect(U u) {
        System.out.println(u.getClass().getName());
        System.out.println(t.getClass().getName());
    }


    public static void main(String[] args) {
        Demo7<String> demo7 = new Demo7();
        demo7.set("abc");    //能通过编译,因为T指定为String类型
        //demo7.inspect("abc");//不能通过编译,因为U必须是Number类型或其子类
        demo7.inspect(new Integer(10));
    }
}
//结果
java.lang.Integer
java.lang.String

//上限
// <T super BoundingType>

案例: 统计数组中大于某个数的总数

public <U> void count(U[] array, U ele) {
    int count = 0;
    for (U u : array) {
        if (u > ele) {//编译报错
            count++;
        }
    }
}
 
//可以修改为如下
public <U extends Comparable> void count(U[] array, U ele) {
    int count = 0;
    for (U u : array) {
        if (ele.compareTo(u) == 1) {
            count++;
        }
    }
}

泛型类和子类型

Integer继承Number但是不能说Container<Integer>继承Container<Number>,其实泛型中不存在子类的概念。泛型的extends可以简单的理解extends和implement取并集。

//例子:
public interface Demo8<E, U> extends List<E> {
}

Demo8<String,String>
Demo8<String,Integer>
都是List<String>的子类型

通配符?

// 创建Demo8<List<String>>后又想创建 Demo8<ArrayList<String>>
public class Demo8<T extends Collection> {
    public static void main(String[] args) {
        Demo8<List<String>> demo8 = new Demo8<List<String>>();
        demo8 =new Demo8< ArrayList<String>>();//编译报错
    }
}

我们可以使用通配符?
public static void main(String[] args) {
    Demo8<? extends Collection<String>> demo8 = new Demo8<Collection<String>>();
    demo8 =new Demo8< ArrayList<String>>();
    demo8 = new Demo8<List<String>>();
}

注意点:

(1)通配符不能应用到类定义上。

(2)在Java集合框架中,对于参数值是未知类型的容器类,只能读取其中元素,不能向其中添加元素(当是super的时候可以添加元素), 因为,其类型是未知,所以编译器无法识别添加元素的类型和容器的类型是否兼容,唯一的例外是NULL。

案例1:
List<? extends Number > list = new ArrayList();
list.add(1);//编译错误
案例2:
List<? extends Number > list = new ArrayList();
list.add(null);//没有错误
案例3:
List<? super Number > list = new ArrayList();
list.add(1);//没有错误,可以添加元素
案例4:
List<? super Number > list = new ArrayList();
list.add(11111111111);//Integer number too large

通过案例三和案例四我初步判读时 ?其实知道类型的,? super Number可以执法哦 ?的上限是Number,而整数默认是Integer所以可以添加。



你可能感兴趣的:(Java泛型)