Static fields in specialized classes

Ben Lewis benlewisj at
Wed Oct 15 08:30:36 UTC 2014

 I think having Foo.class and Foo<int>.class be different is a mistake.

class Person{}

class Employee<any T> extends Bar{
     //lots of other stuff irrelevant to T
     T getId(){ … }

Person p1=new Employee<Object>();
Person p2=new Employee<int>();

As I understand it

p1 instanceof Employee;//true
p2 instanceof Employee;//false

How to determine b2 comes from ‘source class’ Employee?

This will cause bugs in situations where the programmer expects how the
class hierarchy acts now rather than changing it to where specialisation
having a different class. This would also mean migrating <T> to <any T>
will cause backward compatibility issues.

For example

if(p instanceof Employee){
   //do something
   //do something else

if written before specialisations It would do as expected but after and if
p=new Employee<int>() it would execute the else block not as expected when
the code is written.

On Wed, Oct 15, 2014 at 12:59 PM, Brian Goetz <brian.goetz at>

> My gut feeling is that this is undesirable and should be disallowed,
>> and that perhaps we shouldn't even be able to observe Foo<int>.class
>> at all.
> If you think about the problem a little more, I think you'll find that
> this is wishful thinking.  (But of course, you're free to have a gut
> feeling without having thought about it at all.)
>  After all, if specialization is intended to be viewed primarily as an
>> implementation detail
> It is an implementation detail in the same sense that erasure is; that
> generics are implemented by erasure almost certainly leaks into the user's
> perception too.  (Erasure is why you can't have Foo<String>.class, for
> example.  Among many other things that the user has to pay attention to.)
> class Foo<any T> {
>     T get() { ... }
> }
> Consider the members of various instantiations of Foo.
> The signature of get() in Foo<String> is "String get()", but the signature
> of get() in Foo<int> is "int get()".  The erasure of the first is "Object
> get()"; the erasure of the second is "int get()".  While all erased
> reference instantiations can be implemented by the same class, the
> primitive/value instantiations cannot be.
> Similarly, Foo<int> can't extend Foo<?> (because that really means Foo<?
> extends Object>, and has to for compatibility reasons), nor can it extend
> raw Foo.  (Which is fine; raw types exist solely to support migration from
> ungenerified codebases to generified ones.)
> We could hide the existence of List<int>.class, but that would just make
> life harder for users, who would then have to jump through bigger hoops to
> reflect over the members of List<int> (which are different from the members
> of List<String>, even after erasure.)
>  In other words, while the Java language/library changes may be
>> expressed by some improvements to reflection, I'd be concerned about
>> the many implemented algorithms based on reflection.
> It is of course reasonable to be concerned.  Stay tuned and see if your
> concerns are addressed.

More information about the valhalla-dev mailing list