Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the Java Compiler do with multiple generic bounds?

Have a look at this (arguably stupid) code:

public <T extends Appendable & Closeable> void doStuff(T object)
throws IOException{

    object.append("hey there");
    object.close();

}

I know that the compiler removes generic information, so I'm interested in Java 1.4 code equivalent to what the compiler does (I'm pretty sure the compiler doesn't rearrange the source code, so I am asking for an equivalent Java source version which naive people like myself can understand)

Is is something like this:

public void doStuff(Object object)
throws IOException{

    ((Appendable)object).append("hey there");
    ((Closeable)object).close();

}

Or rather like this:

public void doStuff(Object object)
throws IOException{
    Appendable appendable = (Appendable) object;
    Closeable closeable = (Closeable) object;

    appendable.append("hey there");
    closeable.close();

}

Or even like this:

public void doStuff(Appendable appendable)
throws IOException{
    Closeable closeable = (Closeable) appendable;

    appendable.append("hey there");
    closeable.close();

}

Or yet another version?

like image 729
Sean Patrick Floyd Avatar asked Nov 23 '10 16:11

Sean Patrick Floyd


People also ask

What is the function of bounded generic in Java?

Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class. These are known as bounded-types in generics in Java.

Can a parameterized type have several bounds?

A type parameter can have multiple bounds.

What is the purpose of generic types in Java?

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs.


2 Answers

Signature of the method looks like public void doStuff(Appendable appendable), because

The order of types in a bound is only significant in that the erasure of a type variable is determined by the first type in its bound, and that a class type or type variable may only appear in the first position.

(JLS §4.4 Type Variables)

This behaviour may be important if you use reflection to access this method.

Another use of this behaviour is retaining binary compatibility with pre-generic interfaces, as described in Generics Tutorial, section 10 (thanks to Mark Peters for pointing it out). That is,

public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll)

is binary compatible with its pre-generic version returning Object.


Method body is an equivalent of the following, but I think it's implementation details:

appendable.append("hey there"); 
((Closeable) appendable).close(); 
like image 65
axtavt Avatar answered Oct 29 '22 08:10

axtavt


I couldn't wait, I had to go and answer my own question. The answer is a combination of my first and third versions: the first bound is used as variable type, and the object is casted to the second bound whenever needed. This is the resulting byte code (I added a single line break for readability):

  // Method descriptor #20 (Ljava/lang/Appendable;)V
  // Signature: <T::Ljava/lang/Appendable;:Ljava/io/Closeable;>(TT;)V
  // Stack: 2, Locals: 2
  public void doStuff(java.lang.Appendable object) throws java.io.IOException;
     0  aload_1 [object]
     1  ldc <String "hey there"> [26]
     3  invokeinterface java.lang.Appendable.append(java.lang.CharSequence) :
        java.lang.Appendable [28] [nargs: 2]
     8  pop
     9  aload_1 [object]
    10  checkcast java.io.Closeable [34]
    13  invokeinterface java.io.Closeable.close() : void [36] [nargs: 1]
    18  return
      Line numbers:
        [pc: 0, line: 14]
        [pc: 9, line: 15]
        [pc: 18, line: 17]
      Local variable table:
        [pc: 0, pc: 19] local: this index: 0 type: rumba.dumba.Bumba
        [pc: 0, pc: 19] local: object index: 1 type: java.lang.Appendable
      Local variable type table:
        [pc: 0, pc: 19] local: object index: 1 type: T
like image 34
Sean Patrick Floyd Avatar answered Oct 29 '22 08:10

Sean Patrick Floyd