Java 为什么班级<&燃气轮机;喜欢上课
如果我将类声明为字段:Java 为什么班级<&燃气轮机;喜欢上课,java,generics,raw-types,Java,Generics,Raw Types,如果我将类声明为字段: Class fooClass; Eclipse给了我一个警告: 类是原始类型。提及 泛型类型类应为 参数化 这在实践中意味着什么?为什么要我这么做?如果我要求Eclipse提供“快速修复”,它会给我: Class<?> fooClass; (但从第一天开始使用Java,我并没有真正注意到类何时变得通用) 注意:我接受了@oxbow_lakes,因为这对我来说是有意义的,但这显然是一个非常复杂的领域。我敦促所有程序员使用特定的类,而不是类。而且Class比C
Class fooClass;
Eclipse给了我一个警告:
类是原始类型。提及
泛型类型类应为
参数化
这在实践中意味着什么?为什么要我这么做?如果我要求Eclipse提供“快速修复”,它会给我:
Class<?> fooClass;
(但从第一天开始使用Java,我并没有真正注意到类何时变得通用)
注意:我接受了@oxbow_lakes,因为这对我来说是有意义的,但这显然是一个非常复杂的领域。我敦促所有程序员使用特定的
类
,而不是类
。而且Class
比Class
安全得多,因为自JDK 5以来,Class
现在具有参数化类型,这使得Class
成为通用对象。这对于编译器进行类型检查(当然是在编译时)是必要的(因为引入了泛型)
类
表示“未知类”,其中?
是泛型。它意味着Class
类型的fooClass
接受类型与任何内容匹配的Class
典型示例:
Class<?> classUnknown = null;
classUnknown = ArrayList.class; //This compiles.
Class classUnknown=null;
classUnknown=ArrayList.class//这是一份汇编。
您可以有效地提供更具体的参数化类型,例如:
Class<ArrayList> = ArrayList.class;
Class=ArrayList.Class;
PS记住,Class-listClass=ArrayList.Class
不会编译(即使ArrayList在列表中),但是(正如Mark Peters在评论中提到的)类
这似乎没有增加多少价值
但不再发出警告
你说得对。但这可能会增加价值:
Class<FooClass> fooClass;
Class类;
或者,如果更合适:
Class<? extends FooClass> fooClass;
Class
您基本上是在说“这意味着可以容纳任何类型的类”因为使用原始类型而不是参数化类型有很多缺陷
其中之一是,如果使用原始类型,则该类上的所有泛型都将丢失。即使是按方法定义的那些。原始类型和无界通配符
前面的答案都没有真正说明为什么你更喜欢Class
而不是Class
,因为从表面上看,前者似乎提供的信息并不比后者多
原因是原始类型,即类
,阻止编译器进行泛型类型检查。也就是说,如果使用原始类型,则将颠覆类型系统。例如:
public void foo(Class<String> c) { System.out.println(c); }
但不是通过:
Class<?> w = Integer.class
foo(w); //WILL NOT COMPILE (RIGHTLY SO!)
我想注入它的一个实现,使用一个系统属性来定义要使用的类
Class<?> c = Class.forName(System.getProperty("foo.service"));
该类的Javadoc确实提供了一些关于该类存在类型参数的想法:
T-由建模的类的类型
这个类
对象。例如
String.class的类型是class.
使用Class
,如果类
这是未知的
这个类型参数的使用不是很明显,但是粗略地看一下类的源代码,就会知道为什么有时需要使用类型参数。考虑<代码> NeWistAs/<代码>方法:
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
}
return newInstance0();
}
如果没有注意到,此方法返回的对象的类型就是type参数的类型。这在使用大量反射的代码中非常有用,并且需要格外小心以确保实例化正确类型的对象
考虑到问题中的示例,如果类实例被声明为:
Class<String> fooClass;
Class<Integer> barClass;
String aString;
简而言之,如果要处理类层次结构,并且希望强制执行严格的编译时检查,以确保代码不需要执行大量的实例检查,那么最好指定希望使用的类的类型。指定?
允许所有类型,但在某些情况下,您需要更加具体。+1到目前为止,这是唯一真正回答问题的答案@Poindexter-试试scala。你会意识到Java的类型系统是一个糟糕的笑话,不管是泛型还是非泛型。@oxbow\u lakes我完全同意Java的类型系统是一个笑话。可惜我的工作不知道这一点。SomeType
与SomeType
不同(正如您所注意的)。它与SomeType
相同,其中OtherType是类型参数的边界(如果未指定,则为Object)。因此,Class
与Class
@Mark是一样的-从我上面的例子来看,这显然是错误的!我不能用类调用foo
,因为这会给我一个编译错误问题是为什么喜欢无界通配符而不是原始类型。我不清楚这是不是一个answer@oxbow_lakes当前位置我想说我的最后两句话解释了这一点。当然,您的答案在这方面要彻底得多。Eclipse并没有以特殊的方式处理Class
。当您使用任何原始类型(例如,List
)时,就会发生这种情况。“擦除”可能是一个误导性的词……所有泛型都会在运行时被擦除,原始类型或否都会被更正。但是一些参数化信息在运行时被保留,而不是所有信息都被删除;)在Java中,泛型类型在其类型参数中不是协变的,是通配符绕过了这个类,这是您最后的评论
Class<?> w = Integer.class
foo(w); //WILL NOT COMPILE (RIGHTLY SO!)
public interface FooService
Class<?> c = Class.forName(System.getProperty("foo.service"));
//next line throws ClassCastException if c is not of a compatible type
Class<? extends FooService> f = c.asSubclass(FooService.class);
FooService s = f.newInstance(); //no cast
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
}
return newInstance0();
}
Class<String> fooClass;
Class<Integer> barClass;
String aString;
aString = barClass.newInstance();