0

I've the following class:

public class IntegerKey extends Number implements Comparable<IntegerKey> {

    private Integer m_key;

    public IntegerKey(Integer key) {
        m_key = key;
    }

    public IntegerKey(int key) {
        m_key = key;
    }

}

I would like to use this class as Follow:

assume I have the following generics:

Map<IntegerKey, MyCache> map = new HashMap<IntegerKey, MyCache>();

map.put(5, new MyCache());

This doesn't compile, why?? I don't want to do:

map.put(new IntegerKey(5), new MyCache());

Thank you.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Shvalb
  • 1,835
  • 2
  • 30
  • 60

4 Answers4

5

This doesn't compile, why?

Because there's no implicit conversion from int to IntegerKey. You can't create user-defined implicit conversions in Java. You're stuck with the ones defined by the language.

You've either got to explicitly get hold of a IntegerKey somehow, or you've got to change the type of your map to Map<Integer, MyCache>.

Jesper
  • 202,709
  • 46
  • 318
  • 350
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

This doesn't compile, why??

Only primitive types are auto-boxed to their wrappers. Not other combinations are allowed in Java.

I don't want to do:

map.put(new KeyInteger(5), new MyCache());

In that case don't use a KeyInteger, just use an Integer.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
2

Autoboxing only works for the primitives types and their respective counter parts in java.lang. In your example you could try dropping IntegerKey altogether and simply use Integer.

Bombe
  • 81,643
  • 20
  • 123
  • 127
  • The example I gave is only partial. this IntegerKey class holds more data-members and logic inside. – Shvalb Oct 04 '12 at 13:14
0

Seeing the comment concerning the special functionality of IntegerKey, it seems logical to wrap the functionality you are asking for in a new class (MHashMap in the following examples):

import java.util.HashMap;

class IntegerKey extends Number implements Comparable<IntegerKey> {
  private Integer m_key;
  public IntegerKey(Integer key) {
    m_key = key;
  }

  public IntegerKey(int key) {
    m_key = key;
  }
  //...Functionality
  //...required methods to include to actually test
  @Override
  public int compareTo (IntegerKey arg0) {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public double doubleValue () {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public float floatValue () {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public int intValue () {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public long longValue () {
    // TODO Auto-generated method stub
    return 0;
  }

}
class MyCache {}
class MHashMap extends HashMap<IntegerKey, MyCache> {
  public void put (int key, MyCache value) {
    super.put(new IntegerKey(key), value);
  }
  public void put (Integer key, MyCache value) {
    super.put(new IntegerKey(key), value);
  }
  //...Useful to include other wrappings
  public MyCache get (int key) {
    return super.get(new IntegerKey(key));
  }
  public MyCache get (Integer key) {
    return super.get(new IntegerKey(key));
  }
}
public class AutoboxFix {
  public static void main (String[] args) {
    //needed to explicitly declare map as MHashMap for "override" to work
    MHashMap map = new MHashMap();
    //compiles
    map.put(5, new MyCache());
    //... get probably works with your extended functionality
  }
}

This should provide the functionality your looking for. The get method will depend on the methods in Comparable. There may be more methods that you want to reimplement to auto cast from int or Integer to IntegerKey, but you should be able to use the rest of the HashMap functionality normally. It is necessary to declare map as MHashMap type, because using Map won't compile. It would be sensible to separate classes into their own files and make them public.

This approach won't work if it's absolutely necessary to declare map as Map<IntegerKey, MyCache>. You could make a static method where ever your using map and such to do the casting for you:

public class AClass {
  public static void myPutMethod (Map<Integer, MyCache> map, int key,
       MyCache value) {
    map.put(new IntegerKey(key), value);
  }
}

Use:

myPutMethod(map, 5, new MyCache());

Then you can define more methods for Integer and Map.get.

DoubleMx2
  • 375
  • 1
  • 9