我有一个泛型Class Factory类,它有两个方法,一个利用class泛型T值,另一个只使用它自己的方法泛型定义。
public class GenericClassFactory<T extends ClassMatchable> {
public <E, K> E newObject(ClassMatcher<E, K> matcher, K key, String packageName){...}
public <K> T newObject(K key, String packageName){...}
}利用T泛型的方法工作得很好,但是当我想使用另一个不关心T泛型是什么的方法时,它不会使用泛型E,它只会返回一个对象,然后我不得不对它进行类型转换。
Data data = new GenericClassFactory().newObject(new ClassMatcher<Data, String>(){...}, "key1", "my.package.name.impl");这有编译错误,因为它希望我将其类型转换为(Data)。如果我向GenericClassFactory传递一个有效的类泛型,它将会工作。这就像如果你定义了一个类泛型但没有使用,它就不能识别方法泛型。
Data data = new GenericClassFactory<ClassMatchable>().newObject(new ClassMatcher<Data, String>(){...}, "key1", "my.package.name.impl");这很好用。但是,当我的目的不需要它时,我不得不定义一个类泛型,这是愚蠢的。我可以这样做:
public class GenericClassFactory {
public <E, K> E newObject(ClassMatcher<E, K> matcher, K key, String packageName){...}
public <T extends ClassMatchable, K> T newObject(K key, String packageName){...}
}但是现在我的第二个方法似乎太宽了,或者something...maybe不是。我的意思是,如果你赋值给返回类型的对象没有实现ClassMatchable,它仍然会给出编译错误。那是我应该走的路吗?这样我就不用打字了?
发布于 2011-04-21 01:37:29
没错,如果不输入类引用,那么即使是只使用方法类型参数的泛型方法也不会被泛化。这是Java泛型中比较奇怪的细微差别之一。正如您所说,您可以为T添加一些任意类型
Data data = new GenericClassFactory<ClassMatchable>().newObject(new ClassMatcher<Data, String>(){...}, "key1", "my.package.name.impl");但更有可能的是,这甚至不应该是一个实例方法。它不能是一个静态方法吗?如果是这样,您可以像这样调用它:
Data data = GenericClassFactory.newObject(new ClassMatcher<Data, String>(){...}, "key1", "my.package.name.impl");编辑
请注意,这将扩展到所有实例成员,而不仅仅是泛型实例方法。因此,有一些更简单的案例可以证明这种奇怪的细微差别。此代码编译时仅显示警告:
public class Scratchpad<T> {
List<String> list;
public static void main(String[] args) {
Scratchpad sp = new Scratchpad();
List<Integer> list = sp.list;
}
}这是因为sp.list被解析为List,而不是List<String>,即使Scratchpad.list与T无关。
在JLS, Section 4.8中详细记录了这一点
未从其超类或超接口继承的原始类型C的构造函数(§8.8)、实例方法 (§8.8、§9.4)或非静态字段(§8.3)的类型在与C对应的泛型声明中擦除其类型。原始类型C的静态成员的类型与其在与C对应的泛型声明中的类型相同。
发布于 2011-04-21 01:45:19
在调用该方法时,应告知E和K的实际类型:
new GenericClassFactory<ClassMatchable>().<TypeforE, TypeforK>newObject(...)看起来Java不能从参数中推断出它。
当然,还有:
如果你定义了一个类泛型但没有使用,它就像
不能识别方法泛型一样。
是完全正确的。
发布于 2011-04-21 02:19:13
如果你定义了一个类泛型但没有使用,它就像
不能识别方法泛型一样。
完全正确。如果您在一个类上定义了一个泛型约束,然后在没有提供任何泛型约束的情况下实例化该类(也就是说,您完全放弃了<> ),那么您就进入了的领域,在这个领域中,一切都不再相同。
原始类型的存在只是为了向后兼容。根据Angelika Langer的优秀Java Generics FAQ,
在将泛型引入
编程语言之后,不鼓励在编写的代码中使用原始类型。根据Java语言规范,Java编程语言的未来版本可能不允许使用原始类型。
它也是states
原始类型的
方法或构造函数具有类型擦除后的签名。如果擦除操作更改了参数类型,则对原始类型的方法或构造函数调用会生成未检查的警告。
如果newObject()方法没有使用它所属类的类型参数T,那么您的设计就有问题:newObject()很可能应该成为一个静态方法。
但是,如果由于某种原因,它确实必须是实例方法,则可以使用wildcard type GenericClassFactory<?>使其正常工作
GenericClassFactory<?> gcf = new GenericClassFactory();
Data data = gcf.newObject(new ClassMatcher<Data, String>(){...}, "key1", "my.package.name.impl"); https://stackoverflow.com/questions/5734248
复制相似问题