前言:最近看源码的时候经常见到标题中的两处代码public static <T> T 与Class<?>[] clazz(因为提交时显示非法字符,所以题目?两边少了两个括号),有点不知道什么意思,就查阅了资料整理如下,下面的资料来源于网上与个人理解..
目录
第一章 public static T methodName
第一章 public static <T> T methodName
1.1 <T>的意义
按理说有一个T表示返回值就可以了,为什么还要一个<T>呢?这个<T>表示这个方法声明为泛型方法.
但是又有一种情况出现了,同样是泛型方法,为什么下面的getName方法就不用<T>声明呢?
public class Test1<T> {
private T name;
public T getName(T name){
return name;
}
public static <T> void printA(T a){
System.out.println(a);
}
}
解释:对于声明了<T>的类(Test1<T>就是声明了<T>的类)不需要声明泛型方法,对于带了static的方法,它并不属于类的一部分,所以相当于没有声明<T>的类,所以需要声明为泛型方法.
像Test2这样的类就必须声明泛型方法
public class Test2 {
public <T> T test1(T A){
System.out.println(A);
System.out.println(A.getClass());
return A;
}
}
1.2 使用Test2类的test1方法
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
Test2 test2 = new Test2();
Test2 test3 = new Test2();
test3.test1(new Base());
test2.test1("123");
}
输出为:
Hello World!
Base@4554617c
class Base
123
class java.lang.String
可见T的类型与我们传入的类一致.
同理两个类型的泛型方法声明
public <T, S extends T> T testGenericMethodDefine(T t, S s){}
第二章 ?与T的区别
参考:https://blog.csdn.net/woshizisezise/article/details/79374460
https://blog.csdn.net/u011586504/article/details/80052750
https://blog.csdn.net/qq_18581651/article/details/81942221
2.1 书上的解释
T的作用是限制泛型可用类型,泛型类的类型必须实现或继承了anyClass这个接口或类,无论anyClass是接口还是类.
class 类名称<T extends anyClass>
?是类型通配符,其主要作用是创建一个泛型类对象时限制这个泛型类的类型实现或继承继承某个接口或类的子类.
泛型类名称<? extends List> a=null
单独的?表示 <? extends Object>
2.2 自己的理解与实例
?和T的区别就是:T主要表示的是一个类,主要给类的泛型指定范围.如下代码所示,如果是?将报错,如果是T才对.如果想给类的泛型指定范围那就是图三.
/*public class P<?> {
private ? test;
public ? getTest() {
return test;
}
//会报错
}*/
public class P<T> {
private T test;
public T getTest() {
return test;
}
}
public class P<T extends List> {
private T test;
public T getTest() {
return test;
}
}
?主要是为参数T指定范围,如下图所示,如果将参数表示为T将会报错.表示为?则没问题.
/*public class Test5 {
public <T> void set(P<T extends List> lists){
}
}报错*/
public class Test5 {
public void set(P<? extends List> lists){
}
}
综上:如果在声明泛型类时没有给类的泛型指定范围,那么可以直接用T来声明参数.
public class P<T> {
private T test;
public T getTest() {
return test;
}
}
public class Test5 {
public <T> void set(P<T> lists){
}
}
如果在声明泛型类时给类的泛型指定了范围,那么想用参数引入时就要用?来限制泛型的范围.
public class P<T extends List> {
private T test;
public T getTest() {
return test;
}
}
public class Test5 {
public void set(P<? extends List> lists){
}
}
且用?可以表示类型未知,在实例化时再用具体的泛型进行实例化.
A<? extends List> a=null;
a=new A<ArrayList>();
2.2.1 实例一
如下图所示,不论用Demo<animal>,Demo<cat>,Demo<dog>中的哪一个,总会有另外两个报错,为了解决这种不确定问题,我们用Demo<?>来显示即可.
public class Test3 {
private static void take(Demo<?> d){
d.print();
}
public static void main(String[] args) {
Demo<Dog> dog = new Demo<Dog>(new Dog());
take(dog);
Demo<Cat> cat = new Demo<Cat>(new Cat());
take(cat);
Demo<Animal> animal = new Demo<>(new Animal());
take(animal);
}
}
public class Animal {
public void print(String name){
System.out.println(name);
}
}
public class Dog extends Animal{
}
public class Cat extends Animal {
}
public class Demo <T extends Animal>{
private T ob;
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public Demo(T ob) {
super();
this.ob = ob;
}
public void print(){
System.out.println("T的类型是:"+ob.getClass().getName());
}
}
2.2 实例二
public static <T> void show1(List<T> list){
for (Object object : list) {
System.out.println(object.toString());
}
}
public static void show2(List<?> list) {
for (Object object : list) {
System.out.println(object);
}
}
public static void test(){
List<Student> list1 = new ArrayList<>();
list1.add(new Student("zhangsan",18,0));
list1.add(new Student("lisi",28,0));
list1.add(new Student("wangwu",24,1));
//这里如果add(new Teacher(...));就会报错,因为我们已经给List指定了数据类型为Student
show1(list1);
System.out.println("************分割线**************");
//这里我们并没有给List指定具体的数据类型,可以存放多种类型数据
List list2 = new ArrayList<>();
list2.add(new Student("zhaoliu",22,1));
list2.add(new Teacher("sunba",30,0));
show2(list2);
}
第三章 Class<?>[]
经过了上面的说明,这个声明的意思已经很好理解了,接收一个Class类的泛型数组,实现泛型的类随意.