在Java中转换为泛型方法类型变量时的编译器警告

gde*_*ohn 4 java generics reflection casting

编辑:我最初接受了我的答案,但我并不满意,因为我想要正确使用泛型.所以,我一直在做研究并找到了解决方案.请在下面的答案中阅读相关内容.


这是一段自包含的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 }
Run Code Online (Sandbox Code Playgroud)

运行此打印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));
Run Code Online (Sandbox Code Playgroud)

但是这给出了一个编译错误,我无法做出头脑或尾巴.

---- jGRASP exec:javac -g -Xlint:unchecked Sandbox.java
Sandbox.java:8:
发现不兼容的类型:捕获#898的?
必需:T
1错误

---- jGRASP wedge:进程的退出代码是1.
---- jGRASP:操作完成.

capture#每当我尝试使用相同的代码行编译时,旁边的数字就不同了.

那么问题到底是什么?当我将调用返回的对象转换为类型变量时,为什么会收到警告?这是否表明我做错了什么?我怎么写这个警告消失了?我宁愿不用注释来压制它,因为这似乎不是我的解决方案.

gde*_*ohn 5

我进一步研究了这一点,发现我可以通过使用类文字作为运行时类型标记来解决问题,如Java教程中所述.

我有正确的想法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));
}
Run Code Online (Sandbox Code Playgroud)

这是一个示例电话.

foo(Character.class, String.class.getMethod("charAt", int.class), "test", 1, 'e');
Run Code Online (Sandbox Code Playgroud)

编译时没有警告并打印true到控制台.请注意,如果您希望底层方法返回一个原语,则returnType参数需要是其各自的包装类.