6

Why this happened? One line in the code works well while the other similar line doesn't. Does the automatic type cast only happen in certain conditions? I have tried to assign gt.echoV() to an Object and it works well; but when I assign it to a String, the same error will come out again.

public class GeneMethodTest {

    public static void main(String... args) {
        GeneMethodTest gt = new GeneMethodTest();
        gt.<String>echoV(); //this line works well
        gt.<String>echoV().getClass();//this line leads to a type cast exception                                                          
    }

    public <T> T echoV() {
        T t=(T)(new Object());                                                                    
        return t;
    }
}
10
  • 1
    This answer may help stackoverflow.com/a/3437930/1316346 Commented Jul 31, 2013 at 18:53
  • (T)(new Object()) is an unchecked cast - make sure to read up on what that is and its implications, along with type erasure. Commented Jul 31, 2013 at 18:55
  • Yup, i know that. @PaulBellora Actually (T)(new Object()) will do nothing during run time because of type erasure. The problem is when I call gt.<String>.echoV() the automatic class casting doesn't take effect while it does take effects when i call gt.<Stirng>echo.getClass() Commented Jul 31, 2013 at 19:00
  • @PaulBellora care to explain your comment a bit further ? from the documentation: "Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods." docs.oracle.com/javase/tutorial/java/generics/erasure.html Commented Jul 31, 2013 at 19:06
  • @charles_ma That's because the <String> in of itself has nothing to do with casting - it's just the type argument to the generic method. gt.<String>echoV() alone requires no cast to be inserted by the compiler, so that doesn't fail at runtime. Commented Jul 31, 2013 at 19:08

3 Answers 3

4

gt.<String>echoV().getClass(); produces the equivalent of the following sequence of operations:

// Inside echoV
Object t = new Object();  // Note that this is NOT a String!
Object returnValue = t;
// In main
String stackTemp = (String) returnValue;  // This is the operation that fails
stackTemp.getClass();

What you get "for free" with generics is that (String) cast. Nothing else.

Sign up to request clarification or add additional context in comments.

2 Comments

That's right. It seems the compiler will figure out when to insert code rather than insert it every single time~
@charles_ma - Yep, take away the getClass and the compiler figures there's no need for the cast.
2

This works perfect, nothing special, normal use of generics

gt.<String>echoV(); //this line works well

Here do we have something less obvious. Because generic method are defined at runtime does the jvm not know what kind of Class the generic method will return at compiletime, hence the classTypeException

gt.<String>echoV().getClass();//this line leads to a type cast exception   

you should allocated it to a variable first, because the jvm does know the type of the variable at compiletime

String s = gt.<String>echoV();
s.getClass();

7 Comments

Actually if you do System.out.println(gt.<String>echoV()) you got a java.lang.ClassCastException.
same problem, System.out.println expects a string as parameter. If this is not the case, it will call the toString() of the object, but at compileat does the jvm not know from what object
I believe maybe it's because in the first line, i called the function but didn't use the reference so the compiler didn't bother adding any class cast code; but in the second line, i tried to use the resulting reference from the call so the compiler had to insert class casting code there~ And same situation when you call System.out.println(gt.<String>echoV()) @System.exit
@user1394628 every object has a toString() method hence it doesn't have anything to do with things that happened during compile-time.
@user1394628 I believe String s = gt.<String>echoV(); will produce a class cast exception at runtime too~
|
1

change this line:

gt.<String>echoV().getClass();

to:

(gt.echoV()).getClass();

and it'll compile
(it'll return: class java.lang.Object)

The root of the ClassCastException is that the method returns t (of generic type T which is an object) and you try to downcast it to a String. You can also change your code to return:

return (T)"some-string";

in order to remove the error.

Generic are used by the compiler to check what type of object to expect, so it can catch mistakes the developer made in compile time (vs. run-time errors). So IMHO this way of using generics beats the purpose.

4 Comments

downvoter - care to write a comment ? did I write something inaccurate ?
I think the question is about the use of Generics, not the ´getClass()´ itself method.
@System.exit I think that my answer covers that as well.
Actually, I'm seeing that you made some modifications :). I think I judged your answer too early, but yes, now your answer covers the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.