Notes on implementing concise calls to constructors with type parameters

Reinier Zwitserloot reinier at zwitserloot.com
Fri May 15 19:54:19 PDT 2009


I believe the current rules for how generified static methods infer  
the generics can be very easily adapted to inferring for a constructor  
call with no generics info whatsoever (what's currently a raw  
constructor call) - without breaking ANY backwards compatibility. The  
only major difference is for 'un-inferable' types, where generics  
inference will bind the type to the specified bound (the Number in <T  
extends Number>) whereas a raw type will always pick Object, even if  
Object would never make for a legal T. Inference is very very  
complicated, so cooking this up without checking the official spec is  
bound to lead to inconsistencies.

Example complex inference:

foo(Collections.emptyList(), Arrays.asList(1, 2, 3).get(1));

where foo exists in many overloaded variants. Try and sort that mess  
out. From past experience the current inference algorithm generally  
chokes on this, and you'll need to put in explicit generics info.

Unfortunately I don't have the time this month to open the JLS and  
work this out.


  --Reinier Zwitserloot



On May 16, 2009, at 01:27, Ali Ebrahimi wrote:

> On *Fri*, May 15, 2009 at 14:01:02,  Joseph D. Darcy <Joe.Darcy at
> sun.com<http://mail.openjdk.java.net/mailman/listinfo/coin-dev>>
> wrote:
> :
>
>> Raw types were of course a compromise as part of bring generics to an
>> established language and its existing libraries.
>>
>> Their use should be avoided in new code and the compiler should help
>> users in this regard.
>>
>> One step in that direction is that compiler(jdk1.7+) to use hidden  
>> diamond
> operator in some cases.
> By adding below simple rule:
> code sample:
>
> Cell<String> cs = new Cell(1);
>
> Rule:
> if instantiated object type(in new Cell(1), Cell class) is generic  
> class
> then goto GENERIC_CASE
>
> GENERIC_CASE:
>   treated as :
>   Cell<String> cs = new Cell<>(1);
>
>   and this treated as:
>
>   Cell<String> cs = new Cell<String>(1);
>   goto Next:
>
> else // raw type(legacy code)
> RAW_CASE:
>   Cell<String> cs = new Cell(1);
>
> Next:
>
> And finally catching compile time error for generic code.
>
> I think one of main goals of adding generic support to java language
> was catching run time exceptions in compile time and having robust and
> safe code.
>
> I don't think the Cell class to be a legacy code(row type)in this  
> case.
> I think this particular rule can be applicable at least in Object
> instantiation case.
>
> if right hand side is not a generic type use the row type.
>
> Cell<String> cs = new LegacySubCell(10);
>
> By diamond operator if we use:
> Cell<String> cs = new LegacySubCell<>(10);
>
> compiler got an error, because LegacySubCell is not generic
> class(legacy code).
> But by my rule(no diamond operator in code) this compiles fine.
>
> because that the LegacySubCell class is not generic(legacy code)
> treated as row type.
> By this rule we decrease the use of row types and not dropping them
> totally ones.
>
> One advantage of this rule is that if some day we decided to update
> legacy code and generified them.
> By recompiling code, in this time the compiler  would use the generic
> LegacySubCell class and
> We would had:
> the code:
> Cell<String> cs = new LegacySubCell(10);
>
> treated as
> Cell<String> cs = new LegacySubCell<>(10);
>
> and this treated as:
> Cell<String> cs = new LegacySubCell<String>(10);
>
> And finally catching compile time error.
>
> I think we don'nt need to the first step and diamond operator to be  
> hidden.
>
> And we have:
>
> Cell<String> cs = new Cell(1);
>
> if Cell is generic class
> then goto GENERIC_CASE
>
> GENERIC_CASE:
>   treated as :
>
>   Cell<String> cs = new Cell<String>(1);
>   goto Next:
>
> else // raw type(legacy code)
> RAW_CASE:
>   *Cell<String> cs = new Cell(1);
>
> Next:
>
>
> One note: By this rule we don't need to change code for using new
> generic versions of legacy classes.
>
> Another example:
> List<String> myList = new ArrayList();
>
> treates as: GENERIC_CASE
>
> List<String> myList = new ArrayList<String>();
>
> because that ArrayList is now generic class(since 1.5).
>
> But the following code:
>
> List<String> myLegacyList = new MyCustomLegacyList();
>
> is treated as: Raw_CASE
> List<String> myLegacyList = new MyCustomLegacyList();
>
> and some day if I update MyCustomLegacyList class(generified it) and  
> recompile
> above code without changing code:
>
> Compiler(jdk 1.7+) in this time must behave as below:
> List<String> myLegacyList = new MyCustomLegacyList();
>
> Must be treated as: GENERIC_CASE
> List<String> myLegacyList = new MyCustomLegacyList<String>();
>
>
> Therefore by this rule we can slowly remove row types from language(by
> compiler help).
>




More information about the coin-dev mailing list