Generic blues ...

V

verec

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
 
H

Hendrik Maryns

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

verec schreef:
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.

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFEq3abe+7xMGD3itQRAlhaAJ43lmvIas/vFaqfkrpUuK7xkFfhowCffyQc
VbgF2avc19PBSPgQpaXSPjo=
=qZ8m
-----END PGP SIGNATURE-----
 
K

Kai Schwebke

Hendrik said:
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
 
O

Oliver Wong

Kai Schwebke said:
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?

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
 
H

Hendrik Maryns

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

Oliver Wong schreef:
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.


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:

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

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFEq/Upe+7xMGD3itQRAqXxAJoDILxU0JwDAdytzBp9WlV1SLn5fACbBp4B
BlW+zk7+7WrWYqfGD1FbXRo=
=I/IQ
-----END PGP SIGNATURE-----
 
H

Hendrik Maryns

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

Hendrik Maryns schreef:
Oliver Wong schreef:


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

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFErBKye+7xMGD3itQRArKvAJ9ZS9zzwbyCg94eSbvsFXFML8FKXACggpRq
G4e2iedE8bfHC0/rfIalGPA=
=ZV/7
-----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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top