控制台输出:
5 4 Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at GenericityTest01.main(GenericityTest01.java:17)2、使用泛型的情况
就可以在编译时进行语法检查 ,避免了在运行时出现ClassCastException异常,同时也避免了类型的强制类型转换。 /** * @author Jason * @create 2020-07-11 11:47 * 泛型实例 */ public class GenericityTest04 { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("Jason"); list.add("Jack"); //list.add(222); //创建一个迭代器 Iterator it = list.iterator(); while (it.hasNext()) { //将集合中的内容强制转换 String o = (String) it.next(); //打印出他们各自的长度 System.out.println(o.length()); } } }控制台输出:
5 43、新的问题
刚我们存入的是String,而如果我们需要存入Integer,则还要单独编写一个ArrayList,实际上还需要为其他所有class单独编写一种ArrayList,需要解决这样的问题,我们只需要将ArrayList编写一种模板。实现我们想要什么都可以。 /** * @author Jason * @create 2020-07-11 14:49 * */ public class MyClass { public static void main(String[] args) { GenericityTest05<String> strgeneric = new GenericityTest05<>("jason"); String key1 = strgeneric.getKey(); System.out.println("key1:" + key1); System.out.println("----------"); GenericityTest05<Integer> intgeneric = new GenericityTest05<>(111); Integer key2 = intgeneric.getKey(); System.out.println("key2:" + key2); } } ** * @author Jason * @create 2020-07-11 14:42 */ public class GenericityTest05<T> { private T key; public GenericityTest05() { } public GenericityTest05(T key) { this.key = key; } public T getKey() { return key; } public void setKey(T key) { this.key = key; } @Override public String toString() { return "GenericityTest05{" + "key=" + key + '}'; } }控制台输出:
key1:jason ---------- key2:111(5)从泛型类派生子类
• 子类也是泛型类,子类和父类的泛型类型要一致 class ChildGeneric<T> extends Generic<T> /** * @author Jason * @create 2020-07-11 15:36 */ public class Parent<E> { private E value; public E getValue() { return value; } public void setValue(E value) { this.value = value; } } /** * @author Jason * @create 2020-07-11 15:39 * 子类也是泛型类 */ public class ChildFirst<T> extends Parent<T> { @Override public T getValue() { return super.getValue(); } } /** * @author Jason * @create 2020-07-11 15:41 */ public class MyClass { public static void main(String[] args) { ChildFirst<String> childFirst = new ChildFirst<String>(); childFirst.setValue("Jason"); String value = childFirst.getValue(); System.out.println(value); } }• 子类不是泛型类,父类要明确泛型的数据类型
class ChildGeneric extends Generic<String>
/** * @author Jason * @create 2020-07-11 15:36 */ public class Parent<E> { private E value; public E getValue() { return value; } public void setValue(E value) { this.value = value; } } /** * @author Jason * @create 2020-07-11 15:48 * 泛型类派生子类,如果子类不是泛型类,那么父类要明确数据类型(创建子类的时候无法确定父类类型) */ public class ChildSecond extends Parent<Integer> { @Override public Integer getValue() { return super.getValue(); } @Override public void setValue(Integer value) { super.setValue(value); } } /** * @author Jason * @create 2020-07-11 15:41 */ public class MyClass { public static void main(String[] args) { ChildSecond childSecond = new ChildSecond(); childSecond.setValue(100); Integer value1 = childSecond.getValue(); System.out.println(value1); } }2、泛型接口详情
实现类不是泛型类,接口要明确数据类型 /** * @author Jason * @create 2020-07-11 16:08 * 泛型接口 */ public interface Generator<T> { T getKey(); } /** * @author Jason * @create 2020-07-11 16:11 * 实现泛型接口的类不是泛型类,需要明确实现泛型接口的数据类型 */ public class Apple implements Generator<String> { @Override public String getKey() { return "Hello Jason!"; } } /** * @author Jason * @create 2020-07-11 16:13 */ public class Test { public static void main(String[] args) { Apple apple = new Apple(); String key = apple.getKey(); System.out.println(key); } } 实现类也是泛型类,实现类和接口的泛型类型要一致 /** * @author Jason * @create 2020-07-11 16:08 * 泛型接口 */ public interface Generator<T> { T getKey(); } /** * @author Jason * @create 2020-07-11 16:17 * 泛型类实现泛型接口,需要保证实现接口的泛型类的泛型标识包含泛型接口的泛型标识 */ public class Pair<T,E> implements Generator<T> { private T key; private E value; public Pair(T key, E value) { this.key = key; this.value = value; } @Override public T getKey() { return key; } public E getValue() { return value; } } /** * @author Jason * @create 2020-07-11 16:13 */ public class Test { public static void main(String[] args) { Pair<String,Integer> pair = new Pair<>("count",100); String key1 = pair.getKey(); Integer value = pair.getValue(); System.out.println(key1 + " = " + value); } }5、总结
泛型方法能使方法独立于类而产生变化 如果static方法要使用泛型能力,就必须使其成为泛型方法2、通配符上限
语法: 类/接口<? extends 实参类型> 要求该泛型的类型,只能是实参类型,或实参类型的子类类型 public class Animal { } public class Cat extends Animal { } public class MiniCat extends Cat { } /** * @author Jason * @create 2020-07-12 8:33 * 通配符上限 */ public class TestUp { public static void main(String[] args) { ArrayList<Animal> animals = new ArrayList<>(); ArrayList<Cat> cats = new ArrayList<>(); ArrayList<MiniCat> miniCats = new ArrayList<>(); //这里为啥可以添加呢?原因在于他的底层源码:public boolean addAll(Collection<? extends E> c) cats.addAll(cats); cats.addAll(miniCats); //这里会报异常:原因是什么呢?问题在于showAnimal()采用的是通配符上限 //showAnimal(animals); showAnimal(cats); showAnimal(miniCats); } //泛型通配符上限,传递的集合类型,只能是Cat或Cat的子类 public static void showAnimal(ArrayList<? extends Cat> list) { //这里是不可以添加元素的,因为ArrayList是上限通配符,此时我们是无法知道他存的是何种类型的元素 /*list.add(new Animal()); list.add(new Cat());*/ for (int i = 0; i < list.size(); i++) { Cat cat = list.get(i); } } }3、通配符下限
语法: 类/接口<? super 实参类型> 要求该泛型的类型,只能是实参类型,或实参类型的父类类型。 实例一: /** * @author Jason * @create 2020-07-12 8:57 * 通配符下限 */ public class TestDown { public static void main(String[] args) { ArrayList<Animal> animals = new ArrayList<>(); ArrayList<Cat> cats = new ArrayList<>(); ArrayList<MiniCat> miniCats = new ArrayList<>(); //集合只能是Cat或Cat的父类类型,不能是它的子类型 showAnimal(animals); showAnimal(cats); //showAnimal(miniCats); } //类型通配符下限,要求集合只能是Cat或Cat的父类类型 public static void showAnimal(List<? super Cat> list) { //这里可以添加元素,并且他本身和子类都能添加,for循环是object类型接收的 list.add(new Cat()); list.add(new MiniCat()); //list.add(new Animal()); for (Object o : list) { System.out.println(o); } } }实例二:
/** * @author Jason * @create 2020-07-12 9:23 * 下限通配符 */ public class Test05 { public static void main(String[] args) { //这里的TreeSet底层采用的是下限通配符:public TreeSet(Comparator<? super E> comparator) //我们在构造子类对象的时候,必须先构造父类对象,如果这时候比较的是父类成员的话是没有任何问题的。 //而如果这里比较子类对象的话,则不可以,因为它还没有构造出来 //TreeSet<Cat> treeSet = new TreeSet<>(new Comparator2()); TreeSet<Cat> treeSet = new TreeSet<>(new Comparator1()); treeSet.add(new Cat("jack", 10)); treeSet.add(new Cat("mimi", 14)); treeSet.add(new Cat("jim", 11)); treeSet.add(new Cat("bibi", 16)); treeSet.add(new Cat("didi", 6)); for (Cat cat : treeSet) { System.out.println(cat); } } } class Comparator1 implements java.util.Comparator<Animal> { @Override public int compare(Animal o1, Animal o2) { return o1.name.compareTo(o2.name); } } class Comparator2 implements Comparator<Cat> { @Override public int compare(Cat o1, Cat o2) { return o1.age-o2.age; } } class Comparator3 implements Comparator<MiniCat> { @Override public int compare(MiniCat o1, MiniCat o2) { return o1.level-o2.level; } }控制台输出:
ArrayList ArrayList ============= true3、无限制类型擦除
擦除前 /** * @author Jason * @create 2020-07-12 10:05 */ public class Erasure<T> { private T key; public T getKey() { return key; } public void setKey(T key) { this.key = key; } } 擦除后 /** * @author Jason * @create 2020-07-12 10:05 */ public class Erasure { private Object key; public Object getKey() { return key; } public void setKey(Object key) { this.key = key; } }4、有限制类型擦除
擦除前 /** * @author Jason * @create 2020-07-12 10:05 */ public class Erasure<T extends Number> { private T key; public T getKey() { return key; } public void setKey(T key) { this.key = key; } } 擦除后 /** * @author Jason * @create 2020-07-12 10:05 */ public class Erasure { private Number key; public Number getKey() { return key; } public void setKey(Number key) { this.key = key; } }5、擦除方法中定义的参数
擦除前 public <T extends Number> T getValue(T value) { return t; } 擦除后 public Number getValue(Number value) { return value; }6、桥接方法
擦除前 /** * @author Jason * @create 2020-07-12 10:31 * 泛型接口 */ public interface Info<T> { T info(T t); } public class InfoImpl implements Info<Integer> { @Override public Integer info(Integer integer) { return null; } } 擦除后 /** * @author Jason * @create 2020-07-12 10:31 * 泛型接口 */ public interface Info<T> { Object info(Object var); } public class InfoImpl implements Info { public Integer info(Integer var) { return null; } @Override public Object info(Object var) { return info((Integer) var); } }可以通过java.lang.reflect.Array的newInstance(Class,int)创建T[]数组 /** * @author Jason * @create 2020-07-12 11:07 */ public class Fruit<T> { private T[] array; public Fruit(Class<T> clz, int length) { array = (T[])Array.newInstance(clz, length); } public void put(int index, T item) { array[index]=item; } public T get(int index) { return array[index]; } public T[] getArray(){ return array; } } /** * @author Jason * @create 2020-07-12 10:53 * 泛型与数组 */ public class Test07 { public static void main(String[] args) { Fruit<String> fruit = new Fruit<>(String.class, 3); fruit.put(0, "桃子"); fruit.put(1, "栗子"); fruit.put(2, "苹果"); System.out.println(Arrays.toString(fruit.getArray())); String s1 = fruit.get(2); System.out.println(s1); } }