1

I wrote some code as follow:

public class MyClass {
    public static void main(String[] args) {
        printIt(getLong());
        System.out.println("---------");
    }

    public static Object printIt(Object... objects) {
        System.out.println(objects[0].toString());
        return objects[0];
    }

    public static <T> T getLong() {
        return (T)Long.valueOf(1L);
    }
}

When I run it, it throws java.lang.ClassCastException as follow:

Exception in thread "main" java.lang.ClassCastException: java.lang.Long cannot be cast to [Ljava.lang.Object; at com.sealinetech.MyClass.main(MyClass.java:5)

But when I debug it with Evaluate Expression, It's OK Evaluate Expression is OK

My IDE is intellij, and the JDK version is jdk1.8.0_144

VPK
  • 3,010
  • 1
  • 28
  • 35
Rhett
  • 29
  • 1
  • You are casting `Long` to `Object[]`. Just don't do it. – rkosegi Jan 29 '18 at 11:12
  • 7
    I'd strongly discourage a method signature like your `public static T getLong()`, where you can't infer the type T from any **arguments**. Typical usage has some argument of type T, e.g. `public static T doSomething(T arg)`. – Ralf Kleberhoff Jan 29 '18 at 11:34
  • 2
    Exactly as every textbook says. When you ignore “unchecked” warnings, you may get strange `ClassCastException`s at runtime… – Holger Jan 29 '18 at 14:06
  • 1
    Similar to [this issue](https://stackoverflow.com/q/40737967/2711488)… – Holger Jan 29 '18 at 14:40
  • When I run the application, it throws ClassCastException in the printIt(getLong()) line, but I copy printIt(getLong()) into Evaluate Expression tool then click Evaluate button, it can output result properly, just like the picture above. So I want to know why java use the different type inference method in to ways. – Rhett Jan 30 '18 at 02:05

2 Answers2

0

getLong method has generic return type. at compile time compiler decides call it with Object[] result type, because printIt accepts this argument type. in runtime compiler suggestion fails so you get this error: java.lang.Long cannot be cast to [Ljava.lang.Object

you can specify expected type with printIt(this.<Object>getLong()); (thanks to @CoderinoJavarino)

Sergii Lagutin
  • 10,561
  • 1
  • 34
  • 43
0

As already mentioned, the exception comes from the fact that the compiler resolves T to be Object[] rather than Object.

I get that this the code is just a toy example for something more complex. Depending on what the actual scenario is, an alternative solution to what has been already suggested is to constraint the return of type-parameter T to a non-array type of choice. In this trivial example perhaps it would be something like <T extends Number>.

However, it needs to be pointed out that only looking at the question code, it seems quite clear that given the name of the method, it is going to return Long or perhaps a long if null, is not a valid value, here it simply makes far more sense to get rid of the type-paramter T and set the return type as Long or long.

Valentin Ruano
  • 2,726
  • 19
  • 29