Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News JEP 286 Proposes Extending Type Inference to Local Variables in Java

JEP 286 Proposes Extending Type Inference to Local Variables in Java

This item in japanese

A proposal has been sent to the platform-jep-discuss mailing list, introducing JEP 286 that, if implemented, would extend type inference to local variables in Java. As this is at an early stage proposal there is no plan on which version of Java it would target, or even that it would ever be implemented.

Type inference is the ability for a variable to be declared but without having to specify the associated type. Java has had type inference for some time; when generics were added in Java 5 it used type inference when dealing with generic methods. Java 7 added the diamond operator <> (as part of Project Coin) which allowed a variable of type List<String> to be initialized without a type bound ArrayList<>. More recently, Java 8 added lambdas and streams which inferred types in method chains, along with the formal parameter types in lambda arguments. Type information can often be inferred from the surrounding context or from the expression used in the initializer. Similarly expressions which are typeless (like 0 or null) cannot necessarily have a correct type inferred. Type inference even has the entire chapter 18 in the Java Language Specification.

Since there is support for type inference already, including inferring effectively final local variables, it is not a big stretch to imagine this being used for local Java variables. This only applies to local variables (those defined within a method or lambda body) but not those in method signatures or field signatures.

The proposal offers a keyword-like var construct in order to declare a variable with an inferred type. Languages with type inference have typically put the type after the variable name, such that a variable or parameter can be defined as aNumber:Int or aNumber, effectively treating the type declaration (:Int) as an optional suffix. However, Java is based on C like languages that put the type first, and changing this wouldn't be practical. As a result, a keyword-like var is used to act as a placeholder meaning 'any type', while being similar to the way that variables in other languages are defined. As a result it would be possible to write statements like:

var proposal = "JEP-286";

In this case, the type of the proposal varaible would be inferred to be String, the concrete type of the expression on the other side. This would also simplify generified data structures such as:

var phonebook = new HashMap<String,String>()

It should be noted that the type will be inferred to be the concrete type; in this case, it might be preferable to use an interface instead. However for most purposes, and given that it will apply to local variables only, the distinction shouldn't be particularly relevant.

There are also questions as to whether other keyword-like constructs may be beneficial, such as a different construct for read-only variables. Although final var could be used (and the inference for effectively final is already in place, perhaps not even necessary) there are other possibilities that could be used, inspired from other languages, such as constval or let. There are also other possibilities for the var declaration, such as auto and the JEP proposers are asking for feedback. There is a survey available which asks for your opinions on which would be preferable.

The suggested implementation is not to make the var (or auto/let/def/val ...) a new keyword, which would invalidate existing Java programs who had used those as identifiers already. Instead, they would be reserved type names, effectively like Object or String. Applications that used var as an existing type (class or interface) would break, but these would be breaking existing Java naming guidelines already.

A prototype implemented and scanned over the existing JDK source code suggested that in many cases local variables could be translated to use var with no problems. A few cases weren't able to infer the result successfully, either because there was no initializer value, the initializer was null (which of course could be any type) or because they inferred a more strict type than the one specified (e.g. inferring ArrayList instead of List). It does suggest that the idea could be workable in practice and useful in a majority of cases.

Running a prototype over the JDK source code:

  • 83.5% inferred the exact type present in the source code
  • 4% inferred another denotable type (usually a sharper type)
  • 0% were rejected because inferred type was non-denotable
  • 8.5% were rejected because they had no initializer
  • 3% were rejected because initializer was null
  • .5% were rejected because a target type was required

If we exclude those that are rejected because they have no initializer or the initializer was null, we find that over 99% of local variables are inferrable, and 95% are inferred with the exact type present in the source code.

Of effectively final locals (77% of all locals):

  • 86% inferred the exact type present in the source code
  • 4.5% inferred another denotable type (usually a sharper type)
  • 0% were rejected because inferred type was non-denotable
  • 8% were rejected because they had no initializer
  • .5% were rejected because initializer was null
  • .5% were rejected because a target type was required

The proposal to add this into a future version of the Java language will be discussed under the JEP 286 banner; those with opinions are invited to fill in the survey before it closes on 16th March 2016 to provide feedback to the Java team.

Update to enable developers to try and experiment with the work in progress so far of JEP 286, and as part of the Adopt OpenJDK programme run by the London Java Community, Richard Warburton of Iteratr Learning has publicly posted unofficial builds of the Open JDK with JEP 286 support. This will allow developers to easily consume and experiment with the new featuers described above.

Rate this Article