Static fields in specialized classes
Vitaly Davidovich
vitalyd at gmail.com
Wed Oct 15 14:56:12 UTC 2014
>
> C# had the benefit of hindsight and designed their VM explicitly to
> support parametric polymorphism, including over value types. We don't have
> that benefit, and we're not going to redesign the VM for generics (sorry).
For posterity, .NET gained generics in 2.0, which was about 4 yrs after
initial release. They bit the bullet and made this first class (i.e. VM
knows about it), but granted they had fewer years of history/compatibility
(and user base) to deal with at the time.
If you conclude that List<int> is represented by a different class than
> List<String>, now we get to ask some questions. Should I be able to
> reflect over the members of List<int>? Should I be able to ask whether
> something is an instance of List<int>? If so, we have a choice of how to
> spell this, but ultimately that's just a question of syntax, how we expose
> the reality into the surface language.
>
My vote/answer would be "yes" to both of those questions. I'm not a fan of
erasure though, so I'm biased :).
>
> Whether we add more to reflection -- and we certainly will have to -- is
> another matter, but I think your actual disagreement is with the
> representation of generic types by classes.
> (Anyone else find it amusing that people complain when generics are erased
> (all instantiations are represented by a single class), and then complain
> when they are not erased (different instantiations mapped to different
> classes)?)
Yes, it's amusing but unsurprising given java's culture of preserving
backwards compatibility at all cost. Personally, I worry that evolving the
language with too much concern for preserving 10+yr old behavior is going
to lead to clunky features. Perhaps there can be a java X release that
simply breaks free of some baggage and people wanting to upgrade do their
part in modifying their codebase accordingly? Wishful thinking, I know :)
On Wed, Oct 15, 2014 at 10:19 AM, Brian Goetz <brian.goetz at oracle.com>
wrote:
> Let's take several steps back away from the "I want to continue
> programming with the reflective tools I was comfortable with in Java 1.0",
> and see if we can get at the heart of this "augh, different is scary!"
> reaction here that seems to be spreading.
>
> Forget for a second about whether the letters "List<int>.class" have
> semantic meaning in a .java file. We can certainly hide that, though I
> think (as I said yesterday) you'd probably ultimately complain if we did.
>
> The fundamental question for an implementation of generics is the mapping
> between types and classes. (List<String> is a type; List.class is a class.)
>
> In Java 1.0, there was a clean 1:1 mapping from types to classes.
>
> In Java 5, all instantiations of List<X>, for reference X, mapped to class
> List.class; this is an all-to-1 mapping. This is simple but everyone seems
> to think this is smelly and complains about it a lot. (Too bad, this aspect
> isn't going away.)
>
> In C++ templates, there is a clean 1:1 mapping again; every instantiation
> of list<x> is a distinct class, with no relationship to each other in the
> type system. But that distinctness means we give something up; for
> example, there is no "instanceof list" (or cast to list) because list is an
> infinite family of unrelated types.
>
> C# had the benefit of hindsight and designed their VM explicitly to
> support parametric polymorphism, including over value types. We don't have
> that benefit, and we're not going to redesign the VM for generics (sorry).
>
> So the question is, can we implement List<int> with the same class as we
> implement List<String>. Nearly all the other discomforts follow from this
> same issue (that's what instanceof means, for example). Can you do
> better? (I propose you think about this for a good long time before
> responding.)
>
> If you conclude that List<int> is represented by a different class than
> List<String>, now we get to ask some questions. Should I be able to
> reflect over the members of List<int>? Should I be able to ask whether
> something is an instance of List<int>? If so, we have a choice of how to
> spell this, but ultimately that's just a question of syntax, how we expose
> the reality into the surface language.
>
> Whether we add more to reflection -- and we certainly will have to -- is
> another matter, but I think your actual disagreement is with the
> representation of generic types by classes.
>
> (Anyone else find it amusing that people complain when generics are erased
> (all instantiations are represented by a single class), and then complain
> when they are not erased (different instantiations mapped to different
> classes)?)
>
> On 10/15/2014 9:48 AM, Paul Benedict wrote:
>
>> I throw my lot in with Ben and Stephen. I don't think specialization
>> should be exposed to the point that you can tell the difference with
>> .class. That's very disruptive to code and surprising. Rather, I think
>> you should expose more methods on Class to query the specialization type
>> -- that was something I recommended in the beginning and still favor.
>>
>>
>> Cheers,
>> Paul
>>
>> On Wed, Oct 15, 2014 at 3:30 AM, Ben Lewis <benlewisj at gmail.com
>> <mailto:benlewisj at gmail.com>> wrote:
>>
>> 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.class==Employee.class;//true
>> p2.class==Employee.class;//false
>> 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
>> }else{
>> //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 oracle.com <mailto:brian.goetz at oracle.com>>
>>
>> wrote:
>>
>> > 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