Doug Smith
Doug Smith

Reputation: 29316

How does polymorphism differ from generics in Java ArrayLists?

If I have an ArrayList<Shape>, I'm under the impression that within that list I can store objects of class Shape or objects that are subclasses of Shape.

I've also seen a lot of notation around with things like ArrayList<T> or ArrayList<?>. Are these the same things? A T superclass and all its subclasses can be stored, and the ? is just a placeholder?

Basically, how does something like ArrayList<CLASSNAME> differ from ArrayList<T> where you just have the one letter.

Upvotes: 0

Views: 130

Answers (3)

JungJoo
JungJoo

Reputation: 171

First of all, ArrayList can't reference any subclass of Shape like this:

ArrayList<Shape> blah = new ArrayList<Square>

But you can do it this way:

ArrayList<? extends Shape> blah = new ArrayList<Square>

Polymorphism doesn't work with type parameter. It only works with objects such as:

Collection<String> blah = new ArrayList<String>

But you have to understand the purpose of using T. T is used to declare a type parameter for class and methods.

Such that when you declare a class with parameter T:

 public class ArrayList <T>

T acts as a placeholder when the class is instantiated as object.

So in this case:

 ArrayList<String>

you are replacing T with String in the ArrayList class.

Btw, you aren't suppose to use T as a type for argument. Because T isn't really defined, it is only a placeholder.

Upvotes: 1

gerrytan
gerrytan

Reputation: 41123

You express ArrayList<T> when you're declaring the type / class and ArrayList<String> when you're creating an instance of ArrayList and associate it with the type parameter String.

For example:

// class declaration
public class ArrayList<T> extends ... implements ... {
  ...

// Creating an arraylist of string
ArrayList<String> stringArray = new ArrayList<String>

You can think of generics as a type variable. Hence instead of creating a class which only works with String:

public class MyArray {

  String get(int index) { ... }

}

You can create an array class that works with any arbitrary type

public class MyArray<T> {

  T get(int index) { .. }

}

Upvotes: 0

tbodt
tbodt

Reputation: 16987

First, the difference is not whether it is one letter as you might think. It is whether T is the name of a generic argument or not. If you declare a method like:

public <T> void method()

as opposed to:

public void method()

or a class like:

public class Whatever<T>

as opposed to:

public class Whatever

then T is a generic argument. You then get to use T anywhere you want as if it were a real class name, and a real class name will be substituted for T at compile time. But this is not the best picture of it, so let's say that the type of T is whatever type was passed to the arguments of type T. So, at any given moment, T has a value that is a real class name.

So, the difference between ArrayList<T> and ArrayList<Shape> is that ArrayList<T> holds objects of type T, whereas ArrayList<Shape> holds objects of type Shape. The trick is that T is whatever type was passed to arguments of type T, so it can vary.

Disclaimer: The type T does not actually change over time. In most cases, the compiler replaces it with Object. However, the compiler is good at hiding that, and it is a good idea to think of T changing.

Upvotes: 1

Related Questions