Win a copy of Functional Reactive Programming this week in the Other Languages forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

An atypical type puzzle (Java)

 
Istvan Kovacs
Ranch Hand
Posts: 100
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
We are all taught Java has single inheritance (each class may extend 0 or 1 class). We're also taught about the keyword final meaning no class may extend this one. Finally, we all know that abstract classes cannot be instantiated.

I'm now asking you to call TypePuzzle.puzzle with objects that get it to print "Good solution". The method classPuzzle does a number of checks:
  • child directly extends Object
  • child has (at least) two more supertypes
  • those supertypes are unrelated abstract final classes, whose instances are parent1 and parent2, respectively


  • Have fun! :-)

     
    Ernest Friedman-Hill
    author and iconoclast
    Marshal
    Pie
    Posts: 24212
    35
    Chrome Eclipse IDE Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Don't think that because no one has replied, no one is interested. This is a good one! I'm waiting for my old buddy Mike to stop by and tell us the answer though...
     
    Campbell Ritchie
    Sheriff
    Pie
    Posts: 50251
    79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Unrelated abstract final classes? Can you have an abstract final class at all?
     
    Ernest Friedman-Hill
    author and iconoclast
    Marshal
    Pie
    Posts: 24212
    35
    Chrome Eclipse IDE Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:Unrelated abstract final classes? Can you have an abstract final class at all?


    The compiler won't let you create one, but that doesn't mean the JVM can't make one for you.
     
    Istvan Kovacs
    Ranch Hand
    Posts: 100
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote: abstract final classes? Can you have an abstract final class at all?


    That's not the only weirdness here :-)
    Those classes are final, yet they'll have a subclass. They're also abstract, yet you'll need to pass an instance of each. You can even instantiate such a class without using the keyword new, but if you wish, you can use it.

    Ernest is on the right track.
     
    Istvan Kovacs
    Ranch Hand
    Posts: 100
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Check Javadoc of Class.isAssignableFrom. It references the JLS. Widening reference conversions (the key to this puzzle) are in fact in section 5.1.5, not 5.1.4, here:
    http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.5.
    Just read that and follow links to the referenced sections.

    If there's no solution within a few days, I'll post an even more specific pointer to the relevant section of the JLS. After that, the solution becomes trivial.

     
    Mike Simmons
    Ranch Hand
    Posts: 3090
    14
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Nice one, Istvan!
     
    Mike Simmons
    Ranch Hand
    Posts: 3090
    14
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    (And hi, EFH!)
     
    Istvan Kovacs
    Ranch Hand
    Posts: 100
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mike Simmons wrote:
    Nice one, Istvan!


    Glad you liked it :-)

    The idea came while I was writing an in-house training material on generics, and I wanted to show participants the differences between class hierarchies of arrays and typed ArrayList.
     
    Anil Bharadia
    Greenhorn
    Posts: 15
    Eclipse IDE jQuery
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ernest Friedman-Hill wrote:
    Campbell Ritchie wrote:Unrelated abstract final classes? Can you have an abstract final class at all?


    The compiler won't let you create one, but that doesn't mean the JVM can't make one for you.


    but how can i tell JVM that i want one ?
     
    Istvan Kovacs
    Ranch Hand
    Posts: 100
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Anil Bharadia wrote:but how can i tell JVM that i want one ?


    You cannot ask the JVM to create one, they will be created automatically. Read on to find out why:

    The abstract, final classes in question are arrays.
    When you create a type (e.g. MyClass), the JVM creates the corresponding array class automatically.
    So, for each type (class or interface, what's more, even primitive types, like int), you have an array class that corresponds to it:
    int.class -> int[].class
    String.class -> String[].class
    MyClass.class -> MyClass[].class

    (If you are confused with the .class thing, it denotes the object representing the type. For example:


    The solution Mike has posted here used pre-defined types, but to understand what's going on, you can create ones of your own.


    By defining those interfaces and the class, you (get the JVM to) also implicitly define the corresponding array classes.
    A.class -> A[].class
    B.class -> B[].class
    C.class -> C[].class

    According to the Java Language Specification (JLS), if for two types it is true that

    then it also holds that


    Since class C implements both interfaces A and B, both will become supertypes (not superclasses!) of C, which means that a reference of interface A or B may be set to point to an instance of class C:



    This means that

    will hold, and thus

    will also hold.

    You cannot extend an array class, which made me suspect that they are final. Upon examining their modifiers (see lines 25-27 of the original puzzle code where superIsFinalAbstractClass is calculated), I found they were also abstract, which just made for a confusing-enough puzzle to post here.

    So

    is a valid solution.

    In Mike's answer, he used pre-defined types Integer, Serializable and Comparable, because the Integer class implements the interfaces Serializable and Comparable, just like class C implements interfaces A and B.
     
    Vlado Zajac
    Ranch Hand
    Posts: 245
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Istvan Kovacs wrote:
    You cannot extend an array class, which made me suspect that they are final. Upon examining their modifiers (see lines 25-27 of the original puzzle code where superIsFinalAbstractClass is calculated), I found they were also abstract, which just made for a confusing-enough puzzle to post here.


    They may not be abstract in other JREs. According to getModifiers() API documentations, it is not defined if array classes have abstract modifier or not.
     
    Ernest Friedman-Hill
    author and iconoclast
    Marshal
    Pie
    Posts: 24212
    35
    Chrome Eclipse IDE Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I think you just have to ignore the modifiers here. It really makes no sense for them to be abstract, as I can directly create instances with "new", and it makes no sense for them to be final because, as this puzzle shows, they enter into inheritance relationships. Maybe the "final" is helpful for a compiler, as the compiler won't let you the programmer extend such a class, and actually, the normal "new" bytecode isn't used for array objects, but rather there's a "newarray" bytecode, so perhaps the "abstract" makes sense as a signal to the compiler too.

    But in any case: thanks for posting this!
     
    Anil Bharadia
    Greenhorn
    Posts: 15
    Eclipse IDE jQuery
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    thanks Istvan,,

    i tried the following code



    now i unserstood the concept of array types

     
    Istvan Kovacs
    Ranch Hand
    Posts: 100
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ernest,

    I was also surprised to see that array classes are abstract. I was not too surprised about them being final, for the exact reason you mention, to prevent this:


    Arrays forming a type hierarchy is a necessary evil: before generics, we didn't have wildcards. If Java wanted to be able to handle arrays of related classes (like being able to provide a method that can sum arrays containing Number or any of its subtypes), there was no other way but to twist the type system to allow such hierarchies. The side effect is ArrayStoreException, and multiple superclasses for some classes in a language that advocates single inheritance between classes. :-(

    With generics and collections, we have a better way in the form of bounds and wildcards (T extends Number, ? extends Number). However, some generic code can look really frightening, e.g. Collections.min is defined as:


    Or (generified Observer/Observable from the book 'Java Generics and Collections'):


    But I'm getting off-topic :-)
     
    Avishkar Nikale
    Ranch Hand
    Posts: 173
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    This is a highly informative post.

    Thanks to all who gave their inputs.
     
    Eugene Rabii
    Ranch Hand
    Posts: 30
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    This question made my day! Thank you so much!
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic