We are currently in the process of migrating an application from Java 7 to Java 8. After fixing a some compilation issues, I stumbled upon an issue similar to the following question: ClassCast Error: Java 7 vs Java 8.
To summarise, here is a sample code that shows the issue:
public class Test {
public static void main(String[] args) {
System.out.println(String.valueOf(getVal("xxx"))); // 7: prints the result, 8: Exception
}
@SuppressWarnings("unchecked")
public static <T> T getVal(String param) {
// do some computation based on param...
return (T) result; // actual return type only depends on param so the caller knows what to expect
}
}
The idea was that we would trust that the caller knows the expected type, and this would avoid him an explicit cast (I’m not saying this was a good idea…). In a lot of cases, the caller just expects an Object
so there was no implicit cast at all.
As stated in the question above, the String.valueOf
example worked fine in Java 7 because there was no type inference, hence Object
was assumed. Now in Java 8, the compiler chooses the most specific type (here char[]
), which causes a ClastCastException
at runtime.
The problem is that we have around 350 calls of this getVal
method. Is there a way to detect overloaded method calls that would differ between Java 7 and Java 8? I.E. detect when the Java 8 compiler would select a different method from the Java 7 compiler.
Class<T> clazz
parameter. This way you can have an explicit error handling: either return null or throw some more specific exception. I just did this manually spending like half an hour. I advise you to do the same. I don't know how to automatize it, thus this is not qualified as an answer to your question. – Localism@SuppressWarnings("unchecked")
… – Royroyal@SuppressWarnings
on the method call themselves, it's only in the declaration ofgetVal
. Removing this annotation here will thus not show any of the problematic usages. – AylsworthgetVal
has been declared is the problem. So looking for the annotation will lead you to the right spot. Then, fixing the signature will, of course, raise compiler errors at the callers so they’ll be easy to find. Unless you use an IDE which refactors the signature and the callers in one go, which is a viable alternative. Of course, once the annotation has guided you to the problematic method, finding its callers works even without changing it, if you use a decent IDE. So the necessary tools are available… – RoyroyalObject
will automatically fix the problematic calls, so ironically there will be no change there (and I will maybe never know where they were :-). – AylsworthgetVal
method, I still fear that there are some other methods somewhere which may be declared similarly (maybe not in such an obvious way) which could cause the same issue, and be difficult to spot… – Aylsworth