我有这个小问题,我想知道发生了什么事情发生在我身上: 我做了这样的课:
public class SomeSimpleClass {
//and I had method who returns generic. it can be instance of whatever, and for sure can be casted to U:
public <U>U giveMeSomething(String arg) {
return (U)SomewhereSomething.getValueCastingIsOK(arg);
}
}
然后我就像这样使用它:
// give me some number:
Integer number = instanceSomeSimpleClass.giveMeSomething("I want integer value");
OR
String text = instanceSomeSimpleClass.giveMeSomething("I want text now");
一切都好。来自SomewhereSomething的getValueCastingIsOK返回我想要的东西,而且我不需要在giveMeSomething上输入类型。看起来U被关联变量中的类型替换了......一切都很酷..
然后我创建了一个新类:
public class SomeOtherClass <T extends Something> {
//And I have the exactly same method here:
public <U>U giveMeSomething(String arg) {
return (U)SomewhereSomething.getValueCastingIsOK(arg);
}
}
现在当我想以同样的方式使用它时,编译器(我正在使用Java 1.7)告诉我,我必须使用类型转换,并开始使用这样的giveMeSomething,因为U现在是对象,没有别的......
Integer number = (Integer)instanceSomeSimpleClass.giveMeSomething("I want integer value");
:(
为什么在第二种情况下,编译器无法以相同的方式获取U类型,如第一种情况。而我必须做的就是这样做?
感谢答案,建议..;)
答案 0 :(得分:1)
问题是您使用的是类SomeOtherClass
的原始类型,但没有为您的声明提供任何类型参数:
SomeOtherClass instanceSomeSimpleClass = new SomeOtherClass();
执行此操作时,Java编译器将使用类型擦除版本替换类中的所有泛型,甚至是不相关的泛型,例如泛型方法。方法的类型擦除
public <U>U giveMeSomething(String arg) {
变为
public Object giveMeSomething(String arg) {
需要转换为Integer
。
你必须向SomeOtherClass
提供一个类型参数(没用,除非你已经删除了使用T
在这里发布类代码的不必要的代码):
SomeOtherClass<Something> instanceSomeSimpleClass = new SomeOtherClass<Something>();
或者你可以删除类定义中的type参数,就像你原来的那样:
public class SomeSimpleClass {
要么保持泛型方法的完整性,又无需转换giveMeSomething
的返回类型。
答案 1 :(得分:1)
您缺少显式输入的java语法:
public <U>U giveMeSomething(String arg) {
return SomewhereSomething.<U>getValueCastingIsOK(arg);
}
注意点和方法名称之间的<U>
。另请注意,现在不需要进行投射。
这就是你如何明确声明类型化方法的类型。如果没有这个,java必须推断这个类型,它不能在这里,所以(不安全)转换是必需的。
另一个例子来说明。在这种情况下,java可以推断类型为Integer
,因为结果被分配到的类型:
Integer number = instanceSomeSimpleClass.giveMeSomething("I want integer value");
但是如果您在不指定值的情况下使用该值,则需要传递给:
someIntegerRequired(instanceSomeSimpleClass.<Integer>giveMeSomething("I want integer value"));