一、JAVA的泛型(泛型就是语法糖)
1、泛型类
①只能用在非静态成员变量和非静态成员方法上
②只能代替引用变量
class Student<T>{ T name; public T getName() { return name; } }
2、泛型接口
①只能用在抽象方法上,不能用在常量上
interface Human<T>{ T compareTo(T t); }
3、泛型方法(静态方法和非静态方法两者皆可以用)
class Method{ public static <T> void show(T t) { } } class Method2{ public static <T extends Cloneable> void show(T t) { } }
4、泛型继承(四种情况 )
//泛型父类(抽象方法和接口和父类都一样) abstract class Father<T1,T2>{ T1 age; abstract void test(T2 arg); } //①不指定类shi于:Father<Object,Object> class Son1 extends Father{ @Override void test(Object arg) { // TODO Auto-generated method stub } } class Son11<A,B> extends Father{ @Override void test(Object arg) { // TODO Auto-generated method stub } } //②指定具体类型 class Son2 extends Father<Integer,String>{ @Override void test(String arg) { // TODO Auto-generated method stub } } class Son22<A,B> extends Father<Integer,String>{ @Override void test(String arg) { // TODO Auto-generated method stub } } //③部分保留,泛型子类 class Son3<T1> extends Father<T1,String>{ @Override void test(String arg) { // TODO Auto-generated method stub } } class Son33<T1,A,B> extends Father<T1,String>{ @Override void test(String arg) { // TODO Auto-generated method stub } } //④完全保留,泛型子类 class Son4<T1,T2> extends Father<T1,T2>{ @Override void test(T2 arg) { // TODO Auto-generated method stub } } class Son44<T1,T2,A,B> extends Father<T1,T2>{ @Override void test(T2 arg) { // TODO Auto-generated method stub } }
5、泛型擦除(使用、实现、继承的时候不指定类型)
public class App { public static void main( String[] args ) { //第一种情况(泛型的擦除) Teacher teacheer = new Teacher(); Object obj = teacheer.getName(); //第二种情况(泛型的擦除) Teacher<String> teacher2 = new Teacher(); //第三种情况(泛型的擦除) Teacher teacher3 = new Teacher<String>(); //第四种情况,这种情况是有错误的(编译时错误) //Teacher<Object> teacher4 = new Teacher(); //Teacher<String> teacher5 = teacher4; } } //泛型的擦除,使用、实现、继承不指定类型 class Teacher<T>{ T name; T getName() { return name; } void setName(T name) { this.name = name; } }
6、泛型的嵌套
public class Solution { public static void main(String[] args) { // TODO Auto-generated method stub Student<Double> s1 = new Student<Double>(); s1.setScore((double) 100); Banji<Student<Double>> ssas = new Banji<Student<Double>>(); ssas.setStu(s1); Double adasd = ssas.getStu().getScore(); System.out.println(adasd); } } class Student<T> { T score; public T getScore() { return score; } public void setScore(T score) { this.score = score; } } class Banji<R> { R stu; public R getStu() { return stu; } public void setStu(R stu) { this.stu = stu; } }
7、泛型需要注意的地方
①泛型没有多态
②泛型没有数组
③泛型不能使用静态属性
④泛型不能使用基本数据类型
⑤静态方法中不能访问类的泛型
⑥catch语句中不能使用泛型catch(T e){}这样子是错误的
public class DuoTai { public static void main(String[] args) { //泛型没有多态 Object object = new String();
Object[] strs = new String[10];//数组是可以的 //List<Object> object1 = new ArrayList<String>();错误 //泛型没有数组 //List<Object>[] object2 = new ArrayList<Object>[10];错误 //jdk1.7关于泛型的简化 List<Object> object3 = new ArrayList<>(); //相较于以前的List<Object> object3 = new ArrayList<Object>(); } } class Fruit { } class Apple extends Fruit { } class Pear extends Fruit { } class FushiApple extends Apple { }
二、JAVA的泛型通配符:?(super和extends)
List<?>是所有List<Object>,List<String>,List<Integer>...的父类
List<?>这样的集合是可以读取的(读取出来的元素类型是Object),写入是不允许的,只能写入null(这个要结合这种式子只能写在等号左边,它不知道等号右边传给它的实际的集合是什么类型的)
1、泛型通配符(?)
①?通配符就是表示类型不确定
②只能用在(声明类型、方法参数)上也就是等号左边;不能用在定义泛型类上也就是等号右边
③不能用在定义泛型类泛型接口泛型方法上(就是不能放在定义泛型的尖括号里面)
List<?> list = new ArrayList<String>();
list = new ArrayList<Integer>();
list = new ArrayList<Date>();
2、泛型上限(? extends xxx)(包含等于)
①一般用于限制某个操作
②不能使用在数据添加上面,一般用于数据读取
③List<?>等同于List<? extends Object>
public class App { public static void main( String[] args ) { List<? extends Fruit> t1 = new ArrayList<Fruit>(); test(t1); List<Fruit> t2 = new ArrayList<Fruit>(); test(t2); List<Apple> t3 = new ArrayList<Apple>(); test(t3); List<? extends Apple> t4 = new ArrayList<FushiApple>(); test(t4); List<?> t5 = new ArrayList<Fruit>(); //List<?>等同于List<? extends Object> //test(t5);错误 } static void test(List<? extends Fruit> list) { //list.add(new Apple());错误 list.add(null); } } class Fruit{ } class Apple extends Fruit{ } class Pear extends Fruit{ } class FushiApple extends Apple{ } class Test<T extends Fruit>{ }
3、泛型下限(? super xxx)(包含等于)
①不能用于添加父类信息
public class App { public static void main(String[] args) { List<Fruit> t1 = new ArrayList<Fruit>(); show(t1); List<Apple> t2 = new ArrayList<Apple>(); show(t2); List<Object> t3 = new ArrayList<Object>(); show(t3); List<? super Apple> t4 = new ArrayList<Apple>(); show(t4); List<? super Fruit> t5 = new ArrayList<Object>(); show(t5); List<? super FushiApple> t6 = new ArrayList<Object>(); //show(t6);错误 List<?> list7 = new ArrayList<Object>(); //show(t7);错误 } static void show(List<? super Apple> list) { list.add(new Apple()); list.add(new FushiApple()); // 不能用于添加父类信息 //list.add(new Fruit()); } } class Fruit { } class Apple extends Fruit { } class Pear extends Fruit { } class FushiApple extends Apple { }
4、图解
假设给定的泛型类型为G,(如List<E>中的List),两个具体的泛型参数X、Y,当中Y是X的子类:
- G<? extends Y> 是 G<? extends X>的子类型(如List<? extends Cat> 是 List<? extends Animal>的子类型)。
- G<X> 是 G<? extends X>的子类型(如List<Animal> 是 List<? extends Animal>的子类型)
- G<?> 与 G<? extends Object>等同,如List<?> 与List<? extends Objext>等同。
Plate<? extends Fruit>
是Plate<Fruit>
以及Plate<Apple>
的基类。这种不能往里面存,只能取。
Plate<? super Fruit>
是Plate<Fruit>
的基类,但不是Plate<Apple>
的基类。这种只能往里面存,不能取。要取也只能取在Object对象里。
三、一个经典的实例:
package org.eclipse.winery.repository; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class Main2 { public static void main(String[] args) { // TODO Auto-generated method stub List<Obj> list = new ArrayList<Obj>(); list.add(new Obj()); List<?> list2 = list; list2.forEach((obj) -> System.out.println(((Obj) obj).name)); Collection<?> list3 = list; list3.forEach((obj) -> System.out.println(((Obj) obj).name)); Collection<Obj> list4 = list; list4.forEach((obj) -> System.out.println(((Obj) obj).name)); } private static class Obj { public String name = "Soar up into the sky with one start!"; } }
从这里我们看出了Collection<Obj>是List<Obj>的父类
四、泛型的静态方法
静态方法有一种情况需要注意一下,那就是在类中的静态方法使用泛型:静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。
即:如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法 。
五、JAVA的extends在泛型中的扩展
public static <T extends Comparable<T>> void sort(T[] arr) { }