关于模板:如何在Java中使用class

How to use Class<T> in Java?

在这个问题上,我们有一个很好的讨论,关于泛型以及它们在幕后的实际操作,所以我们都知道Vector是整数数组的向量,HashTable是一个键为字符串和值Person的表。然而,令我头疼的是Class<>的用法。

Java类EDCOX1(4)也应该采取模板名称,(或者说,在Eclipse中的黄色下划线告诉我)。我不明白该放什么进去。Class对象的全部要点是,当您没有完全掌握关于对象的信息时,您需要进行反射等等。为什么要指定Class对象将持有哪个类?我显然不知道,或者我不会使用Class对象,我会使用特定的对象。


我们只知道"任何类的所有实例共享同一类的java.lang.Class对象"

例如)

1
2
Student a = new Student();
Student b = new Student();

那么,a.getClass() == b.getClass()是正确的。

现在假设

1
Teacher t = new Teacher();

没有仿制药,以下是可能的。

1
Class studentClassRef = t.getClass();

但现在这是错误的….

例如,可以用Teacher.class调用public void printStudentClassInfo(Class studentClassRef) {}

这可以避免使用泛型。

1
Class<Student> studentClassRef = t.getClass(); //Compilation error.

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

例如)class name

因此,Class表示特定类类型"T"的类对象。

假设类方法必须使用以下未知的类型参数

1
2
3
4
5
6
7
8
9
10
11
/**
 * 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

或者t可以用作Integer类型作为型号,

或者t可以用作Object类型的有效汽车实例。

现在,上面是简单的pojo,可以在运行时使用不同的pojo。集合(例如)list、set、hashmap是最好的例子,可以根据t的声明使用不同的对象,但是一旦我们将t声明为string例如)HashMap map = new HashMap();,那么它只接受字符串类实例对象。

泛型方法

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
 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;
}

这里,是方法参数中使用的类型的声明,该方法参数应该位于返回类型(这里是boolean之前)。

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

1
2
3
4
5
class MyClass<T> {
   private  T myMethod(T a){
       return  a;
   }
}

但下面是错误的,因为类级类型参数k、v、z和y不能在静态上下文中使用(此处为静态方法)。

1
2
3
4
5
6
7
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());
    }
}

其他有效方案包括

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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;
        }
    }

最后,静态方法总是需要显式的声明;它不会从类级Class派生。这是因为类级别t与实例绑定。

同时阅读对泛型的限制


使用generified版本的类的类,允许你写的东西,在其他事情上,样

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

然后你可以确信你收到Collection扩展类对象,类和实例这将(至少)收集。


从Java的文档:

[……]更奇怪,已经generified舱舱。现在literals AS类功能型标记,提供两个运行时和编译时类型信息。这一风格的exemplified提供静态工厂方法在新的getannotation annotatedelement界面:

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

这是一个通用的方法。它infers其类型参数T的值从它的参数和返回的适当的实例,如下面的代码片断:画报red

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

现有的仿制药,你将不得不到作者灌注的结果。所以你会做的有没有办法代表的实际参数,编译器检查a)标注收藏指正.[……]

嗯,我从来没有使用这个小东西。任何人?


我发现当我创建Classuseful服务注册中心查找。例如

1
2
3
4
<T> T getService(Class<T> serviceClass)
{
    ...
}

其他答案一点退房,有许多的原因,为什么这个位置是由Class通用。然而,有足够的时间,你没有办法知道一个Class通用型使用。在论文的情况下,你可以简单的忽略警告或黄河Eclipse,你可以使用Class…这是我做的;)


在下面的回答@ kire haglin example of a与泛型方法,可以在文档的湖泊:JAXB解包

1
2
3
4
5
6
7
8
public <T> T unmarshal( Class<T> docClass, InputStream inputStream )
         throws JAXBException {
  String packageName = docClass.getPackage().getName();
  JAXBContext jc = JAXBContext.newInstance( packageName );
  Unmarshaller u = jc.createUnmarshaller();
  JAXBElement<T> doc = (JAXBElement<T>)u.unmarshal( inputStream );
  return doc.getValue();
}

这允许一个文件返回一unmarshalJAXB在树型的任意内容。


你想要一个Class使用通配符。例如,Class,会允许你指定的,这是一些一流大学JComponent收藏指正.如果你的ClassClass.forName检索实例,然后你可以使用Class.asSubclass做演员之前说,N的,构建的实例。


为了引入另一个例子,类的通用版本(Class允许编写如下通用函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static <T extends Enum<T>>Optional<T> optionalFromString(
        @NotNull Class<T> clazz,
        String name
) {
    return Optional<T> opt = Optional.ofNullable(name)
            .map(String::trim)
            .filter(StringUtils::isNotBlank)
            .map(String::toUpperCase)
            .flatMap(n -> {
                try {
                    return Optional.of(Enum.valueOf(clazz, n));
                } catch (Exception e) {
                    return Optional.empty();
                }
            });
}

在一开始它是到位。但它使在下面的情况:

1
2
3
4
5
6
7
class SomeAction implements Action {
}

// Later in the code.
Class<Action> actionClass = Class.forName("SomeAction");
Action action = actionClass.newInstance();
// Notice you get an Action instance, there was no need to cast.


只是使用:牛肉类

1
2
3
4
5
6
7
8
public <T> T beefmarshal( Class<beef> beefClass, InputBeef inputBeef )
     throws JAXBException {
     String packageName = docClass.getPackage().getBeef();
     JAXBContext beef = JAXBContext.newInstance( packageName );
     Unmarshaller u = beef.createBeef();
     JAXBElement<T> doc = (JAXBElement<T>)u.beefmarshal( inputBeef );
     return doc.getBeef();
}