编辑:我最初接受了我的答案,但我对此并不满意,因为我想要正确使用泛型。所以,我一直在做研究并找到了解决方案。请阅读以下my answer中的相关内容。
这是一段自包含的Java代码,展示了我正在尝试做的事情。它可以正确编译,运行和运行。
1 import java.lang.reflect.Method;
2 import java.lang.reflect.InvocationTargetException;
3
4 public class Example
5 {
6 public static <T> void foo(Method method, String target, Object argument, T expectedReturn) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
7 {
8 T actualReturn = (T) method.invoke(target, argument);
9 System.out.print(actualReturn.equals(expectedReturn));
10 }
11
12 public static void main(String[ ] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
13 {
14 foo(String.class.getMethod("charAt", int.class), "test", 1, 'e');
15 }
16 }
运行它会将true
打印到控制台,这正是我所期望的。困扰我的是,由于第8行的演员表,我在编译时会收到警告,如下所示(顺便说一句,jGRASP是我的IDE)。
---- jGRASP exec:javac -g -Xlint:未选中Sandbox.java
Sandbox.java:8:警告:[未选中]未经检查的施放
发现:java.lang.Object
要求:T
1警告---- jGRASP:操作完成。
最初,我在没有强制转换的情况下尝试了第8行,但是在编译失败时抱怨找到Object
时需要T
invoke
返回Object
})。后来,我这样写了一遍,盲目地希望摆脱警告。
T actualReturn = method.getReturnType( ).cast(method.invoke(target, argument));
但是这给出了一个编译错误,我不能做头或尾。
---- jGRASP exec:javac -g -Xlint:未选中Sandbox.java
Sandbox.java:8:不兼容的类型
发现:捕获#898的?
要求:T
1错误---- jGRASP wedge:进程的退出代码是1.
---- jGRASP:操作完成。
每次尝试使用相同的代码行编译时,capture#
旁边的数字都不同。
那么,究竟是什么问题?当我将调用返回的对象转换为类型变量时,为什么会收到警告?这是否表明我做错了什么?我怎么写这个警告消失了?我宁愿不用注释来压制它,因为这对我来说似乎不是一个解决方案。
答案 0 :(得分:5)
我对此进行了更多调查,发现我可以通过使用类文字作为运行时类型标记来解决问题,如Java Tutorials中所述。
我对method.getReturnType( ).cast(...)
有了正确的想法,但它没有用,因为getReturnType( )
的返回类型是Class<?>
,我需要Class<T>
。
所以,这就是现在的方法。
public static <T> void foo(Class<T> returnType, Method method, String target, Object argument, T expectedReturn) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
T actualReturn = returnType.cast(method.invoke(target, argument));
System.out.print(actualReturn.equals(expectedReturn));
}
这是一个示例电话。
foo(Character.class, String.class.getMethod("charAt", int.class), "test", 1, 'e');
编译时没有警告,并将true
打印到控制台。请注意,如果您希望底层方法返回一个原语,则returnType参数必须是其各自的包装类。
答案 1 :(得分:1)
为什么要将其投放到T
?你为什么不这样做?
Object actualReturn = method.invoke(target, argument);
System.out.print(actualReturn.equals(expectedReturn));
哦,如果方法可以返回null而expectedReturn
不是,那就更好了:
Object actualReturn = method.invoke(target, argument);
System.out.print(expectedReturn.equals(actualReturn));
答案 2 :(得分:0)
那么,究竟是什么问题?为什么 我施放时会收到警告吗? 通过调用返回的对象 类型变量?
方法可以返回任何Object。并且在所有情况下都不能转换为T.
这表明我在做什么 有什么不对吗?
将反射和泛型混合起来是不好的做法,imho。
我怎么写这个以便 警告消失了吗?
就个人而言,我认为如果不进行重构,你无法避免这种警告。