//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所以可以添加。