0

Consider the following code:

MyClass myClass= new MyExtendedClass();
myClass.method();

where MyExtendedClass be a subtype of MyClass. As i understood on a compile state compiler on the second string compiler checked of existence method method()in a source code of MyClass. Is it correct reasoning? Now consider

List<Integer> ints= new ArrayList<Integer>();
ints.add(2);
List<? extends Integer> lst = ints;
lst.get(0);

Where i can see the sources of List<? extends Integer>? Now consider:

new ArrayList<Integer>().getClass().equals(
    new ArrayList<String>().getClass());// return true.

So In a run time classes ArrayList<Integer> and ArrayList<String> are equals, but on a compile state it is not true. Why? Where are the sources of ArrayList<String> and ArrayList<Integer>?

St.Antario
  • 23,179
  • 26
  • 96
  • 243
  • 1
    I don't understand your question. – Rohit Jain Sep 25 '13 at 16:35
  • I want to know, what are compiler doing when in the code we are calling a method? Consider `List extends Integer> lst = ints; lst.get(0);`. What are compiler doing when we call `get(int)`? – St.Antario Sep 25 '13 at 16:38
  • *Where can I see the sources of `List extends Integer>`?* You can see its javadoc **here**: [`java.util.List`](http://docs.oracle.com/javase/7/docs/api/java/util/List.html). – Luiggi Mendoza Sep 25 '13 at 16:38
  • http://docjar.com/html/api/java/util/List.java.html – jlordo Sep 25 '13 at 16:45
  • Possible duplicate of [What is the concept of erasure in generics in java?](http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java) See also: [Java generics - type erasure - when and what happens](http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens) – Paul Bellora Sep 25 '13 at 17:44

3 Answers3

1

Search for type erasure. To start you can refer http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

Akhilesh Singh
  • 2,330
  • 1
  • 11
  • 10
0

For myClass.method(); to be legal, the MyClass class or interface must declare the method method. That is correct.

The reason that the getClass results are equal for ArrayList<Integer> and ArrayList<String> is that at runtime, type erasure erases the generic type parameters, leaving ArrayList in both cases, and of course they are both equal. It is only the compiler that can distinguish between ArrayList<Integer> and ArrayList<String>. The JVM never knew about generics, so type erasure occurs to be backwards compatible with pre-generics (pre-Java 1.5) applications.

rgettman
  • 167,281
  • 27
  • 248
  • 326
  • It is not for *type safety purposes*, it is for **backward compatibility** purposes from Java 1.4.2 or older. – Luiggi Mendoza Sep 25 '13 at 16:39
  • By the way, there's no **definitive** source code for `ArrayList` or another Java SE classes/interfaces. Please note that you're showing OpenJDK 6 source code (not sure why not OpenJDK 7), and I can bet this is not used on JRockit or IBM JVM implementations (just to mention a couple). – Luiggi Mendoza Sep 25 '13 at 16:41
  • @LuiggiMendoza True about type safety/backwards compatibility; my initial revision was unclear. – rgettman Sep 25 '13 at 16:42
0

Java does not work the way that C++ does. In C++ a "template" causes a complete generation of a new class with that referenced type in it. Java, however, does not generate a new class for every templated instantiation. Instead, the type information is carried as a setting at compile and run time. So ArrayList<Integer> and ArrayList<String> make use of the same actual class.

The type checking is in the compiler, and for simple classes this is easy.

class Gem {...}
class Ruby extends Gem {...}
class Diamond extends Gem {...}

Gem a;
Ruby b;
Diamond c;

a = b;   //no problem allowed
b = a;   //type problem, need to cast it!
b = c;   //never allowed!

But parameterized classes are much more complicated

List<Gem> la;
List<Ruby> lb;
List<Diamond> lc;

la = lb;   //not allowed because type is different even though Ruby extends Gem

List<? extends Gem> ld;

ld = la;  //allowed
ld = lb;  //also allowed
ld = lc;  //also allowed

The wildcards are needed to allow you to have a collection variable that holds more than one kind of collection, where the differences are in the type parameter. In all cases the object class (and source code) remains the same.

AgilePro
  • 4,774
  • 2
  • 28
  • 51
  • That is would I would imagine. That `ArrayList` and `ArrayList` make use of the same class. – Marcelo Sep 25 '13 at 16:48
  • @AgilePro I understand you, that in run time we have raw type only. But compiler considering `ArrayList` and `ArrayList`as a different classes. Hence if we calling `List lst = ints; lst.add(0);` compiler checking method `add(int)` in source of `List` where `T` defined to `Integer`. Its correct? But what compiler are doing if he saw `List extends Integer> lst = ints; lst.add(0);`? – St.Antario Sep 25 '13 at 17:07
  • Inheritance for single typed classes is obvious - either A is a super class of B, or not. But parameterized classes add extra dimensions. The wildcards allow you more flexibility with regard to the checking that the compiler does. This does nothing for Integer and String since they are not related by any parent class. But if you did want to have collections for classes that ARE related, the wildcards allow you to pass them around more easily. READ http://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html – AgilePro Sep 25 '13 at 21:59