Extending Generic Classes

80,975

Solution 1

Let's look at this definition:

public class Extend1<T, E> extends MyGeneric<T, E> {}

Here T and E are each present twice and in two different roles

  • in Extend1<T,E> you define type arguments. This means that the type Extend1 has two (unbounded) type arguments T and E. This tells the Java compiler that those who use Extend1 need to specify the types.
  • in extends MyGeneric<T,E> you use the previously defined type arguments. If T and E were not known to be type arguments here, then T and E would be simple type references, i.e. the compiler would look for classes (or interfaces, ...) named T and E (and most likely not find them).

Yes, type arguments follow the same syntactic rules as any other identifier in Java, so you can use multiple letters ABC or even names that can be confusing (using a type argument called String is legal, but highly confusing).

Single-letter type argument names are simply a very common naming strategy.

Solution 2

I was wondering how Java knows when the types given in the superclass are going to be defined when the subclass is instansiated, and when they are actual class names (i.e. How does it know T, E are not class names)?

Java doesn't care. If you do...

class MyGeneric<String> extends ArrayList<String> {
    String value;
}

is it permissible (even if uncommon) to use more than one letter for the generic types? What if (through some sever error of planning) The types conflict with an existing class e.g.

Yes, you can use any valid Java identifier for type parameters.

Names can be in conflict, but Java won't treat this as an error. Identifiers between <...> will always be treated as type parameters, regardless if the identifier corresponds to a class name.

It may get quite confusing though. Here's an example:

class MyGeneric<String> extends java.util.ArrayList<String> {
    String value;
}

class Test {
    public static void main(String... args) throws Exception {
        MyGeneric<Integer> obj = new MyGeneric<Integer>();
        obj.value = 5;
        //          ^
        //          |
        //          '--- Assign an integer to what seems to be a String!
    }
}

Similar question:

Solution 3

There is no problem with:

public class E{}
public class Foo<E>{}

Because in the context of Foo<E>, E is a type.

Share:
80,975
James
Author by

James

Updated on July 08, 2022

Comments

  • James
    James almost 2 years
    public class MyGeneric<T, E> {}
    
    public class Extend1<T, E> extends MyGeneric<T, E> {}
    
    public class Extend2 extends MyGeneric<String, Object> {}
    

    As far as I am aware, both of the subclasses in the above example are valid. I was wondering how Java knows when the types given in the superclass are going to be defined when the subclass is instantiated, and when they are actual class names (i.e. How does it know T, E are not class names)?

    A side note, is it permissible (even if uncommon) to use more than one letter for the generic types? What if (through some sever error of planning) The types conflict with an existing class e.g.

    public class E{}
    public class Foo<E>{}
    

    what happens then?

    Edit: Thanks for answering so promptly. To answer my first question, Joachim's answer is most effective.

    To answer the side point, aioobe's answer is clearer

  • James
    James over 12 years
    Thanks, that cleared things up a lot (had to read it a couple of times to get my head round it though)
  • aioobe
    aioobe over 12 years
    No problem, you're welcome :-) Good question btw. I've seen other questions asking why class MyList<Integer> extends ArrayList<Integer> doesn't work as expected :-)
  • luketorjussen
    luketorjussen over 12 years
    To clarify - if you put a type name in there, such as String, then when referencing a MyGeneric object, String no longer means java.lang.String, it now means "Some generic type I have named String"??
  • sma
    sma about 9 years
    so when use Extend1<String> extends Generic<String>, the compiler will consider first "String" as a type arg (different from java.lang.String), and second "String" as a type reference to the first one?
  • Joachim Sauer
    Joachim Sauer about 7 years
    @pegausbupt: exactly, it would create a type argument names String that has no real relation to java.lang.String other than confusing people and hiding that types short name.
  • rosshjb
    rosshjb over 2 years
    In Extend1<T, E>, the T and E are type parameters. When generic type invocation happens, the T and E in extends MyGeneric<T, E> would be replaced by type arguments which replaces type parameters T and E in Extend1<T, E>. So, in fact, both generic and non-generic types can extends/implements non-generic types only.