Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / April 2007

Tip: Looking for answers? Try searching our database.

enum/generics typesafe getter for generic types

Thread view: 
visionset - 31 Mar 2007 23:47 GMT
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

Signature

Mike W

Piotr Kobzda - 01 Apr 2007 01:34 GMT
> 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
visionset - 01 Apr 2007 01:46 GMT
>> I thought it might be possible to have just one getter for a variety of
>> Object return types
[quoted text clipped - 23 lines]
>
>     }

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.

Signature

Mike W

Piotr Kobzda - 01 Apr 2007 01:55 GMT
> Yes, but how do I now use this class to form a generic getter outside of Key
> class?
[quoted text clipped - 4 lines]
> 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
Piotr Kobzda - 01 Apr 2007 10:54 GMT
>> Yes, but how do I now use this class to form a generic getter outside
>> of Key class?
[quoted text clipped - 8 lines]
>
>     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

Signature

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);
    }
}

visionset - 01 Apr 2007 11:00 GMT
>>> Yes, but how do I now use this class to form a generic getter outside of
>>> Key class?
[quoted text clipped - 13 lines]
> attached example (SSCCE).  If that not match your expectations, explain
> them deeper.

Thank you Piotr that is perfect!!

Signature

Mike W

visionset - 01 Apr 2007 10:54 GMT
>> Yes, but how do I now use this class to form a generic getter outside of
>> Key class?
[quoted text clipped - 8 lines]
>
>     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);

}

Signature

Mike W

Hendrik Maryns - 02 Apr 2007 10:52 GMT
visionset schreef:

>>> Yes, but how do I now use this class to form a generic getter outside of
>>> Key class?
[quoted text clipped - 23 lines]
>
>     // how to get T outside of Key class?

You can’t.  But generally, you will have instantiated a Key<Something>
yourself, so you will know what Something is.

> }
>
> 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
Class<Integer>.  But get(T.class) will not work, since T cannot be
resolved at compile time.

> }
>
[quoted text clipped - 3 lines]
>
> }

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


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.