泛型
什么是泛型
泛型:广泛通用的类型
一开始还不确定是什么类型,在使用的时候,才能确定是什么类型
(1)在开始定义的时候,留一个插口
(2)在创建对象的时候,再去插入对应的类型
泛型也可以理解为“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。
顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
泛型的定义
泛型类:public class Demo
泛型接口:public interface ImplDemo<T,V>{} ,和定义类一样(接口就是一个特殊类)。
泛型方法:public
<>括号中,名字可以是任意的,通常使用 T:Type,E:Element,K:Key,V:Value。
代码模板中类型不确定,谁调用该段代码,谁就可以来指明这个类型。
如果没有指明泛型类型,它默认就是Object类型
泛型的好处
(1)编译时确定类型,保证类型安全,避免类型转换异常。
(2)避免了强制类型转换。
(3)代码利于重用,增加通用性。
泛型的本质
泛型其实是一个语法糖,本质还是Object,内部其实还是要做强转。
class Demo<T> {
T x;
public Demo(T x) {
this.x = x;
}
public T getX() {
return x;
}
}
public class Test {
public static void main(String[] args) {
Demo<String> demo = new Demo<>("SSS");
String str = demo.x;
System.out.println(str);
}
}
反编译后:
class Demo
{
Object x;
public Demo(Object x)
{
this.x = x;
}
public Object getX()
{
return x;
}
}
public class Test
{
public Test()
{
}
public static void main(String args[])
{
Demo demo = new Demo("SSS");
String str = (String)demo.x;
System.out.println(str);
}
}
泛型类和泛型方法
(1)泛型类
在类上面定义的泛型,class 类名
泛型类当中定义的泛型只能用在普通方法上面,不能使用在静态方法上面。
(2)泛型方法
就是在方法上面添加了泛型,是在使用方法时,参数传递确定具体的类型。
方法想要单独使用泛型,必须要有参数才有意义。
class Demo {
public <T> void demo1(T t) {
System.out.println(t.getClass());
}
public <T> T demo2(T t) {
System.out.println(t.getClass());
return t;
}
public static <T> void demo3(T t) {
System.out.println(t.getClass());
}
}
public class Test {
public static void main(String[] args) {
Demo demo = new Demo();
demo.demo1("str");// class java.lang.String
demo.demo1(10);// class java.lang.Integer
demo.demo1(10.5);// class java.lang.Double
Demo.demo3(true);// class java.lang.Boolean
}
}
泛型通配符
通配符:不知道使用什么类型来接收的时候,可以使用?表示未知。
(1)无边界的通配符
无边界的通配符的主要作用就是让泛型能够接受未知类型的数据。
public static void printList(List<?> list) {
for (Object o : list) {
System.out.println(o);
}
}
public static void main(String[] args) {
List<String> l1 = new ArrayList<>();
l1.add("aa");
l1.add("bb");
l1.add("cc");
printList(l1);
List<Integer> l2 = new ArrayList<>();
l2.add(11);
l2.add(22);
l2.add(33);
printList(l2);
}
这种使用List<?>的方式就是父类引用指向子类对象。注意,这里的printList方法不能写成public static void printList(List