1

I have a class A like this:

public class A<T extends Number>
{
 ....
}

In another class I have this method:

public Hashtable<String, A> createAHashtable()
    {
        Hashtable<String, A> hTable = new Hashtable<String, A>();

        return hTable;
    }

There is a warning for parameter A because it is generic class. So should I do this:

public Hashtable<String, A <?>> createAHashtable()
        {
            Hashtable<String, A<?>> hTable = new Hashtable<String, A<?>>();

            return hTable;
        }

or do this:

public Hashtable<String, A <? extends Number>> createAHashtable()
{
Hashtable<String, A<? extends Number> hTable = new Hashtable<String, A<? extends Number>();

return hTable;
}

or ....???

EDIT:

Tried this (as suggested by Dilum)

public <T extends Number> Hashtable<String, A<T>> createAHashtable()
    {
        Hashtable<String, A<T>> hTable = 
                new Hashtable<String, A<T>>();
        A<Float> constraint = new A<Float>();
        hTable.put("test", constraint);

        return hTable;
    }

But it is invalid to "put" my Float A.

Maybe the wildcard is the way to go.

EDIT 2:

Based on Dilum's suggestion, the following code (cast to A when put a Float A into the Hashtable) has no error but warning it is unsafe cast. Why we need the cast?

public <T extends Number> Hashtable<String, A<T>> createAHashtable()
        {
            Hashtable<String, A<T>> hTable = 
                    new Hashtable<String, A<T>>();
            A<Float> constraint = new A<Float>();
            hTable.put("test", (A<T>)constraint);

            return hTable;
        }
4
  • As far as I can tell they both should be fine. :-) Commented Sep 9, 2011 at 15:55
  • Except that nowhere is a generic argument ever properly supplied to A. He's just got wildcards everywhere. Commented Sep 9, 2011 at 16:03
  • Edit2 is not good code. Here's why: there are three possible scenarios. Case 1 - all callers to createAHashtable are capable of handling values of A<T> AND A<Float>. This is difficult to model in Java without an additional indirection. Case 2 -- all callers are capable of handling any A<Number>. If so, the API should return Hashtable<String,A<Number>>. Case 3 -- A caller expects something other than A<Float>, and dies with a class cast exception at runtime. Commented Sep 9, 2011 at 17:49
  • So, generic is not the same as inheritance. we cannot mix Float, Long and Integer together and put them into one collection container. Commented Sep 9, 2011 at 18:25

2 Answers 2

5

Try this:

public <T extends Number> Hashtable<String, A<T>> createAHashtable() {
  return new Hashtable<String, A<T>>();
}

Say you did want to pre-fill with a key-value pair, try:

public <T extends Number> Hashtable<String, A<T>> createAHashtableWithEntry(String key, T value) {
  Hashtable<String, A<T>> ht = return new Hashtable<String, A<T>>();
  ht.put(key, new A<T>(value));
  return ht;
}
Sign up to request clarification or add additional context in comments.

4 Comments

An A<T> is not always an A<Float>. So you cannot add it.
why we need the cast? that means <? extends Number> may be a better solution?
What do you mean cast? I didn't write any casts. I have a suspicion what you are looking for is just Hashtable<String, A<Number>)
Please look at my edit 2, the A class is a T extends Number generic class, so I plan to add Float A object, Integer A object and Long A object into that Hashtable within that createAHashtable() method.
0

Related to edit 2:

Here's a concrete example of why the case is unsafe. On my IDE I actually don't even get a warning that the cast is unsafe.

import java.util.ArrayList;
import java.util.List;

public class Genericss {

   static <T extends Number> List<A<T>> get2() {
      List<A<T>> list = new ArrayList<A<T>>();
      A<Float> f = new A<Float>(3.0f);
      list.add((A<T>) f); // Compiles... not even a warning on my IDE
      return list;
   }

   public static void main(String[] args) {
      List<A<Integer>> l = Genericss.<Integer>get2();
      Integer i = l.get(0).get(); // runtime error

      A<Float> f = new A<Float>(3f);
      //i = (A<Integer>) f;  // won't compile
   }

   public static class A<T> {
      T t;

      public A(T t) {
         this.t = t;
      }

      public T get() {
         return t;
      }
   }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.