7

It is detail, but I want to know why this happens.

Exemplary code:

Class klasa = Enum.class;
for(Type t : klasa.getGenericInterfaces())
   System.out.println(t);

Output o the program:

java.lang.Comparable<E>
interface java.io.Serializable

Why on the output there is no interface word before java.lang.Comparable<E>. It is interface, yes?

In my opinion output should be:

**interface** java.lang.Comparable<E>
interface java.io.Serializable

Comparable is specially treated?

Pawel
  • 1,457
  • 1
  • 11
  • 22

3 Answers3

3

The toString method of ParametrizedTypeImpl(the internal Type of Comparable), indicates that "interface" is not outputted in any case:

public String toString() {
    StringBuilder sb = new StringBuilder();

    if (ownerType != null) {
        if (ownerType instanceof Class)
            sb.append(((Class)ownerType).getName());
        else
            sb.append(ownerType.toString());

        sb.append(".");

        if (ownerType instanceof ParameterizedTypeImpl) {
            // Find simple name of nested type by removing the
            // shared prefix with owner.
            sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$",
                                     ""));
        } else
            sb.append(rawType.getName());
    } else
        sb.append(rawType.getName());

    if (actualTypeArguments != null &&
        actualTypeArguments.length > 0) {
        sb.append("<");
        boolean first = true;
        for(Type t: actualTypeArguments) {
            if (!first)
                sb.append(", ");
            if (t instanceof Class)
                sb.append(((Class)t).getName());
            else
                sb.append(t.toString());
            first = false;
        }
        sb.append(">");
    }

    return sb.toString();
}

In the toString method of Class, on the other hand, "interface" is clearly output if the class is an interface.

public String toString() {
    return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
        + getName();
}
FThompson
  • 28,352
  • 13
  • 60
  • 93
Pratik Shelar
  • 3,154
  • 7
  • 31
  • 51
1

What happens is that you get two different subclasses of java.lang.reflect.Type; one that is a generic type (probably j.l.r.ParameterizedType), and one that is a specific (non-generic) interface type (a j.l.Class<?>).

What do you want to do with that information, and why?

Tassos Bassoukos
  • 16,017
  • 2
  • 36
  • 40
  • 2
    I want only to know why word `interface` is missing. This is `interface`, but `interface` word is missing. – Pawel Oct 09 '13 at 09:12
  • 1
    Because two different versions of `toString()` are called; the Class> version that adds the interface, and the `ParameterizedType` subclass version that doesn't. Still, is this an academic question, or do you need to perform decisions based on that data? – Tassos Bassoukos Oct 09 '13 at 09:14
  • This is academic question for my future knowledge. – Pawel Oct 09 '13 at 09:16
  • 1
    If you have access to the OpenJDK sources, have a look into `java.lang.Class#toString()` and `sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl#toString()`. – Tassos Bassoukos Oct 09 '13 at 09:19
1

java.lang.Class#toString

public String toString()

Converts the object to a string. The string representation is the string "class" or "interface", followed by a space, and then by the fully qualified name of the class in the format returned by getName. If this Class object represents a primitive type, this method returns the name of the primitive type. If this Class object represents void this method returns "void".

sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl#toString()

public String More ...toString() {
    StringBuilder sb = new StringBuilder();

    if (ownerType != null) {
        if (ownerType instanceof Class)
            sb.append(((Class)ownerType).getName());
        else
            sb.append(ownerType.toString());

        sb.append(".");

        if (ownerType instanceof ParameterizedTypeImpl) {
            // Find simple name of nested type by removing the
           // shared prefix with owner.
            sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$",
                                     ""));
        } else
            sb.append(rawType.getName());
    } else
        sb.append(rawType.getName());

    if (actualTypeArguments != null &&
        actualTypeArguments.length > 0) {
        sb.append("<");
        boolean first = true;
        for(Type t: actualTypeArguments) {
            if (!first)
                sb.append(", ");
            if (t instanceof Class)
                sb.append(((Class)t).getName());
            else
               sb.append(t.toString());
           first = false;
        }
        sb.append(">");
    }

    return sb.toString();
}  

After call to toString() method of ParameterizedTypeImpl does not append interface keyword. It just calls getName() method.

The name interface java.lang.Comparable is there in t. After statement System.out.println(t); calls toString().
You can see below image, when I debug

enter image description here

Aniket Kulkarni
  • 12,825
  • 9
  • 67
  • 90