在这个问题上,对泛型及其在幕后的实际工作进行了很好的讨论,因此我们都知道这Vector<int[]>是整数数组的向量,并且HashTable<String, Person>是一个表,其键是字符串和值Person s。但是,让我感到困扰的是的用法Class<>。
Vector<int[]>
HashTable<String, Person>
Person
Java类Class应该也采用模板名称,(否则,Eclipse中的黄色下划线告诉我)。我不明白该放什么。该Class对象的重点是当你没有完全有关该反射的信息时。为什么要让我指定Class对象将容纳哪个类?我显然不知道,或者我不会使用该Class对象,而是使用特定的对象。
Class
使用Class的通用版本,你可以编写以下内容:
Class<? extends Collection> someCollectionClass = someMethod();
然后,你可以确保收到的Class对象扩展了Collection,并且该类的实例将(至少)是Collection。
Collection
我们所知道的是“ 任何类的所有实例共享该类类型的相同java.lang.Class对象 ”
例如)
Student a = new Student(); Student b = new Student();
那a.getClass() == b.getClass()是真的。
a.getClass() == b.getClass()
现在假设
Teacher t = new Teacher();
没有泛型,下面是可能的。
Class studentClassRef = t.getClass();
但这是错误的..?
例如)public void printStudentClassInfo(Class studentClassRef) {}可以用Teacher.class
public void printStudentClassInfo(Class studentClassRef) {}
Teacher.class
使用泛型可以避免这种情况。
Class<Student> studentClassRef = t.getClass(); //Compilation error.
现在什么是T ?? T是类型参数(也称为类型变量);用尖括号(<>)分隔,并紧随类名。 T只是一个符号,就像在编写类文件时声明的变量名(可以是任何名称)一样。稍后, 在初始化(HashMap map = new HashMap();)时将用有效的类名替换T
例如) class name<T1, T2, ..., Tn>
class name<T1, T2, ..., Tn>
因此Class<T>表示特定类类型为' T' 的类对象。
Class<T>
' T'
假设你的类方法必须使用未知的类型参数,如下所示
/** * Generic version of the Car class. * @param <T> the type of the value */ public class Car<T> { // T stands for "Type" private T t; public void set(T t) { this.t = t; } public T get() { return t; } }
在这里T可以String用作CarName的类型
String
OR T可以用作modelNumber的Integer类型,
Integer
OR T可以用作有效的汽车实例的Object类型。
Object类
现在,上面是简单的POJO,可以在运行时以不同的方式使用它。 集合(例如List,Set,Hashmap)是最好的示例,它们将根据T的声明与不同的对象一起工作,但是一旦我们将T声明为String( 例如)HashMap<String> map = new HashMap<String>();,则它将仅接受String类实例对象。
HashMap<String> map = new HashMap<String>()
通用方法
泛型方法是引入自己的类型参数的方法。这类似于声明泛型类型,但是类型参数的范围仅限于声明它的方法。允许使用静态和非静态通用方法,以及通用类构造函数。
通用方法的语法包括类型参数,尖括号内,并且出现在方法的返回类型之前。对于泛型方法,类型参数部分必须出现在方法的返回类型之前。
class Util { // Generic static method public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) { return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue()); } } class Pair<K, V> { private K key; private V value; }
这<K, V, Z, Y>是方法参数中使用的类型声明,该声明应在boolean此处的返回类型之前。
<K, V, Z, Y>
在下面;<T>在方法级别不需要类型声明,因为它已经在类级别声明了。
<T>
class MyClass<T> { private T myMethod(T a){ return a; } }
但是下面是错误的,因为不能在静态上下文中使用类级类型参数K,V,Z和Y(此处为静态方法)。
V,Z
Y
class Util <K, V, Z, Y>{ // Generic static method public static boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) { return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue()); } }
其他有效场景
class MyClass<T> { //Type declaration <T> already done at class level private T myMethod(T a){ return a; } //<T> is overriding the T declared at Class level; //So There is no ClassCastException though a is not the type of T declared at MyClass<T>. private <T> T myMethod1(Object a){ return (T) a; } //Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>). private T myMethod1(Object a){ return (T) a; } // No ClassCastException // MyClass<String> obj= new MyClass<String>(); // obj.myMethod2(Integer.valueOf("1")); // Since type T is redefined at this method level. private <T> T myMethod2(T a){ return a; } // No ClassCastException for the below // MyClass<String> o= new MyClass<String>(); // o.myMethod3(Integer.valueOf("1").getClass()) // Since <T> is undefined within this method; // And MyClass<T> don't have impact here private <T> 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<T> a :: a is Class object of type T //<T> is overriding of class level type declaration; private <T> Class<T> myMethod4(Class<T> a){ return a; } }
最后,静态方法总是需要显式<T>声明。它不会从课堂上获得Class<T>。这是因为类级别T与实例绑定。