JLS §5.2 of Java SE 11 contains some new type conversion cases which JLS of Java 8 doesn't have, see item 4 and item 5 in the list:
Assignment contexts allow the use of one of the following:
- an identity conversion
- a widening primitive conversion
- a widening reference conversion
- a widening reference conversion followed by an unboxing conversion
- a widening reference conversion followed by an unboxing conversion, then followed by a widening primitive conversion
- a boxing conversion
- a boxing conversion followed by a widening reference conversion
- an unboxing conversion
- an unboxing conversion followed by a widening primitive conversion
I don't understand the case 4 and case 5 in the list. Could anyone give me some explanation with examples? If possible, please also explain its practical usage.
Update:
As @Naman commented, here is the proposal to change the JLS - JDK-8166326 : 5.2: Allow widening before unboxing which was in effect since Java-9. In the report, it mentioned:
This behavior is especially important for interoperability with capture: various existing programs expect to be able to treat the elements of a
List<? extends Integer>
as if they were ints.List<? extends Integer> li = null; int i = li.get(0);
This may imply that this JLS change do have a practical necessary. But I still don't understand why <? extends Integer> is important. What does interoperability with capture mean and why is it important? What do these various existing programs look like? Are they java code (I know some other languages also work on JVM and may have interaction with Java code)?
final
, I do not see the point of those two cases either. Those phrases, however, are repeated in § 5.3, § 5.5 and partially § 5.6. – Disciplinantfinal
makes importance here? – Mhopublic class MyBoolean extends Boolean { ... }
, for example, it would be logical thatboolean bool = myBoolean;
works. But since we cannot extend from the wrappers, I do not understand how we can get into a situation where we need to first widen the reference (from something that is a subtype of a wrapper) and then unbox. – DisciplinantInteger bigNumber = 10000000; Byte littleNumber = 5; long l = (bigNumber=littleNumber+2);
would demonstrate both - widening followed by unboxing and widening followed by unboxing followed by a widening primitive conversion. However, this is OK for JDK 8 alike. Just tested. – Mho<T extends Integer>
asint
s. – Prut<T extends Integer>
(or more precisely<? extends Integer>
) could easily be infered and not explicitly written by the developer, which can quite easily be constructed. – Sanity<T extends Integer>
is obviously non-sensical (since the wrappers are final), but it's not in itself an invalid type signature. And type inferrence (which often happens when closures are applied) can often lead to types that look like that (you don't tend to see those type definitions, which is the whole point of type inference). Now if something was inferred to be of the typeT extends Integer
then it would be nice if you could use it as if it was just anint
. This rule simply allows that. – SanityT extends Integer
without an example. – FeleciafeledyList<? extends Integer>
as if they were ints. So the change really took practical cases into account. But what is interoperability with capture? And what are the various existing code look like? Are they java code? – Feleciafeledy