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 / June 2007

Tip: Looking for answers? Try searching our database.

Generics pains

Thread view: 
Joshua Cranmer - 26 Jun 2007 03:07 GMT
I am trying to create an options class that manages options for a
project. In this class, the options are internally stored as Strings that
can be cast to (depending on circumstances) integers, booleans, or even
enums. However, I am having trouble getting the code to compile:

public final class Options {
   private Options() {}
   private static HashMap<String, String> opts = new HashMap<String,
String>();
   private static HashMap<String, Class<?>> types = new HashMap<String,
Class<?>>();
   public static String getOption(String name) {
       return opts.get(name);
   }

   public static <T extends Enum<T>> T getAsEnum(String name) {
       Class<?> c = types.get(name);
       if (!c.isEnum())
           throw new RuntimeException("Option "+name+" is not an enum!");
       Class<T> ec = c.asSubclass(Enum.class);
       return Enum.valueOf(ec, getOption(name));
   }
}

The exact error:
C:\Documents and Settings\Josh\Desktop\Programming\Java\Decompiler_new
\util\Options.java:43: incompatible types
found   : java.lang.Class<capture of ? extends java.lang.Enum>
required: java.lang.Class<T>
              Class<T> ec = c.asSubclass(Enum.class);
                                         ^
If it helps, this is one of the intended usages:

// Options.opts has pair "log","ERROR"
// and Options.types has pair "log",LogLevel.class
// via my options scheme
@Option("log",LogLevel.class,"ERROR")
public class Logger {

   // various methods

   private static void log(String message, LogLevel severity) {
       if (severity.ordinal() < Options.getAsEnum("log").ordinal())
           return;
       // log the message somehow
   }

   private enum LogLevel {
       ERROR, WARNING, VERBOSE, DEBUG;
   }
}

P.S. I know my error-handling is as of right now unacceptable; I am going
to start fixing that once I implement my logger, for which I need my
getAsEnum function to work.
Tom Hawtin - 26 Jun 2007 09:02 GMT
>     public static <T extends Enum<T>> T getAsEnum(String name) {
>         Class<?> c = types.get(name);
>         if (!c.isEnum())
>             throw new RuntimeException("Option "+name+" is not an enum!");
>         Class<T> ec = c.asSubclass(Enum.class);

ec could be of type Class<Enum>.

>         return Enum.valueOf(ec, getOption(name));

You could simply cast it with (T).

The general way of dealing with heterogeneous collections is to pass a
class of the type you want:

    public static <T> T get(Class<T> type, String name) {
        return type.cast(types.get(name));
    }
    public static Enum<?> getEnum(String name) {
        return get(Enum.class, name);
    }

Tom Hawtin
Ingo R. Homann - 26 Jun 2007 09:14 GMT
Hi,

> I am trying to create an options class that manages options for a
> project. In this class, the options are internally stored as Strings that
> can be cast to (depending on circumstances) integers, booleans, or even
> enums. However, I am having trouble getting the code to compile:

My suggestiuon (although I am not really sure about it ;-) is this:

class Options
{

  private Options()
  {
  }

  private static HashMap<String, String> opts = new HashMap<String,
String>();

  private static HashMap<String, Class<?>> types = new HashMap<String,
Class<?>>();

  public static String getOption(String name)
  {
    return opts.get(name);
  }

  public static <T extends Enum<T>> T getAsEnum(String name)
  {
    Class<?> c = types.get(name);
    if (!c.isEnum())
      throw new RuntimeException("Option " + name + " is not an enum!");
    @SuppressWarnings("unchecked")
    Class<T> ec = (Class<T>) c.asSubclass(Enum.class);
    return Enum.valueOf(ec, getOption(name));
  }
}

Hth,
Ingo
Twisted - 26 Jun 2007 09:17 GMT
> The exact error:
> C:\Documents and Settings\Josh\Desktop\Programming\Java\Decompiler_new
> \util\Options.java:43: incompatible types
> found   : java.lang.Class<capture of ? extends java.lang.Enum>
> required: java.lang.Class<T>
>                Class<T> ec = c.asSubclass(Enum.class);

Try Class<T> ec = (Class<T>)c.asSubclass(Enum.class);

and throw an @SuppressWarnings("unchecked") right before the method
declaration.

If your logic is right, the return value should always be a Class<T>;
if your logic is wrong, well, then things won't work, but they
wouldn't have been able to anyway.
Joshua Cranmer - 26 Jun 2007 23:02 GMT
> Try Class<T> ec = (Class<T>)c.asSubclass(Enum.class);
>
[quoted text clipped - 4 lines]
> your logic is wrong, well, then things won't work, but they wouldn't
> have been able to anyway.

My original intent of the question was how to get Enum.class to return a
type of Class<Enum<?>> and not Class<Enum>, which (after external
verification) cannot be done.

However, looking at Sun's bug database, it appears that the return of the
raw type for class literals was a mistake, and they seem to be in the
process of rectifying it: http://bugs.sun.com/bugdatabase/view_bug.do?
bug_id=6209029.

I was afraid that I would be forced to use the @SuppressWarnings, but it
seems I have no choice...

Thanks for your help anyways!
Owen Jacobson - 26 Jun 2007 23:17 GMT
> I am trying to create an options class that manages options for a
> project. In this class, the options are internally stored as Strings that
[quoted text clipped - 27 lines]
> required: java.lang.Class<T>
>                Class<T> ec = c.asSubclass(Enum.class);

...

> P.S. I know my error-handling is as of right now unacceptable; I am going
> to start fixing that once I implement my logger, for which I need my
> getAsEnum function to work.

I realize you're writing a completely general Options class, but the
only actual use you've shown so far is logging...  Is there a reason
not to use log4j, which has enough logging levels and configurability
to cover what it looks like you're trying to do?

Owen


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



©2008 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.