• Post Reply Bookmark Topic Watch Topic
  • New Topic

Subclassing Hashtable with generics?  RSS feed

 
Paula Davis
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am belatedly moving from Java 1.4 to 1.5, and so far am ok with using generics in everyday ways, e.g.
And yes, I have looked at Gilad Bracha's "Generics in the Java Programming Language", which seems to be the link everyone offers for everyone's questions about generics in all the forums. (OK, maybe overstatement, but it is pretty ubiquitous.) If the answer to this question is in there, it must have been in wording that I didn't follow. (Please speak slowly... )

But now I want to subclass Hashtable to add some convenience methods for the specific purposes of my little app. This is my first foray into the more heavy-duty generics stuff. Right off the bat, in my constructor I hit a warning about belonging to the raw type Hashtable. Is there simply some syntax I need to fix, or is this whole attempt a golden example of rookie mistakes in generics? (I know there is tricky stuff about inheritance when generics are involved, but don't have a clear grasp of all the particulars yet.) Code sample below.

Thanks in advance.

 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aside from Gilad Bracha's tutorial, another good resource is Angelika Langer's Java Generics FAQ. For future reference.

The problem is this line, actually:

You declare T and S, as type parameters of EasyTable, but you haven't told the compiler that those same parameters should be applied to the Hashtable you're inheriting from. As far as the compiler know, that Hashtable is a raw type, and it knows nothing about its type parameters. Instead, try

(I dropped the "extends Object" because that doesn't really tell us, or the compiler, anything useful.)

Some other quick thoughts:

Most of us recommend using HashMap rather than Hashtable nowadays. The legacy collection classes (Vector, Hashtable, Enumeration) tend to just confuse matters without being very useful for anything. (Insert rant about how the synchronization in Vector and Hashtable is at the wrong level anyway and tends to be dangerously misleading.)

I would also recommend that you consider using composition rather than inheritance here - because inheritance tends to have complications that are harder to spot. Try something like this:

This may involve more typing, but the methods are generally pretty simple. This tends to give you more control over how things work.

You may also decide you don't really need or want to implement the full Map interface, and that's fine too. If you inherit, you get the entire Hashtable or HashMap class whether you want it or not, and then need to override the parts that don't behave the way you want. With composition, you can just omit the methods you don't want or need.

Last, it's a bit risky to call any overrideable method or the current class from within your constructor. You might want to make put() final if you do that. The reasons are a bit complex; I recommend Effective Java for a good discussion of this and other coding issues.
 
Paula Davis
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, Jim. I will try out your HashMap suggestion. I appreciate the heads-up about Vector, Hashtable, and Enumeration, and I will take a look at the book you recommended.

Although it's now beside the point (since I will use the other approach you recommended), I thought I'd mention that when I used Eclipse gives me the following compile error (I swear I am not making this up): "The method put(T, S) in the type Hashtable<T,S> is not applicable for the arguments (T, S)". (When I compile the same thing from the command line, I get "cannot find symbol" for the call to put.)

Anyway, I'm off to implement the Map interface

Cheers,
Paula
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, there's also a problem with the constructor you were using:

This is essentially declaring new type parameters T and S, unrelated to the T and S which were declared in the class declaration. I'm not sure why the rules allow this at all, because it just creates confustion later - as when you try to use method put(T1, S1) with arguments of types T2, S2. It would be much cleaner if the compiler just complained about reusing the same type parameter name twice in the same scope. Anyway, to fix it, just remove the < > section from the constructor declaration:

Now T and S refer to the same T and S that was declared in the class declaration.
 
Paula Davis
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the clarification!
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!