Java 为什么泛型方法更改赋值中的参数化类型?
在编写处理表单数据的通用方法时,我遇到了以下(在我看来)未执行的行为。给定以下代码:Java 为什么泛型方法更改赋值中的参数化类型?,java,generics,Java,Generics,在编写处理表单数据的通用方法时,我遇到了以下(在我看来)未执行的行为。给定以下代码: public class Test { public <T> void someGenericMethod(Integer a) { @SuppressWarnings("unchecked") T t = (T) a; System.out.println(t); System.out.println(t.getClass()); }
public class Test {
public <T> void someGenericMethod(Integer a) {
@SuppressWarnings("unchecked")
T t = (T) a;
System.out.println(t);
System.out.println(t.getClass());
}
public static void main(String[] args) {
Test test = new Test();
test.<BigDecimal>someGenericMethod(42);
}
}
事实上,如果我向方法签名添加另一个参数(如字符串b
),并进行另一次赋值t2=(T)b
,程序将打印
42
class java.lang.String
为什么t
变量将其类型更改为Integer
(很可能是对类型t进行了某种升级,使其成为对象)
对此行为的任何解释都是受欢迎的(T)a
是未经检查的强制转换:由于运行时无法知道T是什么类型,因此它实际上无法检查a是否属于T类型
执行此操作时,编译器会发出警告;在您的例子中,您已通过写入@SuppressWarnings(“未选中”)
来抑制该警告
编辑后添加(回答下面评论中的进一步问题): 如果要检查强制转换,可以编写以下内容:
public class Test {
public <T> void someGenericMethod(Class<T> clazz, Integer a) {
T t = clazz.cast(a);
System.out.println(t);
System.out.println(t.getClass());
}
public static void main(String[] args) {
Test test = new Test();
// gives a ClassCastException at runtime:
test.someGenericMethod(BigDecimal.class, 42);
}
}
但那是
main
的错误,而不是someGenericMethod
。:-) 编译时,上面的代码基本上变成了以下非泛型方法:
public void someGenericMethod(Integer a) {
Object t = a;
System.out.println(t);
System.out.println(t.getClass());
}
没有演员阵容。没有例外。您在方法签名中指定了一个类型参数,但从不使用它 我想你想要这样的东西:
public class Test {
public <T> void someGenericMethod(T someItem) {
System.out.println(someItem);
System.out.println(someItem.getClass());
}
}
public static void main(String[] args) {
Test test = new Test();
BigDecimal bd = new BigDecimal(42);
test.someGenericMethod(42); // Integer
test.someGenericMethod("42"); // String
test.someGenericMethod(42L); // Long
test.someGenericMethod(bd); // BigDecimal
}
公共类测试{
public void someGenericMethod(T someItem){
System.out.println(someItem);
System.out.println(someItem.getClass());
}
}
公共静态void main(字符串[]args){
测试=新测试();
BigDecimal bd=新的BigDecimal(42);
test.someGenericMethod(42);//整数
test.someGenericMethod(“42”);//字符串
test.someGenericMethod(42L);//长
test.someGenericMethod(bd);//BigDecimal
}
请注意,不需要强制转换
参数类型在方法签名中声明并从参数推断
在您的代码中,您正在参数化方法调用(我从未见过),并传入一个int
很难理解您想做什么,因为您的示例代码什么都不做。是的,是未经检查的强制转换,但是为什么不抛出
ClassCastException
而不是将T
的类型更改为Object
?因为它是未经检查的强制转换。运行时无法检查强制转换的有效性。如果运行时可以检查强制转换,它将看到它无效,并抛出一个ClassCastException
;但它不能,所以它不能,也不能。我不知道你为什么会有其他想法。未经检查强制转换的定义是,如果在运行时知道完整的类型信息,它无法检查是否会抛出ClassCastException
。感谢您的澄清,不知道未经检查强制转换意味着,测试中的
东西。如果方法签名不包含至少一个T
参数,则某些泛型方法调用是非常无用的?谢谢,因此如果不在方法签名中添加类型为T
的参数,
是无用的。。。
public void someGenericMethod(Integer a) {
Object t = a;
System.out.println(t);
System.out.println(t.getClass());
}
public class Test {
public <T> void someGenericMethod(T someItem) {
System.out.println(someItem);
System.out.println(someItem.getClass());
}
}
public static void main(String[] args) {
Test test = new Test();
BigDecimal bd = new BigDecimal(42);
test.someGenericMethod(42); // Integer
test.someGenericMethod("42"); // String
test.someGenericMethod(42L); // Long
test.someGenericMethod(bd); // BigDecimal
}