目录
前言:
本篇只是阅读相关文档后加以自身理解希望在以简单的叙述方式作为笔记,方便以后快速查找回忆。
如何理解泛型类型
public void test(String name);
public void test(T val)
上面是第一个方法是一个可以传参普通方法,并且指定了传入传参数的类型。第二个方法是一个未指定类型的传参方法,未指定类型则代表需要指定类型,既然可以随意指定类型我们就可以称此为之为泛型类型。此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
如何使用泛型类型
泛型可以使用在类、接口和方法,并可称之为泛型类、泛型接口、泛型方法。
泛型类
泛型类,在未实例化类前不指明泛型的具体类型
//普通类
public class Generic{ }
//泛型类
public class Generic<T>{
//T为外部指定类型
private T val;
//构造方法传入具体类型和参数
public Generic(T val){
this.val=val;
}
//获取实参
public T getKey(){
return val;
}
}
以下是在Main方法中运行的代码和结果
public static void main(String[] args) {
//方式一:未指定类型
Generic generica=new Generic(123);
//方拾二:指定类型
Generic<String> genericb=new Generic<String>("String类型的val");
System.out.println(generica.getVal());
if(genericb.getVal() instanceof String){
System.out.println(genericb.getVal());
}
}
console:
123
String类型的val
扩展
Q:定义的泛型类,就一定要传入泛型类型实参么?
A:不一定,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。
注意:
1、泛型的类型参数只能是类类型,不能是简单类型。
2、不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。
if(123 instanceof Generic<Number>){ }
3、在指定泛型类时如果对象存在继承和实现关系,不会影响继承和实现关系。
public class person{
public String toString(){
return "Person";
}
}
public class student extends Person{
public String toString(){
return "Student";
}
}
public class Generic<T>{
public void show(T t){
System.out.println(t.toString);
}
}
//Main方法
main{
person per=new person();
student stu=new student();
Generic<person> generic=new Generic<person>();//此时T为person
generic.show(stu);
//传入student对象输出student,重写了toString方法
}
泛型方法
泛型方法是在调用方法的时候指明泛型的具体类型
//泛型方法的特性:1、需要有泛型返回值,即在方法内用<T>进行了声明。
public <T> T getTe(T tclass){
T instance=tclass;
return instance;
}
泛型方法的使用场景
(1)多个类中有相同的方法名这时声明泛型,可把类当做时参传入,然后在调用该方法。
扩展:
1、泛型类中可以写泛型方法,并且泛型方法可以直接使用泛型类中声明的泛型T,泛型方法也可直接覆盖声明T或用其它字符代替,两者互不干扰。
public class Generic<T>{
//在泛型类中声明了一个泛型方法,方法声明的T独立于类泛型类声明的T
public <T> void methoda(T t);
//同理,我们可以用其它字母表示,如E
public <E> void methodb(E e);
}
2、泛型方法内的可变参数
public class Generic<T> {
public <T> void fortest( T... args){
for(T t:args){
System.out.print(t);
}
}
public static void main(String[] args) {
Generic<String> gen=new Generic<String>();
gen.fortest("a",1,"b",2);
}
}
console:a1b2
3、静态方法无法访问类上定义的泛型;如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法。
public static <T> void show(T t);
泛型接口
泛型接口和泛型类的定义形式相同,但可分为两种形态
1、实现泛型接口的类未传入泛型实参; 2、实现泛型接口的类传入泛型实参
//泛型接口
public interface person<T>{}
1、当实现泛型接口的类未传入泛型实参时,两者都需要声明泛型
public class student<T> implements person<T>{}
2、当实现泛型接口的类传入泛型实参时,改变所有实现方法类型
public class student implements person<String>{}
泛型类关系的限定
实质是为泛型添加上边界,即传入的类型实参必须是指定类型的子类型。若想添加关系限定只需要在声明泛型类或方法时添加。
类
public class Generic<T extends Number>{
方法1:
public void showKeyValue1(Generic<? extends Number> obj){ }
方法2:
public <T extends Number> T showKeyName(Generic<T> container){ }
泛型通配符
表示符号:?当做实参
使用场景:当具体类型不确定的时候或当操作类型不需要使用类型的具体功能时,单单调用Object类中的功能
public void showKeyValue(Generic<?> obj){ }
泛型数组
Java不允许不能创建一个确切的泛型类型的数组,但使用通配符的方式是被允许的。
List<?>[] lsa = new List<?>[10]; // OK, array of unbounded wildcard type.
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // Correct.
Integer i = (Integer) lsa[1].get(0); // OK
参照文档:https://blog.csdn.net/s10461/article/details/53941091