aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Generics Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Generics" Watch "Generics" New topic
Author

Generics

Paredes Be
Greenhorn

Joined: Sep 19, 2006
Posts: 2
Hi guys,
Somebody could I tell me, Why in the marked line, cause a compile error "cannot find symbol" if l tends to be a List and it has the add
method?.

import java.util.*;
class Shape{
}
class Rect extends Shape{
}
class Circle extends Shape{
}
class ShadedRect extends Rect{
}
class Generics2{
public static void add(List<? extends Shape> l,int pos, Rect r){
l.add(pos, r); // Compile Error in this line.Why?
}
public static void main(String args[]){
List<ShadedRect> l = new LinkedList<ShadedRect>();
add( l,0, new ShadedRect() );
}
}
Petrus Pelser
Ranch Hand

Joined: Feb 20, 2006
Posts: 132
Originally posted by Paredes Be:

class Generics2{
public static void add(List<? extends Shape> l,int pos, Rect r){
l.add(pos, r); // Compile Error in this line.Why?
}
public static void main(String args[]){
List<ShadedRect> l = new LinkedList<ShadedRect>();
add( l,0, new ShadedRect() );
}
}


You are trying to add a Rect object to a list that only takes ShadedRect objects. If it was the other way around you would have no problem.

Change:

to:


Or you need to cast the Rect object to a ShadedRect object before adding it to the list.
Anthony Karta
Ranch Hand

Joined: Aug 09, 2004
Posts: 342
Originally posted by Petrus Pelser:

to:



doesn't work. still compile error on the same line. I get confuse now. :roll:
[ September 20, 2006: Message edited by: Tony Keith ]

SCJP 5
joshua antony
Ranch Hand

Joined: Jun 05, 2006
Posts: 117
I think once you use ? extends SOMECLASS you are not supposed to add anything to the list.
For adding you can use ? super THE CLASS WHOSE OBJECT YOU WANT TO ADD

Please correct me if I am wrong.

Regards,
Joshua
Petrus Pelser
Ranch Hand

Joined: Feb 20, 2006
Posts: 132
You need to cast the list and the Rect object back to their original types for the operation to work.

Change:

to:

[ September 20, 2006: Message edited by: Petrus Pelser ]
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729
Hi guys,
Somebody could I tell me, Why in the marked line, cause a compile error "cannot find symbol" if l tends to be a List and it has the add
method?.



Let's take a look at your method add. The first parameter is a list, or rather a member of a family of lists. The family consists of List<Shape>, List<Rect>, List<ShadedRect>, and List<Circle>. But which one is the type of your list parameter? That we do not know.

Now, the List<E> class has a method add(int, E e), where E is the type of element that the list holds. But we do not know that type. We know that the list should contain a homogeneous (all the same type) set of elements. That is, they are all Rects, ShadedRects, or Circles, or Shapes. But we cannot insert a Rect because we do not know that the list contains only Rects, it could be a list of Circles. That is the reason why you get the compiler error.

(Of course, I could be writing complete rubbish, in which case let me know)
[ September 20, 2006: Message edited by: Barry Gaunt ]

Ask a Meaningful Question and HowToAskQuestionsOnJavaRanch
Getting someone to think and try something out is much more useful than just telling them the answer.
Meena R. Krishnan
Ranch Hand

Joined: Aug 13, 2006
Posts: 178
Check this out:

http://64.233.187.104/search?q=cache:FiiQnFUy0CsJ:java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf+generics&hl=en&gl=us&ct=clnk&cd=1

(under "wildcard" section)
Naveen Zed
Ranch Hand

Joined: Aug 11, 2006
Posts: 61
We have to remember one thing while using of collections using generics. By using the known type as the type parameter in the list you are telling to the compiler that you only provide that type of parameter while using.

In your program you are passing a �ShadedRect� parametered List to the �? extends shape� type. It is acceptable because the parameter �? extends shape� contains �ShadedRect�. But donot forget the contact made with the compiler that you only provide the objects of type ShadedRect, So compiler only creates the list of ShadedRect.

So the add block


Is perfectly alright,because there is an availability to the compiler to know that you only use of type �ShadedRect�.

Even though the block

public static void add(List<? extends Shape> l,int pos, Rect r){
l.add(pos, (ShadedRect)r);
}


Will not work, because you broken the contract with the compiler that you only use the type as �ShadedRect�. So compiler will see this �l.add(pos, (ShadedRect)r)� as another method that uses parameters as (pos,ShatedRect) and not as (pos, ShatedRect).

So what we are not any way able to corrupt the type that declared as the type parameter in the declaration of the predefined generic representation, because we know ,that they (the designers) believe that we use those types of elements only.
Anthony Karta
Ranch Hand

Joined: Aug 09, 2004
Posts: 342
Originally posted by joshua antony:
I think once you use ? extends SOMECLASS you are not supposed to add anything to the list.
For adding you can use ? super THE CLASS WHOSE OBJECT YOU WANT TO ADD

Please correct me if I am wrong.


Joshua gave important fundamental rule. It is discussed in K&B book, somehow I remember read that section (will check later).

thanks Joshua
Ankit Gaurav
Greenhorn

Joined: Jun 22, 2006
Posts: 10
Hi,
I think that there are 2 problems with the basic code.
1st problemThe first problem is with the basic declaration of the list.

The problem is that the list is of generic type ShadedRect and when passed to the add method the argument is List<? extends Shape>l
When "?" parameeter is used in accepting the List then we have a contract with the compiler that we wont add anything to the list in the add method.
Thats the first reason why the error is coming.

2nd problemIf we use the argument for List in add method as List<? super ShadedRect> then we will be be only able to add objects of type ShadedRect to the List as the List is typed for <ShadedRect>
perhaps the following code might help you in getting things better.I have typed the list for shape and I am adding a ShadedRect .Its possible because ShadedRect extends shape.
Pawanpreet Singh
Ranch Hand

Joined: Jun 12, 2005
Posts: 264

Yes Ankit is right.

We can not add anything with the instance of a List which is declared as

List<? extends ANYOBJECT>
OR
List<?> ....===> List<? extends Object>

Even if this declaration is method parameter, or assigning some object creation to a reference or returning some object in caller.

Keep in mind, whenever <? extends ...> or <?> comes, we can not apply add method on collection.

Also in case of Map, we can use put method
For ex:

class Animal{
}
class Cat extends Animal{
}

public class Test
{
public static void main(String... agrs)
{
Map<? extends Animal,String> map = new HashMap<Cat,String>();

map.put(new Cat(),""); // compiler error

List<? extends Animal> lst = new ArrayList<Cat>();
lst.add(new Cat()); // compiler error
}
}

If i am wrong, please correct me
Anthony Karta
Ranch Hand

Joined: Aug 09, 2004
Posts: 342
Originally posted by Pawan preet:
Yes Ankit is right.
Map<? extends Animal,String> map = new HashMap<Cat,String>();

map.put(new Cat(),""); // compiler error

List<? extends Animal> lst = new ArrayList<Cat>();
lst.add(new Cat()); // compiler error


Then what is the benefit by declaring a reference variable with wild card <?>?? if we cannot add anything to it.
Pawanpreet Singh
Ranch Hand

Joined: Jun 12, 2005
Posts: 264

The benefit that you can use it for iteration only but no updates are allowed.
Anthony Karta
Ranch Hand

Joined: Aug 09, 2004
Posts: 342
Originally posted by Pawan preet:
The benefit that you can use it for iteration only but no updates are allowed.


Hi Prawan,

I still don't get it.


If we even cannot add anything to the Map, there is nothing to iterate.
Keith Lynn
Ranch Hand

Joined: Feb 07, 2005
Posts: 2367
You could use that type as a parameter to a method, and then send a Map which matches it.

Consider this example.



Of course in each instance of the method, you wouldn't be able to call methods defined only in the subclass on the keys in the Map since there is no way to infer the type.
Anthony Karta
Ranch Hand

Joined: Aug 09, 2004
Posts: 342
Originally posted by Keith Lynn:

Of course in each instance of the method, you wouldn't be able to call methods defined only in the subclass on the keys in the Map since there is no way to infer the type.


Thanks keith that helps re-affirm my understanding.

But I don't get your last sentence. we can call method on Cat class. could you elaborate?

thanks
Keith Lynn
Ranch Hand

Joined: Feb 07, 2005
Posts: 2367
What I mean is that in the method, the type of the key is anything that extends Animal. That could be a Dog, Cat, etc. The only methods guaranteed to be available are the methods defined in Animal that are allowed to be inherited by its subclasses. But if you have a method that is only defined in the Dog class, you wouldn't be able to call it directly because the only thing known about the type of the parameter is that it extends Animal.

It's just like in the equals(Object) method. Since the parameter's type gets promoted to Object, you can't call methods defined in the parameter's class and not defined in Object unless you cast.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Generics