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 / July 2006

Tip: Looking for answers? Try searching our database.

Generic blues ...

Thread view: 
verec - 05 Jul 2006 02:33 GMT
import java.util.List;

public class GenericGotchas {

   void foo(Class c) {
       System.out.println(c.getSimpleName()) ;
   }

   void doesCompile() {
       foo(List.class) ;
   }

   void doesNotCompile() {
       foo(List<String>.class) ;       // compile error (1)
   }

   static class Test<E> {
       Test(E e) { }

       static <E> Test<E>              // fine (2)
       newTest(E e) {
           return new Test<E>(e) ;
       }

       static <E> Test<E>              // compile error (3)
       singletonDoesNotCompile ;
   }
}

Case 1 is extremely unfortunate. I want to maintain
a map of (some) classes/interfaces to (some of) their
instances. This works UNLESS any of the class is a
parameterized one, in which case I couldn'y find a
way to name it.

For case 2, even though you can create "static generic"
factories (2), you CANNOT cache (3) the to be returned result.

I'm certain the powers that be have tons of explanations
involving type erasure, "reification" and many other
beasts, but the end result is that, in practice, this sucks!

This far, short of dropping the generic stuff altogether,
I haven't found any workaround for either of those two cases.

Any idea?

Many thanks
--
JFB
Hendrik Maryns - 05 Jul 2006 09:21 GMT
verec schreef:
> import java.util.List;
>
[quoted text clipped - 30 lines]
> parameterized one, in which case I couldn'y find a
> way to name it.

That will not work anyway, because the class object for a List<String>
and a List<Object> and even a List or a List<?> are all the same.  There
is only one, and it is referred to with List.class.  So either you have
to change your design, or have List.class map to a mixture of lists with
different type parameters.

> For case 2, even though you can create "static generic"
> factories (2), you CANNOT cache (3) the to be returned result.

Because only methods can have a generic parameter.  I find that most
unfortunate too, it would be nice in singleton instances.  The
‘solution’ is to have a *private*

private static Test singleton;

and a method

static <E> Test<E> getInstance() { return singleton; }

with the appropriate access restrictions.  Unfortunately, this will give
you a warning, unless you use @SuppressWarnings("unchecked").

> I'm certain the powers that be have tons of explanations
> involving type erasure, "reification" and many other
> beasts, but the end result is that, in practice, this sucks!

2x true.

> This far, short of dropping the generic stuff altogether,
> I haven't found any workaround for either of those two cases.
>
> Any idea?

2c above.

HTH, H.
- --
Hendrik Maryns

==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
Kai Schwebke - 05 Jul 2006 16:45 GMT
Hendrik Maryns schrieb:
> private static Test singleton;
>
> and a method
>
> static <E> Test<E> getInstance() { return singleton; }

I think this won't work -- you'll need at least a type token for a
generic function:

static <E> Test<E> getInstance(Class<E> type) { return singleton; }

Where's the point in using generics in this case -- you cast the
singelton to any type, so you gain no type-safety after all?

Regards
Kai
Oliver Wong - 05 Jul 2006 17:00 GMT
> Hendrik Maryns schrieb:
>> private static Test singleton;
[quoted text clipped - 10 lines]
> Where's the point in using generics in this case -- you cast the singelton
> to any type, so you gain no type-safety after all?

The following will compile:

<code>
public class Test<E>{
 private static Test singleton;

 public <E> Test<E> getInstance() {
   return singleton;
 }
}
</code>

but it doesn't do what the OP wants, I think. If you put a Test<Foo> into
the private singleton field, and then do:

Test<Bar> tb = Test.getInstance();

then the singleton instance will be placed into tb, and you'll get a
ClassCastException at some random point in the future when you try to get a
Bar out of tb, when actually it contains a Foo.

If you want a singleton for every possible generic type that could be passed
in, you'd need something like:

<code>
public class Test<E>{
 private static Map<Class, Test> singletonMap; /*initialize this somehow*/

 public <F> Test<F> getInstance(Class<F> clazz) {
   Test<F> returnValue = singletonMap.get(clazz);
   if (returnValue == null) {
     returnValue = new Test<F>();
     singletonMap.put(clazz, returnValue);
   }
   return returnValue;
 }
}
</code>

(the type argument of the static method was changed for clarity)

   - Oliver
Hendrik Maryns - 05 Jul 2006 18:21 GMT
Oliver Wong schreef:
>> Hendrik Maryns schrieb:
>>> private static Test singleton;
[quoted text clipped - 27 lines]
>
> Test<Bar> tb = Test.getInstance();

> then the singleton instance will be placed into tb, and you'll get a
> ClassCastException at some random point in the future when you try to
> get a Bar out of tb, when actually it contains a Foo.

You’re right, I forgot the initialisation, I meant to do this:

public class Test<E>{

@SuppressWarnings("unchecked")
private static Test singleton = new Test;

@SuppressWarnings("unchecked")
public <E> Test<E> getInstance() {
  return (Test<E>) singleton;
}
}

This is how Sun handles empty sets in java.util.Collections.

> If you want a singleton for every possible generic type that could be
> passed in, you'd need something like:
[quoted text clipped - 13 lines]
> }
> </code>

Though I agree this is much cleaner.

H.
- --
Hendrik Maryns

==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
Hendrik Maryns - 05 Jul 2006 20:27 GMT
Hendrik Maryns schreef:
> Oliver Wong schreef:
>>>> Hendrik Maryns schrieb:
[quoted text clipped - 45 lines]
>
> This is how Sun handles empty sets in java.util.Collections.

I have to add: watch out, this will only work if there is not yet any
object of the given type parameter contained in the singleton.
Otherwise you’ll get into trouble.  So it works with empty collections,
or with generic classes that are no containers.

H.
- --
Hendrik Maryns

==================
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



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