Primitives in Generics
Michael Bien
mbien at fh-landshut.de
Thu Jul 8 15:18:21 PDT 2010
I wouldn't bet money on that :). E.g we generate various kinds of
primitive HashMaps just to prevent autoboxing which caused problems in
some situations.
http://jogamp.org/deployment/gluegen-next/javadoc/com/jogamp/common/util/package-frame.html
(gluegen is the binding lib used for jogl, jocl and joal)
sure its unrelated to project lambda but its basically the same issue as
in Ops.Foo (ParallelArray).
regards,
michael
On 07/08/2010 11:42 PM, Brian Goetz wrote:
> Its worth noting that ParallelArray is really the *only* well-known bad case
> here. Given the invasiveness to the language that function types represent,
> it seems a bad trade to take on such a big solution for a single ill-behaved
> library that some mad professor cooked up :) :) :)
> ^ Lots of smileys here!
>
>
>
> On 7/8/2010 9:48 AM, Reinier Zwitserloot wrote:
>> It's quite relevant, because state-of-the-lambda suffers from a rather
>> serious problem, which is highlighted by a core use-case driving project
>> lambda: ParallelArray's Ops container with its 132 SAM types. This proposal
>> would solve the issue and reduce that set of 132 to 8.
>>
>> If a JVM optimization can be proven to be trivial to implement (JRockit),
>> and fail to apply only in those cases where specialization wouldn't work
>> either, then I don't see how relying on this optimization is not sufficient.
>>
>> Your idea is an intriguing one which would indeed drop the need for the
>> JRockit boxing elimination optimization, though I don't think it can work.
>> For example, the following 2 code samples would seem to be perfectly valid,
>> but as far as I can tell the end result will be a NoSuchMethodError because
>> the produced instance will not actually have the primitive version of the
>> method. How will the compiler stop you from doing this, and, even if it
>> does, how is a java programmer to know these snippets won't work?
>>
>> Snippet #1: new ArrayList<int>().add(10);
>>
>> and to show this problem cannot be remedied just by detecting such
>> situations and disallowing them:
>>
>> Snippet #2:
>>
>> public static List<T> createList(Class<T> type) { return new ArrayList<T>();
>> }
>>
>> public void test() {
>> List<int> list = createList(int.class);
>> list.add(10);
>> }
>>
>>
>> --Reinier Zwitserloot
>>
>>
>>
>> On Thu, Jul 8, 2010 at 9:42 AM, Gernot Neppert<mcnepp02 at googlemail.com>wrote:
>>
>>> Reinier, I think your proposal is propably off-topic with regards to
>>> this mailing list, nevertheless I could not resist to respond ;-)
>>>
>>> I like the idea of making efficient use of generic classes with
>>> primitive type parameters possible. However, I'm worried that solely
>>> relying on a JVM optimization will not be sufficient. Wouldn't it be
>>> possible to gain efficiency on every VM if something along the
>>> following could be adopted:
>>>
>>> 1. Let's assume the existence of a generic interface
>>>
>>> L<T> {
>>> void add(T element);
>>> T get(int index);
>>> }
>>>
>>> 2. The declaration of a variable of type L<p> where p is one of the 8
>>> primitive types is possible.
>>> If the compiler encounters such a variable, it assumes that L<p>
>>> actually is equivalent to following 'extended' interface
>>>
>>> L'<P>
>>> {
>>> void add(P element);
>>> void add(p element);
>>> P get(int index);
>>> p get(int index);
>>> }
>>>
>>> where 'P' is the wrapper type corresponding to 'p'.
>>>
>>> 3. It would still remain illegal to declare an interface such as the
>>> above 'by hand', since overriding by return type is illegal unless the
>>> return types are covariant. However, the VM can cope with such
>>> overrides; and the compiler will encounter no ambiguities, as
>>> paragraph 4. will show.
>>>
>>> 4. With the assumptions made above, the following code would compile
>>> to the most efficient bytecode, invoking the primitive versions of
>>> 'add' and 'get':
>>>
>>> L<int> list;
>>> list.add(42);
>>> int value = list.get(0);
>>>
>>>
>>> 5. There has to be a means of instantiating objects of type L<p>. With
>>> the assumption made in 2., the solution is the same as with other
>>> abstract classes:
>>>
>>> A non-abstract class that implements L<p> for a primitive type p must
>>> implement those methods from the synthetic L'<p> that use the
>>> primitive type p, while the compiler will generate the necessary
>>> bridge methods with the wrapper type P:
>>>
>>> public class IntList implements L<int>
>>> {
>>> public void add(int element)
>>> {
>>> // efficient int-based implementation
>>> }
>>>
>>>
>>> public int get(int index)
>>> {
>>> // efficient int-based implementation.
>>> }
>>>
>>> }
>>>
>>> 6. The types L<P> and L<p> will be assignment compatible in only one
>>> direction: It will be possible to assign an instance of type L<int> to
>>> L<Integer>, but not vice versa.
>>>
>>> L<Integer> list1 = new IntList(); // OK
>>> L<int> list2 = new ArrayList<Integer>(); // Will not compile
>>>
>>> 7. If the assignment from L<P> to L<p> is forced through an unsafe
>>> cast, the attempt to invoke a method of L<p> using the primitive type
>>> p will result in a java.lang.NoSuchMethodException at runtime. This is
>>> comparable to the ClassCastException that can be thrown arbitrarily
>>> when unsafe casts are involved.
>>>
>>> L<int> list = (List<int>)(List)new ArrayList<Integer>();
>>> list.add(42); // Will throw NoSuchMethodException.
>>>
>
--
http://michael-bien.com/
More information about the lambda-dev
mailing list