Primitives in Generics

Rémi Forax forax at univ-mlv.fr
Thu Jul 8 15:38:56 PDT 2010


ParallelArray is not the *only* bad case.
Trove was created more than 10 years ago.
http://trove4j.sourceforge.net/javadocs/

Rémi

Le 09/07/2010 00:18, Michael Bien a écrit :
>    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.
>>>>
>>>>          
>>      
>    



More information about the lambda-dev mailing list