What type is a var?

Java 10 introduced “var” where the type of the variable is implied. This leads to some tricky scenarios.

We first learn that “var” can replace the type. That means these two code blocks are equivalent.

int a = 9;
int b = a;
var a = 9;
int b = a;

Ok. So far so good. Now we have this code:

short a = 9;
short b = a;

So we substitute var and the code no longer compiles!

var a = 9;
short b = a;

What’s going on? Well, Java is only using the one line to figure out the type. Since int seems like a reasonable default, variable a is an int. Until of course, we get to the next line and it isn’t.

This would compile, but defeats the purpose of using var. So be careful!

var a = (short) 9;
short b = a;

[2018 oracle code one] Var with Style

Var with Style – Local Variable Type Inference with Java
Speaker: Stewart Marks
Oracle

#VarWithStyle

For more blog posts, see The Oracle Code One table of contents


Local variable type inference

  • “var” tells compiler to infer the type
  • Still a static type. Should compile same as if typed the class name
  • Type inference is not new. Lambdas did it in Java 8

Where can use

  • local variables
  • resource variables in try-with-resources
  • loop variable in for-each loop
  • [and lambadas in Java 11]
  • can’t use in places where API/written into class file/affects binary compatibility

How compiler determines type

  • Looks at initializer’s type
  • Can’t use when not info info
    • var customer = null (not allowed because ambiguous)
    • var fun = (int a, int b) -> a + b (not allowed because lambda needs type for context)

Other notes

  • Can reassign using normal assignment rules. (aka same or compatible type as to what var really is)

Benefits of var

  • Add features to language so can write better code
  • Using var in right way results in better code
  • Reduces verbosity/clutter/redundancy
  • Let’s variable name stand out which is more important
  • About readability; not amount of typing.

Local Variable Type Inference Style Guide

You can write code with or without var. See style guide to mitigate usage concerns – new idea to release style guide at same time as feature. There’s also a FAQ

Principles

  • P1 – Reading code is more important than writing code
  • P2 – Code should be clear from local reasoning – had considered inferring from context all over class. But then hard to figure out and reader has to type inference in his/her head
  • P3 – Code readability shouldn’t depend on IDEs
  • P4 – Explicit types are a tradeoff

Guidelines

  • G1 – Choose variable names that provide useful information
  • G2 – Minimize the scope of local variables
  • G3 – Consider var when the initializer provides sufficient information to the reader
  • G4 – Use var to break up chained or nested expressions with local variables
  • G5 – Don’t worry to much about “programming to the interface” with local variables
  • G6  – Take care when using var with diamond or generic methods.
  • G7 – Take care when using var with literals.

General

  • “you read the internet and it’s such a great source of conference talks”
  • var x = getSomething() – already terrible code because a bad method name
  • InputStream inputStream = socket.getInputStream() – mentioning input stream twice instead of three times seems ok. Covers G1 and G3. The variable name and context is sufficient
  • try with resources – often long code so hard to spot variables. Using var aligns them.
  • Long class names penalizes doubly. Using var lets you put in once.
  • Helps with generics. Have a very long type name
  • var list = new ArrayList,String>. Can’t use diamond operator or would have ArrayList<Object>. Want to avoid using var and diamond together. Note that the type is now ArrayList and not List. Ok because just using as local variable. The method return type would still be List.
  • Also be careful with methods returning generics. List.of() returns List<Object> when don’t pass any parameters.
  • Fun side effect – less imports because type names not all mentioned explicitly

My take: This was an awesome session. I like that he covered the background and style guide. I also REALLY liked the before/after examples to show when it is good to use var. Also, time flew in this session!

var in java 10

In my Java 10/11 talk, I ask the audience if this code compiles:

var var = "var";

I usually get about a 50/50 response. The answer is that it does compile due to backward compatibility. You could have a local variable named var and it should still work. When I gave the talk at the NY Java Sig tonight, Mark asked “what if you have a class named lower case var”. After wincing a bit at the lower case class name, I said I didn’t know. But I definitely wanted to find out.

The answer is actually pretty interesting – it depends on what version of Java you compile with!

Compiling var.java

Fierst I created a class


public class var {

&nbsp; public static final String STR = "a";

}

This class compiles in Java 9 and below. It does not compile in Java 10 or 11. Instead you get the message:

as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations

This means that you have to change the class name. However, you can still have a var.class file compiled in Java 9 or below.

Referencing that var.class file

Compiling OR running the code with Java 10/11 doesn’t let you refer to that var.class file either.

TripleVar.java:5: error: illegal reference to restricted type 'var'

Conclusion

If you followed bad practices and named your class var.class, you must change it. Even if you compiled in Java 9, it will not run in Java 10.