如何在Java中使用Class <T>?

关于泛型和他们在这个问题背后的真实情况有很好的讨论,所以我们都知道Vector<int[]>是一个整型数组的向量,而HashTable<String, Person>是一个表,其键是字符串和值Person 。 然而,让我感到困惑的是Class<>的用法。

java class Class应该也采用模板名称,(或者我被eclipse中的黄色下划线告知)。 我不明白我应该放在那里。 Class对象的全部重点是当你没有完全掌握关于对象的信息,反射等等。 为什么它会让我指定Class对象将保存哪个类? 我显然不知道,或者我不会使用Class对象,我会使用特定的对象。


使用class类的基础化版本可以让你等写下类似的东西

Class<? extends Collection> someCollectionClass = someMethod();

然后你可以确定你接收到的Class对象扩展了Collection ,并且这个类的一个实例将是(至少)一个Collection。


我们所知道的是“任何类的所有实例共享该类型类的相同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<Student> studentClassRef = t.getClass(); //Compilation error.

现在什么是T? T是类型参数(也称为类型变量); 用尖括号(<>)分隔,跟在类名之后。
T只是一个符号,就像在写入类文件时声明的变量名(可以是任何名称)。 之后T将被替换
初始化期间有效的类名( HashMap<String> map = new HashMap<String>();

例如) class name<T1, T2, ..., Tn>

所以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可以用作CarName的 String类型

OR T可以用作Integer类型作为modelNumber

OR T可以用作Object类型作为有效的汽车实例

现在,上面是简单的POJO,它可以在运行时以不同的方式使用。
集合例如)List,Set,Hashmap是最好的例子,它可以根据T的声明使用不同的对象,但是一旦我们将T声明为String
例如) HashMap<String> map = new HashMap<String>(); 那么它只会接受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之前。

在下面; 类型声明<T>在方法级别不需要,因为它已经在类级别声明。

class MyClass<T> {
   private  T myMethod(T a){
       return  a;
   }
}

但是下面是错误的,因为类级别类型参数K,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与实例绑定在一起。

另请阅读泛型的限制


从Java文档:

更令人惊讶的是,班级已被基因化。 类文字现在用作类型标记,提供运行时和编译时类型信息。 这可以在新的AnnotatedElement接口中启用由getAnnotation方法示例的静态工厂类型:

<T extends Annotation> T getAnnotation(Class<T> annotationType); 

这是一种通用的方法。 它从它的参数中推断出它的类型参数T的值,并返回一个适当的T实例,如下面的片段所示:

Author a = Othello.class.getAnnotation(Author.class);

在泛型之前,您必须将结果呈现给Author。 你也没有办法让编译器检查实际参数是否表示Annotation的子类。 [...]

那么,我从来不用这种东西。 任何人?

链接地址: http://www.djcxy.com/p/23983.html

上一篇: How to use Class<T> in Java?

下一篇: Meaning of new Class(...){{...}} initialization idiom