enum/generics typesafe getter for generic types

V

visionset

I thought it might be possible to have just one getter for a variety of
Object return types

If I pass in an enum which knows the Class type of the value it keys, then
perhaps I can use generics to fix the return type.

This does not compile but gives a better idea of the kind of thing I mean.
Is it possible?



public class Preference {


public enum Key<T> {


A_KEY (String.class),

B_KEY (String.class),

C_KEY (Integer.class),

D_KEY (Integer.class);


Class<T> clazz;


Key(Class<T> c) {

clazz = c;

}


}; // end enum


public T get(Key<T> key) {


// stuff

return myT;

}

}



TIA
 
P

Piotr Kobzda

visionset said:
I thought it might be possible to have just one getter for a variety of
Object return types

Yes, it's possible.
If I pass in an enum which knows the Class type of the value it keys, then
perhaps I can use generics to fix the return type.

You can, but not using enum -- enums can't be generic.
Consider using normal class for your purposes:

public class Key<T> {
Class<T> type;
Key(Class<T> type) {
this.type = type;
}

static <T> Key<T> newKey(Class<T> type) {
return new Key<T>(type);
}

public static final Key<String> A_KEY = newKey(String.class);
public static final Key<String> B_KEY = newKey(String.class);
public static final Key<Integer> C_KEY = newKey(Integer.class);
public static final Key<Integer> D_KEY = newKey(Integer.class);

}


piotr
 
V

visionset

Piotr Kobzda said:
Yes, it's possible.


You can, but not using enum -- enums can't be generic.
Consider using normal class for your purposes:

public class Key<T> {
Class<T> type;
Key(Class<T> type) {
this.type = type;
}

static <T> Key<T> newKey(Class<T> type) {
return new Key<T>(type);
}

public static final Key<String> A_KEY = newKey(String.class);
public static final Key<String> B_KEY = newKey(String.class);
public static final Key<Integer> C_KEY = newKey(Integer.class);
public static final Key<Integer> D_KEY = newKey(Integer.class);

}

Yes, but how do I now use this class to form a generic getter outside of Key
class?
For this kind of call:

String s = foo.get(Key.A_KEY);

because I'm not instantiating Key, I can't pass in a <Type> so I can't form
a generic method.
 
P

Piotr Kobzda

visionset said:
Yes, but how do I now use this class to form a generic getter outside of Key
class?
For this kind of call:

String s = foo.get(Key.A_KEY);

because I'm not instantiating Key, I can't pass in a <Type> so I can't form
a generic method.

You can, declare it e.g. like that:

public <T> T get(Key<T> key) { ...


piotr
 
P

Piotr Kobzda

Piotr said:
You can, declare it e.g. like that:

public <T> T get(Key<T> key) { ...

Well, honestly, I'm not fully sure /you can/. It depends mostly on what
you are trying to achieve. My understanding of your goal is expressed
in attached example (SSCCE). If that not match your expectations,
explain them deeper.


piotr

--
import java.util.HashMap;
import java.util.Map;

public class MultivalueProperty {

public static class Key<T> {
Class<T> type;
Key(Class<T> type) {
this.type = type;
}

static <T> Key<T> newKey(Class<T> type) {
return new Key<T>(type);
}

public static final Key<String> A_KEY = newKey(String.class);
public static final Key<String> B_KEY = newKey(String.class);
public static final Key<Integer> C_KEY = newKey(Integer.class);
public static final Key<Integer> D_KEY = newKey(Integer.class);

// possibly better hashCode() is needed here...

}

private Map<Key<?>, Object> values = new HashMap<Key<?>, Object>();

public <T> T get(Key<T> key) {
return key.type.cast(values.get(key));
}

public <T> void put(Key<T> key, T value) {
values.put(key, value);
}

// sample usage...
public static void main(String[] args) {
MultivalueProperty foo = new MultivalueProperty();

foo.put(Key.A_KEY, "A value");
foo.put(Key.C_KEY, 0);


String a = foo.get(Key.A_KEY);
String b = foo.get(Key.B_KEY);
Integer c = foo.get(Key.C_KEY);
Integer d = foo.get(Key.D_KEY);

System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
 
V

visionset

Piotr Kobzda said:
You can, declare it e.g. like that:

public <T> T get(Key<T> key) { ...

But I think there is a T resolution issue outside the Key class.

public class Preference {


public static final Key<String> A_KEY = new Key<String>();

public static final Key<String> B_KEY = new Key<String>();

public static final Key<Integer> C_KEY = new Key<Integer>();

public static final Key<Integer> D_KEY = new Key<Integer>();


public static class Key<T> {

// how to get T outside of Key class?

}


private Map<Key, T> map; // how to define this?


public <T> T get(Key<T> key) {

// what goes here

return map.get(T);

}


public void testGet() {

String s = get(A_KEY);

}
 
V

visionset

Piotr Kobzda said:
Well, honestly, I'm not fully sure /you can/. It depends mostly on what
you are trying to achieve. My understanding of your goal is expressed in
attached example (SSCCE). If that not match your expectations, explain
them deeper.

Thank you Piotr that is perfect!!
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

visionset schreef:
But I think there is a T resolution issue outside the Key class.

public class Preference {


public static final Key<String> A_KEY = new Key<String>();

public static final Key<String> B_KEY = new Key<String>();

public static final Key<Integer> C_KEY = new Key<Integer>();

public static final Key<Integer> D_KEY = new Key<Integer>();


public static class Key<T> {

// how to get T outside of Key class?

}


private Map<Key, T> map; // how to define this?

You will want to give a generic parameter to Key as well. If you have
nothing better, use Object or even <?>. Using T there will only work if
T is defined in Preference, which it isn’t. You will need Object and
casting, as in Piotr’s example.
public <T> T get(Key<T> key) {

// what goes here

Whatever you want.
return map.get(T);

This is impossible. You cannot use types as parameters. Think of it as
get.(Integer). That doesn’t make sense either. The closest to it is
get(Integer.class), since Integer.class is an object of type
}


public void testGet() {

String s = get(A_KEY);

}

HTH, H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iD8DBQFGENXve+7xMGD3itQRAuNaAJ4orejOfE5rKYFDsbn3H+7w/abjXQCeLTXY
lJOkgv5fhBmiDwDaGZmg3JY=
=hMxf
-----END PGP SIGNATURE-----
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top