• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Liutauras Vilda
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Scott Selikoff
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
  • Frits Walraven
Bartenders:
  • Stephan van Hulst
  • Carey Brown

Generics

 
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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() );
}
}
 
Ranch Hand
Posts: 132
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Ranch Hand
Posts: 342
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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 ]
 
Ranch Hand
Posts: 117
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 132
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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 ]
 
Ranch Hand
Posts: 178
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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)
 
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 342
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 264
Eclipse IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 342
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 264
Eclipse IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The benefit that you can use it for iteration only but no updates are allowed.
 
Anthony Karta
Ranch Hand
Posts: 342
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Ranch Hand
Posts: 2412
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 342
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 2412
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
What are you doing in my house? Get 'em tiny ad!
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic