小编典典
我们所知道的是“ 任何类的所有实例共享该类类型的相同java.lang.Class对象 ”
例如)
Student a = new Student();
Student b = new Student();
那a.getClass() == b.getClass()是真的。
现在假设
Teacher t = new Teacher();
没有泛型,下面是可能的。
Class studentClassRef = t.getClass();
但这是错误的..?
例如)public void printStudentClassInfo(Class studentClassRef) {}可以用Teacher.class
使用泛型可以避免这种情况。
Class studentClassRef = t.getClass(); //Compilation error.
现在什么是T ?? T是类型参数(也称为类型变量);用尖括号(<>)分隔,并紧随类名。
T只是一个符号,就像在编写类文件时声明的变量名(可以是任何名称)一样。稍后,
在初始化(HashMapmap = new HashMap();)时将用有效的类名替换T
例如) class name
因此Class表示特定类类型为' T' 的类对象。
假设你的类方法必须使用未知的类型参数,如下所示
/**
* Generic version of the Car class.
* @param the type of the value
*/
public class Car {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
在这里T可以String用作CarName的类型
OR T可以用作modelNumber的Integer类型,
OR T可以用作有效的汽车实例的Object类型。
现在,上面是简单的POJO,可以在运行时以不同的方式使用它。
集合(例如List,Set,Hashmap)是最好的示例,它们将根据T的声明与不同的对象一起工作,但是一旦我们将T声明为String(
例如)HashMap map = new HashMap();,则它将仅接受String类实例对象。
通用方法
泛型方法是引入自己的类型参数的方法。这类似于声明泛型类型,但是类型参数的范围仅限于声明它的方法。允许使用静态和非静态通用方法,以及通用类构造函数。
通用方法的语法包括类型参数,尖括号内,并且出现在方法的返回类型之前。对于泛型方法,类型参数部分必须出现在方法的返回类型之前。
class Util {
// Generic static method
public static boolean compare(Pair p1, Pair p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
class Pair {
private K key;
private V value;
}
这是方法参数中使用的类型声明,该声明应在boolean此处的返回类型之前。
在下面;在方法级别不需要类型声明,因为它已经在类级别声明了。
class MyClass {
private T myMethod(T a){
return a;
}
}
但是下面是错误的,因为不能在静态上下文中使用类级类型参数K,V,Z和Y(此处为静态方法)。
class Util {
// Generic static method
public static boolean compare(Pair p1, Pair p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
其他有效场景
class MyClass {
//Type declaration already done at class level
private T myMethod(T a){
return a;
}
// is overriding the T declared at Class level;
//So There is no ClassCastException though a is not the type of T declared at MyClass.
private T myMethod1(Object a){
return (T) a;
}
//Runtime ClassCastException will be thrown if a is not the type T (MyClass).
private T myMethod1(Object a){
return (T) a;
}
// No ClassCastException
// MyClass obj= new MyClass();
// obj.myMethod2(Integer.valueOf("1"));
// Since type T is redefined at this method level.
private T myMethod2(T a){
return a;
}
// No ClassCastException for the below
// MyClass o= new MyClass();
// o.myMethod3(Integer.valueOf("1").getClass())
// Since is undefined within this method;
// And MyClass don't have impact here
private T myMethod3(Class a){
return (T) a;
}
// ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
// Should be o.myMethod3(String.valueOf("1").getClass())
private T myMethod3(Class a){
return (T) a;
}
// Class a :: a is Class object of type T
// is overriding of class level type declaration;
private Class myMethod4(Class a){
return a;
}
}
最后,静态方法总是需要显式声明。它不会从课堂上获得Class。这是因为类级别T与实例绑定。
2020-03-20