How to use Class<T> in Java?
在这个问题上,我们有一个很好的讨论,关于泛型以及它们在幕后的实际操作,所以我们都知道
Java类EDCOX1(4)也应该采取模板名称,(或者说,在Eclipse中的黄色下划线告诉我)。我不明白该放什么进去。
我们只知道"任何类的所有实例共享同一类的java.lang.Class对象"
例如)
1 2 | Student a = new Student(); Student b = new Student(); |
那么,
现在假设
1 | Teacher t = new Teacher(); |
没有仿制药,以下是可能的。
1 | Class studentClassRef = t.getClass(); |
但现在这是错误的….
例如,可以用
这可以避免使用泛型。
1 | Class<Student> studentClassRef = t.getClass(); //Compilation error. |
现在是什么??t是类型参数(也称为类型变量);由尖括号(<>)分隔,在类名后面。T只是一个符号,就像在编写类文件时声明的变量名(可以是任何名称)。稍后,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可用作
或者t可以用作
或者t可以用作
现在,上面是简单的pojo,可以在运行时使用不同的pojo。集合(例如)list、set、hashmap是最好的例子,可以根据t的声明使用不同的对象,但是一旦我们将t声明为string例如)
泛型方法
泛型方法是引入自己的类型参数的方法。这类似于声明泛型类型,但类型参数的作用域仅限于声明它的方法。允许使用静态和非静态泛型方法以及泛型类构造函数。
泛型方法的语法包括一个类型参数,在尖括号内,并出现在该方法的返回类型之前。对于泛型方法,类型参数部分必须出现在方法的返回类型之前。
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; } |
这里,
在下面,方法级别不需要类型声明
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; } } |
最后,静态方法总是需要显式的
同时阅读对泛型的限制
使用generified版本的类的类,允许你写的东西,在其他事情上,样
1 | Class<? extends Collection> someCollectionClass = someMethod(); |
然后你可以确信你收到
从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)标注收藏指正.[……]
嗯,我从来没有使用这个小东西。任何人?
我发现当我创建
1 2 3 4 | <T> T getService(Class<T> serviceClass) { ... } |
其他答案一点退房,有许多的原因,为什么这个位置是由
在下面的回答@ 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(); } |
这允许一个文件返回一
你想要一个
为了引入另一个例子,类的通用版本(
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 |
只是使用:牛肉类
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(); } |