当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在Java中使用Class<T>?》经验,为你挑选了5个好方法。

有一个很好的讨论泛型和他们在这个问题的幕后真正做了什么,所以我们都知道这Vector是一个整数数组的向量,并且HashTable是一个表,其键是字符串和值Persons.然而,困扰我的是使用Class<>.

java类Class也应该采用模板名称,(或者我在eclipse中通过黄色下划线告诉我).我不明白我应该放在那里.Class对象的整个要点是当您没有完全拥有关于对象,反射等的信息时.为什么它让我指定Class对象将保持哪个类?我显然不知道,或者我不会使用该Class对象,我会使用具体的一个.



1> Kanagavelu S..:

我们所知道的是" 任何类的所有实例都共享该类类型的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只是一个符号,就像在编写类文件时声明的变量名(可以是任何名称).稍后
在初始化期间T将被有效的类名替换(HashMap map = new HashMap();)

例如) 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可以用作modelNumberInteger类型,

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

现在,上面是简单的POJO,它可以在运行时以不同的方式使用.
集合例如List,Set,Hashmap是根据T的声明使用不同对象的最佳示例,但是一旦我们将T声明为String,
例如)HashMap map = new HashMap();然后它将只接受String Class实例对象.

通用方法

通用方法是引入其自己的类型参数的方法.这类似于声明泛型类型,但类型参数的范围仅限于声明它的方法.允许使用静态和非静态泛型方法,以及泛型类构造函数.

泛型方法的语法包括一个类型参数,在尖括号内,并出现在方法的返回类型之前.对于泛型方法,类型参数部分必须出现在方法的返回类型之前.

 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与实例绑定.

另请阅读泛型限制


我对有界野外卡的回答http://stackoverflow.com/questions/1368166/what-is-a-difference-between-super-e-and-extends-e/15252219#15252219

2> Yuval..:

使用类的类的通用版本允许您(除其他外)编写类似的东西

Class someCollectionClass = someMethod();

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



3> raupach..:

从Java文档:

[...]更令人惊讶的是,班级已经普及.类文本现在用作类型标记,提供运行时和编译时类型信息.这样可以在新的AnnotatedElement接口中使用getAnnotation方法示例的静态工厂样式:

 T getAnnotation(Class annotationType); 

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

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

在泛型之前,您必须将结果转换为Author.此外,您无法让编译器检查实际参数是否表示Annotation的子类.[...]

好吧,我从来没有使用过这种东西.任何人?


我(以为我)做了.我使用的框架(各种类型)要求您传递模块所依赖的服务的类名.我在其上构建了一个采用Class对象的图层,以限制选择的数量.使用`Class <?扩展X>`符号我想我可以将它限制为'服务'类型.除了没有常见的"服务"类型,所以我只能用`Class <?>`来做.唉.

4> Kire Haglin..:

class在创建服务注册表查找时发现有用.例如

 T getService(Class serviceClass)
{
    ...
}



5> bruno conde..:

正如其他答案所指出的那样,为什么这class是通用的有很多很好的理由.但是,很多时候您无法知道要使用的泛型类型Class.在这些情况下,您可以简单地忽略黄色日食警告,或者您可以使用Class......这就是我的方式;)

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有