Jim
Jim

Reputation: 19582

Fundamentals on Generics

Why does the following does not work?

Vector<? extends SomeClass> v = new Vector<SomeClass>();  
SomeClass e = new SomeClass();  
v.add(e);  

I get a compilation error that:

The method add(capture#1-of ? extends SomeClass) in the type Vector is not applicable for the arguments (SomeClass)

Upvotes: 2

Views: 149

Answers (4)

zagyi
zagyi

Reputation: 17528

The problem basically is that by declaring v as Vector<? extends SomeClass> you say that it's a collection of SomeClass or one of its subclasses. The compiler cannot make any assumptions about what specific type the container actually hold, even if the assignment to new Vector<SomeClass>() is done on the same line. As much as the compiler knows v might have been created as new Vector<SubClassOfSomeClass>(). That is why it refuses to put SomeClass instances (or anything else for that matter) to the collection. You can however get the SomeClass elements out of it.

If you want to be able to put elements to the collection, then declare v as Vector<? super SomeClass>, by which you say that it's a container of SomeClass or one of its superclasses. The compiler knows then that a SomeClass instance will certainly fit in such a collection.
You cannot however get a SomeClass element out of that collection, as the compiler knows nothing about the type of elements in it (except that it is some superclass of SomeClass). By the definition of v it might as well be just a collection of Objects.

This is called the put/get principle in short which is discussed in detail also in other posts like this.

Upvotes: 3

Reimeus
Reimeus

Reputation: 159864

Collections with generic wildcards which extend from a type do not allow you to add to that Collection.

As the compiler does not know exactly what type of SomeClass you are attempting to add, it doesn't allow it. The exception to this is a null object which can represent any type of Object.

To answer your comment: Although you cannot add to the Collection, it cannot be described as read only as it is still possible to remove Objects.

To allow addition of Objects, you would need to use a known type:

Vector<SomeClass> v = new Vector<SomeClass>();

Upvotes: 4

nageswara rao
nageswara rao

Reputation: 64

There should not be problem to you in your problem explanation. I understood your problem as in the following code.

import java.util.*;
class Test
{
  int x;
}
public class Demo
{
   public static void main(String args[])
   {
      Vector<Test> vect = new Vector<Test>();

      Test t1 = new Test();
      Test t2 = new Test();
      t1.x = 10;
      t2.x = 20;

      vect.add(t1);
      vect.add(t2);

      for(Test t : vect)
      {
         System.out.println(t.x);
      }  
  }
}

I read this type of gimmicks in Vector Play With.

Upvotes: -1

Dariusz
Dariusz

Reputation: 22291

This is explained here. The list declared like that is effectively a read-only list, but it is more flexible than a normal List<AbstractClass> list.

If you want to use an abstract class as a template, just use it straight on like this: List<SomeClass> list.

Consider reading Java language specification, there is a lot of information about the generics logic.

Upvotes: 1

Related Questions