Classes, specializations, and statics
Palo Marton
palo.marton at gmail.com
Mon Feb 15 21:03:52 UTC 2016
Just one note on this issue: You have to deal also with this slightly
different code:
class SomeOtherClassWithoutTParameter {
private static Collection<T> emptyCollection = …
private static Collection<T> emptyCollection() { return emptyCollection;
}
}
E.g. Collections.emptyList()
It can be handled by creating some fake <T> parametrized inner class, but
may be there is a more elegant solution within your current model.
(see also this message:
http://mail.openjdk.java.net/pipermail/valhalla-dev/2015-January/000812.html
in this old thread from Jan 2015:
http://mail.openjdk.java.net/pipermail/valhalla-dev/2015-January/000802.html
)
On Mon, Feb 15, 2016 at 7:11 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
> M3 leaves us in a position to check off one of the outstanding issues,
> which is that of specialization-specific statics.
>
> Members of Java classes have historically been divided into static and
> instance members; static members are associated with a class, and instance
> members with an instance of a class.
>
> When Java 5 extended the type system to support multiple TYPES that are
> represented by the same CLASS (e.g., ArrayList<String> and
> ArrayList<Number>), we had a choice; treat static members as belonging to
> the CLASS, or as belonging to the TYPE. We chose the former, as that was
> consistent with the translation strategy of erasure, and also maximized
> compatibility with existing code. (When .NET did reified generics, they
> chose the opposite; Foo<Number>.staticMember and Foo<String>.staticMember
> refer different variables. That’s also a valid choice.)
>
> The following program would be sensitive to this distinction:
>
> class Foo<any T> {
> static int count;
>
> public Foo() { ++count; }
> }
>
> new Foo<String>();
> new Foo<Number>();
>
> In Java, this program would increment the common counter twice; under the
> alternative interpretation, the counters Foo<String>.count and
> Foo<Number>.count would each be incremented once.
>
> Statics in Java work the way they do, and we’re not proposing we change
> that. However, once we break the assumption that all instantiations of a
> parameterized type are reference instantiations, we run into some issues
> with existing code idioms. What follows is a proposed generalization of
> static members in the spirit of Model 3.
>
>
> The Problem
> -----------
>
> Java code frequently uses tricks like the following, that exploit the
> assumption of erasure:
>
> // Cached instance of an empty collection
> private static final Collection<?> c = new EmptyCollection<?>();
>
> // Factory method that dispenses the cached empty collections, suitably
> casted
> public static<T> Collection<T> emptyCollection() { return (Collection<T>)
> c; }
>
> The above trick works because of erasure; a Collection<?> has the same
> representation as a Collection<String>, Collection<Integer>, etc, so we can
> freely cast it about with no loss of type safety. But once we anyfy
> emptyCollection(), we’re now hosed; we can’t cast a Collection<?> to a
> Collection<int>. This leaves us without a means of coding this common
> idiom, because static members currently are per-class, not
> per-instantiation.
>
> Obviously, the above code must continue to mean what it means today. But
> we’d also like a means of extending the above idiom more broadly than
> erased generics.
>
>
> Extending Statics to Specializations
> ------------------------------------
>
> Our current model treats parameterizations of template classes like
> classes; anywhere in the bytecode that one can refer to a Constant_Class,
> one can refer to a Constant_ParameterizedType. (Whether they are actually
> classes, or more like “species”, is an open question, but whatever they
> are, there’s a way to write their name in the classfile.)
>
> The existing prototype places static members of Foo<any T> on the erased
> species Class[Foo], and translates access to static member m of Foo<any T>
> as:
>
> xxxstatic Class[Foo].m
>
> However, we are free to assign meaning to xxxstatic as applied to a member
> reference whose owner is a parameterized type. Suppose we extend the
> current set of member ownerships from { instance, static } to { instance,
> static, specialization }. We could then access a per-specialization member
> using xxxstatic on a member reference whose owner is a specialization.
>
> The syntactic story is mostly a bikeshed; we’ll need some token to
> indicate “per-specialization”; we’ll use the silly token
> __SpecializationStatic for now.
>
> The access story is simple: static members continue to only be able to
> reference other static members (and not class type variables); __SS members
> can access static members and other __SS members, as well as class type
> variables; instance members can reference static, __SS, and instance
> members.
>
> The translation / classfile story is simple. Assume we have a spare flag
> bit (we can synthesize one) for ACC_SPECIALIZATION_STATIC (ACC_SS for
> short.) Static members are marked with ACC_STATIC; __SS members are marked
> with ACC_SS. Accesses to static members continue to be translated as
> xxxstatic Class[Foo].m; accesses to __SS members are translated as
> xxxstatic ParamType[Foo,params].m.
>
> The specialization / runtime story is simple. Static members are treated
> as if they are restricted to the erased species (this is a natural choice,
> since Class[Foo] and ParamType[Foo, erased] describe the same class.) __SS
> members become static members on each parameterization. (Both of these are
> one-line changes to the existing specializer prototype.) TypeVar constants
> used in the signature / bodies of __SS members are specialized as usual,
> and just work.
>
>
> Example:
>
> class Collection<any T> {
> private __SS Collection<T> emptyCollection = …
> // ACC_SS field emptyCollection : ParamType[Collection, TypeVar[T]]
>
> private __SS Collection<T> emptyCollection() { return emptyCollection; }
> ACC_SS emptyCollection()ParamType[Collection, TypeVar[T]] {
> getstatic ParamType[Collection, TypeVar[T]].emptyCollection :
> ParamType[Collection, TypeVar[T]]]
> areturn
> }
>
> When we specialize Collection<int>, the field type, method return type,
> etc, will all collapse to Collection<int> by the existing mechanisms.
>
>
>
More information about the valhalla-spec-observers
mailing list