Reputation: 29316
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
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
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
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