Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Generics and casting in Java 1.5

Options
  • 21-04-2007 8:49pm
    #1
    Subscribers Posts: 4,076 ✭✭✭


    Does anyone know how one is supposed to use the new Class.cast(Object) functionality in Java 1.5?

    The documentation for Class.cast(Object) is fine, it's quite clear. My problem is that I can't figure out how to get a Class<T> where T is a reference type and not a wildcard type. For example, a Class<String> rather than a Class<? extends String>.

    Imagine the following code:
    Class<Comparable<String>> castingClass = ???
    Comparable<String> foo = castingClass.cast("foo");
    

    What can I fill in for ???

    Attempt A:
    Comparable<String> foo = "bar";
    foo.getClass() returns a Class<? extends Comparable>
    

    Attempt B:
    Comparable.class.getClass() returns Class<? extends Object>
    

    Attempt C:
    Class.forName("java.lang.Comparable") returns Class<?>
    

    Does anyone know how one would get what I'm looking for? (Ideally a solution that doesn't involve writing my own ClassLoader, although I'm not sure that would do either.)

    Perhaps it isn't possible to ever cast to anything other than a wildcard type, but that strikes me as a bit silly. Yes, I know I can do an unchecked cast, but surely the point of having Class.cast(Object) is to avoid those?


Comments

  • Closed Accounts Posts: 551 ✭✭✭funktastic


    Hmm, When using generics usually, both sides would be cast. I don't know what "bar" would be.

    Eg: List<Type> x = new ArrayList<Type>();

    "bar"<String> sounds crazy. Don't have java installed here so can't test.


  • Subscribers Posts: 4,076 ✭✭✭IRLConor


    funktastic wrote:
    Hmm, When using generics usually, both sides would be cast. I don't know what "bar" would be.

    Eg: List<Type> x = new ArrayList<Type>();

    "bar"<String> sounds crazy. Don't have java installed here so can't test.

    Sorry, I should have explained Attempt A a little more clearly:

    java.lang.String implements Comparable<String>, so:
    // Construct the same String object twice, but with two 
    // different declared types for the references.
    String fooAsString = new String("foo");
    Comparable<String> fooAsComparable = new String("foo");
    
    // The following are all legal
    Class a = fooAsString.getClass();
    Class b = fooAsComparable.getClass();
    Class<?> c = fooAsString.getClass();
    Class<?> d = fooAsComparable.getClass();
    Class<? extends String> e = fooAsString.getClass();
    Class<? extends Comparable> f = fooAsComparable.getClass();
    
    // This is illegal, the compiler says:
    // found   : java.lang.Class<capture of ? extends java.lang.Comparable>
    // required: java.lang.Class<? extends java.lang.Comparable<java.lang.String>>
    Class<? extends Comparable<String>> g = fooAsComparable.getClass();
    
    // This is illegal, the compiler says:
    // found   : java.lang.Class<capture of ? extends java.lang.String>
    // required: java.lang.Class<java.lang.String>
    Class<String> h = fooAsString.getClass();
    
    // This is illegal, the compiler says:
    // found   : java.lang.Class<capture of ? extends java.lang.Comparable>
    // required: java.lang.Class<java.lang.Comparable>
    Class<Comparable> i = fooAsComparable.getClass();
    
    // This is illegal, the compiler says:
    // found   : java.lang.Class<capture of ? extends java.lang.Comparable>
    // required: java.lang.Class<java.lang.Comparable<java.lang.String>>
    Class<Comparable<String>> j = fooAsComparable.getClass();
    

    I need something like i or, preferably, j to use Class.cast(Object) properly, but I don't know how I can get one.


  • Registered Users Posts: 11,980 ✭✭✭✭Giblet


    Comparable<String> caant be runnng class of an object as it is an intertface


  • Subscribers Posts: 4,076 ✭✭✭IRLConor


    The bit between the <> is a "type variable" not a "type". That nice bit of ambiguity is thanks to the Java Language Spec (v3) :rolleyes:

    Also, you have always been able to cast to an interface. Remember stuff like this in Java 1.4?
    List list = new ArrayList();
    list.add("foo");
    list.add("bar");
    for (Iterator i = list.iterator(); i.hasNext(); ) {
        Comparable c = (Comparable)i.next();
        System.out.println(c.compareTo("foo"));
    }
    

    Or am I misunderstanding you?


  • Registered Users Posts: 21,264 ✭✭✭✭Hobbes


    The <cast> part is not the same as (cast).

    The first one tells the compiler that only the following object specified is allowed to be returned or put into an object. When you compile it will automatically put the casts in for you in the related lines.

    (Cast) on the other hand actually wraps a returned object.

    Your going a bit overboard on your casts tbh.

    <? extends X> = Your object can accept or return any subtype of X, however that means subclass of X (concrete or abstract) or an interface.

    Your earlier stuff looks very wrong. Can you explain in english what exactly it is you want to do?
    Comparable<String> fooAsComparable = new String("foo");
    

    String already implements Comparable. So the comparator would only be from the String class as Comparable is an interface and has no code.

    What benefit do you get from doing this? Also new String("foo") is very wasteful. Never do in real code.

    As for your 1.4 code. in 5 it would be.
    List<String> list = new ArrayList<String>();
    	   list.add("foo");
    	   list.add("bar");
    	   
    	   for (String string : list) {
    		   System.out.println(string.compareTo("foo"));
    	   }
    


  • Advertisement
  • Subscribers Posts: 4,076 ✭✭✭IRLConor


    It's hard to explain the problem using the real code, but if you're interested enough, I'm trying to convert the unchecked cast on line 393 of http://exemplar.googlecode.com/svn/trunk/tests/junit/src/junit/com/mcdermottroe/exemplar/NormalClassTestCase.java into a checked cast.

    The most simple way of asking my question is:

    How can I create an instance of Class<String>?


  • Registered Users Posts: 21,264 ✭✭✭✭Hobbes


    You can't create an instance of Class.


  • Subscribers Posts: 4,076 ✭✭✭IRLConor


    Sure you can:
    Class stringClass = Class.forName("java.lang.String");
    

    It just appears to be impossible to create a parameterized Class which as far as I can see it renders Class.cast(Object) almost completely useless. Since they included Class.cast(Object) in the Java 1.5 API I had assumed there was some way of creating the Class instances needed to use it. Perhaps I'm wrong.


  • Subscribers Posts: 4,076 ✭✭✭IRLConor


    Actually, it's not as simple as that, sorry.

    I can get a Class<String> OK, just not a Class for a parameterized type, e.g. Class<List<String>>.
    // This does it for Class<String>
    Class<String> stringClass = String.class;
    
    // This doesn't parse due to List<String>.class being illegal.
    Class<List<String>> listStringClass = List<String>.class;
    

    From digging around on the Java forums it appears that what I'm trying to do isn't possible. From reading the JLS there doesn't appear to be any reason why it shouldn't work (the type erasure is still possible) but it doesn't appear to be implemented in javac.

    Thanks anyway to all those who answered.


Advertisement