Compiler warning when switching to a typical method type variable in Java

Edit: I initially accepted the answer, but I was not very happy with this, since I wanted to use generics correctly. So, I continued to do research and found a solution. Read about it in my answer below.


Here is a bit of a self-contained piece of Java code that shows what I'm trying to do. It compiles, runs, and behaves correctly.

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 } 

Running this fingerprint true on the console, as I expected. What bothers me is because on line 8 I get a warning when I compile it as shown below (jGRASP is my IDE, by the way).

---- jGRASP exec: javac -g -Xlint: unchecked Sandbox.java
Sandbox.java:8: warning: [unchecked] unchecked cast
found: java.lang.Object
required: T 1 warning

---- jGRASP: operation completed.

I initially tried line 8 without a cast, but this could not be compiled with an error complaining about finding Object when T is required ( invoke returns Object ). Later I rewrote it like this, blindly hoping to get rid of the warning.

 T actualReturn = method.getReturnType( ).cast(method.invoke(target, argument)); 

But this gives a compilation error, due to which I can not make the head and tail.

---- jGRASP exec: javac -g -Xlint: unchecked Sandbox.java
Sandbox.java:8: incompatible types
found: capture # 898 of

required: T 1 error

---- jGRASP wedge: exit code for the process is 1.
---- jGRASP: job completed.

And this number next to capture# is different every time I try to compile the same line of code.

So what is the problem? Why do I get a warning when I return the object returned by calling a type variable? Does this mean that I am doing something wrong? How can I write this so that the warning disappears? And I would rather not overwhelm it with an annotation, since it does not seem to solve many problems.

+4
source share
3 answers

I also studied this and found that I could solve the problem using class literals as tokens of the runtime type, as described in the Java Tutorials .

I had the right idea with method.getReturnType( ).cast(...) , but that did not work, because the return type of getReturnType( ) is Class<?> , And I need Class<T> .

So, here is what the method looks like now.

 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)); } 

And here is an example call.

 foo(Character.class, String.class.getMethod("charAt", int.class), "test", 1, 'e'); 

This compilation without warnings and true prints on the console. Note that if you expect the base method to return a primitive, the returnType parameter must be the appropriate wrapper class.

+5
source

Why did you add it to T ? Why don't you do it this way?

 Object actualReturn = method.invoke(target, argument); System.out.print(actualReturn.equals(expectedReturn)); 

Oh, and if the method can return null, but expectedReturn not, this is better:

 Object actualReturn = method.invoke(target, argument); System.out.print(expectedReturn.equals(actualReturn)); 
+1
source

So what is the problem? Why do I get a warning when I throw an object returned by a call to a variable type?

The method can return any object. And it cannot be applied to T in all cases.

Does this mean that I'm doing something wrong?

This is bad practice for mixing reflections and generics, imho.

How can I write this so that the warning goes away?

Personally, I think that you cannot avoid this warning without refactoring.

0
source

All Articles