• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Help with Java Generics...

 
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was hoping you guys might be able to give me a little help with Java
Generics. I'm trying to track down a null pointer exception in my
pluggable rendering code, and I think it may result from improper use
of Generics.

In one of my classes I store a HashMap. The keys for this
HashMap are Strings. The values stored in the HashMap
are the references to any class which implements an interface. (I'll call the interface SomeInterface for this example.) I want the HashMap to be able to store any implementation of the SomeInterface.

Here is my attempt at defining the HashMap using Java Generics:



Eclipse is giving me an error on this statement. It says that it
"Can't instantiate the type HashMap<String,? extends
SomeInterface>".

I'm guessing this is becuase I'm trying to use an interface and not a
class as the upper bound of my wild card in the generics declaration.
Is there a way around this, other than defining a default
class that must be extended by all other
implementations of SomeInterface.

I'm really surprised that you can't use interfaces in this type of
statement. Unless of course, I've got another mistake staring me in
the face.

Thanks in advance for the help.

Landon
 
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
try:

 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The wildcard in
private HashMap<String, ? extends SomeInterface> indicates a parameterized HashMap where the second parameter is some specific implementation (or subclass if SomeInterface were a concrete class) of SomeInterface. For instance if you have an implementing class:


and a method signature:



then a HashMap<String, SomeClass> would qualify as a parameter to this method. However you wouldn't be ablt to add anything to the map because the specific type of the class that implements SomeInterface isn't known at compile time.

Also since parametrized types arent covariant, a HashMap<String, SomeClass> could not be passed to a method that expected a HashMap<String, SomeInterface>.

I'm not sure if that was helpful or more confusing...
 
Landon Blake
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the responses Garett.

Another Java programmer suggested that I try this:

private HashMap<String, ? extends SomeInterface> myHashMap = new HashMap<String, SomeInterface>();

This made the error disappear in Eclipse, although I don't know if the code will work properly when compiled. I'll let you find out.

What I'm trying to do is have a HashMap that can store any class implementing SomeInterface.I also need to be able to add instances of classes implementing SomeInterface to. I think I can accomplish this with the above definition of the HashMap and a genric method that adds elements to the HashMap. I'll report back on how this works.

Thanks again for the help.

Landon
 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Then what you really want is a HashMap<String, SomeInterface>, the wildcards serve no purpose here.
 
Landon Blake
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Garrett,

I can see now that you were correct. I didn't need to use wildcards because I was dealing with an interface.

I think i'd need to use the wildcard if I wanted to allow subclasses of a class, instead of implementations of an interface.

Thanks,

Landon
[ May 17, 2007: Message edited by: Landon Blake ]
 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I think i'd need to use the wildcard if I wanted to allow subclasses of a class, instead of implementations of an interface.



No, a reference of type HashMap<String, Object> will compile without warning and allow you to store any type of Object as a value in the map. For the most part, I usually see wildcards in method parameters. Since generic types aren't covariant you cant do this:

ArrayList<Object> objectList = new ArrayList<String>();//NOT ALLOWED

An ArrayList<String> is not a subtype of ArrayList<Object>. Therefore, an ArrayList<String> is not a valid argument for a method who's signature is:

But in most cases what is really meant by that line of code is "This method will accept a parameterized ArrayList of any type and we will treat the elements of that ArrayList as Objects". With generics in Java one way to express that is:



[ May 17, 2007: Message edited by: Garrett Rowe ]

[ May 17, 2007: Message edited by: Garrett Rowe ]
[ May 17, 2007: Message edited by: Garrett Rowe ]
 
Is that a spider in your hair? Here, threaten it with this tiny ad:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic