泛型可以把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型 。
相当于把数据类型作为参数来进行传递。
注意:泛型只能是引用数据类型。
泛型类和泛型接口的用都相同,本篇以泛型类为例进行讲解。
泛型类就是把泛型定义在类上,用户使用该类的时候,才把类型明确下来 。
在类名后加<>,在<>中定义泛型,<>中的内容相当于泛型的名字,可以随便写。在泛型类中我们可以把这个泛型的名字当做一个数据类型来使用。
public class TestClass<T> { //... }
在泛型类中可以使用在类名后面定义的泛型。
public class TestClass<T> { public void test(T t){ } }
①创建对象时确定
在创建泛型类对象的时候确定之前定义的泛型代表什么数据类型。在定义泛型类对象的时候,在类名的后加<>,在其中写一个具体的数据类型。
public static void main(String[] args) { TestClass<String> t = new TestClass();//指定了该对象的泛型T是String类型 t.test("愚生浅末");//所以test方法的参数类型应该也是String类型 }
完整示例:
public class Test <E>{ public void test(E e){ System.out.println(e); } public static void main(String[] args) { Test<String> e = new Test(); e.test("愚生浅末"); } }
②定义子类时确定
在定义子类的时候可以确定泛型。具体用法如下:
public class SubClass extends TestClass<String> { @Override public void test(String s) { } }
这样在子类SubClass中泛型就确定为String类型了。
注意:我们在定义子类时也可以选择不确定泛型,让其在创建对象的时候在确定。写法如下
public class SubClass<T> extends TestClass<T> { @Override public void test(T t) { super.test(t); } }
在方法返回值类型的前面加<>,在<>中定义泛型,<>中的内容相当于泛型的名字,可以随便写。在该泛型方法中我们可以把这个泛型的名字当做一个数据类型来使用。
public static <T> T test(T t){ return t; }
在泛型方法中可以使用定义的泛型。并且我们一般是在参数列表中或者是返回值类型上使用到这个泛型。
public static <T> T test(T t){ return t; }
在调用泛型方法的时候才真正确定之前定义的泛型代表什么数据类型。在调用泛型方法的时候,程序会根据你的调用自动推导泛型的具体类型。
public static void main(String[] args) { Integer test = test(1); String s = test("愚生浅末"); }
我们在使用确定泛型的时候可以使用任意的引用数据类型去确定。但是在某些场景下我们要求这个泛型必须是某个类的子类或者是某个类的父类。这种情况下我们就需要用到泛型上限和泛型上限来限制泛型的范围。
限制泛型必须是某个类或者是其子类。
格式:
<? extends 具体的类型>
例如:
public static void test(List<? extends Person> t){ }
这样我们再调用test方法的时候只能存入泛型为Person或者是Person子类的List集合对象。
限制泛型必须是某个类或者是其父类。
格式:
<? super 具体的类型>
例如:
public static void test(List<? super Student> t){ }
这样我们再调用test方法的时候只能存入泛型为Student或者是Student父类的List集合对象。
1.泛型上限可以在定义泛型类和方法参数上使用
public class Box<E extends Person> { E e; }
2.泛型下限主要在方法参数上使用。
如图片失效等情况请参阅公众号文章:https://mp.weixin.qq.com/s/fvO0ozrCxrDS6j75zo6GRA
欢迎关注我的公众号:愚生浅末,一起交流学习。