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

2022-08-31 05:17:36

在这个问题上,对泛型以及它们在幕后的真正作用进行了很好的讨论,所以我们都知道它是整数数组的向量,并且是其键是字符串和值s的表。但是,让我感到困惑的是.Vector<int[]>HashTable<String, Person>PersonClass<>

java类也应该采用模板名称,(或者说,在eclipse中,黄色下划线告诉我)。我不明白我应该放什么。对象的全部意义在于当你不完全拥有关于对象的信息时,用于反射等。为什么它让我指定对象将容纳哪个类?我显然不知道,否则我不会使用该对象,我会使用特定的对象。ClassClassClassClass


答案 1

我们所知道的是“任何类的所有实例共享该类的同一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>

So 表示特定类类型 '' 的类对象。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可以用作类型作为CarNameString

OR T可以用作类型作为模型编号Integer

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

现在,以上是简单的POJO,可以在运行时以不同的方式使用。
集合,例如)List,Set,Hashmap是最好的例子,它们将按照T的声明与不同的对象一起使用,但是一旦我们将T声明为String
,例如)那么它将只接受String Class实例对象。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

在下面;类型声明在方法级别不是必需的,因为它已经在类级别声明。<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 与实例绑定。<T>Class<T>

另请阅读泛型限制

通配符和子类型

泛型方法的类型参数


答案 2

使用类类的生成版本,除其他外,您可以编写诸如

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

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