File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes generics / adding to wildcard Collection Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "generics / adding to wildcard Collection" Watch "generics / adding to wildcard Collection" New topic
Author

generics / adding to wildcard Collection

Tapio Niemela
Ranch Hand

Joined: Jan 06, 2006
Posts: 77
Hello, I'm puzzled how the "adding" to wildcard java.util.Collection is blocked by the compiler; compiler even suggests that "add"-method doesn't exist. Also how is this different to "putting" element to custom wildcard object.

For example,
Following attempt will produce following compiler error "cannot find symbol / symbol : method add(java.lang.String) / location: interface java.util.List<capture#913 of ? extends java.lang.String>"


while following code (modified example from http://www.ibm.com/developerworks/java/library/j-jtp04298/)

produces compiling error that "put(capture#189 of ? extends T) in OtherBox<capture#189 of ? extends T> cannot be applied to (java.lang.String) box.put("blaa");"

It *seems* that compiler adds some check for Collection add and addAll methods, but surely that can't be true?
Tommy Delson
Ranch Hand

Joined: Apr 13, 2011
Posts: 206
An obvious error that I see is not using "super" keyword when adding to the list. Go back to Chapter 7 on Generic Methods (Exam Objectives 6.3 and 6.4) for more info and to reinforce your knowledge.

Try this:




OCPJP6-05-11
"Your life is in your hands, to make of it what you choose."
Tapio Niemela
Ranch Hand

Joined: Jan 06, 2006
Posts: 77
Hi Tommy and thanks for reply

Yes, I know about the lower bounds, but I was distracted by the different compile errors. Handling wildcards with java.util.List (like trying to add to wildcard-List) generates (at least on my 1.6.0 compiler) different compile error than with the Box-example. With List I get "cannot find symbol" and with "Box"-example I get "cannot be applied" to -error. This really puzzled me. The thing is that if I use Collection.add I get also "cannot be applied"-error, not "cannot find symbol", so I should get "Cannot find symbol" error with modified OtherBox as I do..



So the problem was the distraction from different compile error messages created by my compiler
Tse Wu
Greenhorn

Joined: Jan 05, 2012
Posts: 10
Think about it this way, if you have an animal class and a dog and cat class that extends animal. And you have a method that accepts <? extends animal>, this is saying you could pass anything that is a subclass of the class animal into this method. Now say that you have a dog collection and you pass that dog collection into the method, and in that method you try and add a cat.. now you have a collection of dogs and cats in the dog collection. To prevent this the compiler will not allow adding to the collection using the extend keyword.


OCPJP 1.6
Tommy Delson
Ranch Hand

Joined: Apr 13, 2011
Posts: 206
So the problem was the distraction from different compile error messages created by my compiler


Yes, different Compiler gives you different error message, but the point here is when you using Generics and Collections in such cases you need to use "super" to add or put object in the List or Map, and the "extends" keyword is work fine with getting objects out of the List or Map.

Have you reread the Chapter section that I mentioned in the previous post? If not, I recommended to reread the section several times until you clear the concept.

Hope it help...
Helen Ma
Ranch Hand

Joined: Nov 01, 2011
Posts: 451
Suppose you have a class Node :


And suppose you have another class Foo:

1 . What should be put in the n.set() as parameter? It must be null, nothing else.
Reason:
The compiler does not know what the paremter type n can accept. It can be Integer, Double.... What if n takes an Integer type as the E and then you set this.e to a Double? For this reason, the compiler won't let you pass in any object type paremeter to the set method. It applies to all other situation similar to this example.

2. What should be return from n.get() ? It must be Number. Therefore, you can assign Number aNum= n.get(); where aNum is a null.
Reason:
The compiler only knows n takes a Number type. This is the only information it knows.

3. What should be put in the n1.set() as parameter? It must be some types that are Number or its subtype.
Reason:
If n1 accepts E as a Number and you pass in an Integer as the parameter , it will be setting the E e ( E is substituted by Number) to an Integer. That is ok. If you pass in an Object as the parameter, it will be setting the Number e = new Object(); That won't compile at all. For this reason, the compiler won't let you pass in any type that is the super type of Number.

4. What should be return from n1.get()? It must be Object. Therefore you can assign Object o = n1.get();
Reason:
For case 3, you can only set e of the Node class to be a Number, Double, Integer....(subtypes). For sure, the compiler knows you pass in a Number. Why can't we assign Number myNum = n1.get()? Because you may assign the n1 to a node that takes Object like this:

The compiler only knows n1 takes a Number or an object, but it does not know what exactly it is. The safest return type for the get() is only an object.

Thefore, when you are given any class (Node, List....) with generic parameters, a method that takes the generic parameter as argument and a method that returns the object of the generic parameter type, you will think of the above 4 cases.
This is an example from Mughal and Rasmussen's study guide , chapter 13 Generics.

Summary:
What to put for set's parameter:
Node<? extends Number> Node<? super Number>
set Null Number or its subtype

What to return for get method:
Node<? extends Number> Node<? super Number>
get Number or Object Object only

Mack Wilmot
Ranch Hand

Joined: Jul 27, 2011
Posts: 88

Helen Ma wrote:
2. What should be return from n.get() ? It must be Number. Therefore, you can assign Number aNum= n.get(); where aNum is a null.
Reason:
The compiler only knows n takes a Number type. This is the only information it knows.



Actually, it does not _have_ to be Number, it can be a supertype of Number and it will work just fine.

For example, I could do this: Serializable aSer = n.get(); and it works just fine.
neha chaukar
Greenhorn

Joined: Oct 16, 2013
Posts: 4
please explain me why the code will compile(example given in kathy sierra for scjp 5)

punlic class TestWildcards
{
public static void main(String [] args)
{
List<Integer> mylist =new ArrayList<Integer>();
Bar bar= new Bar();
bar.doInsert(mylist);
}
}



class Bar
{
void doInsert(List<Object> list)
{
list.add(new Dog());
}
}


Dog is a class defined in other examples...
it should give compilation error
Mack Wilmot
Ranch Hand

Joined: Jul 27, 2011
Posts: 88

neha chaukar wrote:please explain me why the code will compile(example given in kathy sierra for scjp 5)

<snip>


It doesn't compile.
neha chaukar
Greenhorn

Joined: Oct 16, 2013
Posts: 4
yeah that is what i think.But in book it given that it will compile..
anyways thanks ..
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4387
    
    8

neha chaukar wrote:yeah that is what i think.But in book it given that it will compile..

The book doesn't say it will compile. It says Bar will compile, but there's a problem with TestWildcards.
Himai Minh
Ranch Hand

Joined: Jul 29, 2012
Posts: 758
List<Object> cannot refer to List<Integer> even though Integer is an object.
For example List<Object> objectList = new ArrayList<Integer>(); won't compile.

 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: generics / adding to wildcard Collection