With Java 10 or +, we can use var keyword for declaration. At initialization, a type is going to be inferred by the compiler.
What happens when the class I instantiate and assign to the variable declared with var, is the implementation of the interface? which type is it going to be inferred, Interface or the implementation?
5 Answers
My 2 cents to correct the question and answers:
- The
varis NOT a Java keyword. It's a reserved type name. It seems not a big difference but in fact, it IS:
var var = 0; Here var is a variable name too, so the var can be used as a type name, but there is no restriction like for regular keyword (i.e. we can have a variable named var too).
- The actual type of the variable IS decided by the Java compiler on the line where the variable declared, at compile-time, but the type is NOT actually the exact implementation you use on the right side of the expression. See this code:
var i = true ? Integer.valueOf(1) : "ABC"; The Java compiler needs to pick a type for variable i which will satisfy both branches. It could be a) Object, b) Serializable, c) Comparable, or combinatioin, or all three. We don't care and don't know.
Answer to your question:
Type of the variable will be exactly same, as the class, instance of which you're assigning to the variable declared with var.
Motivation for var keyword:
Remember, that the only purpose of using var, according to the design of the language (since JDK 10+) is to beautify the code and make it more readable.
For example, this code:
URL url = new URL(""); URLConnection conn = url.openConnection(); Reader reader = new BufferedReader( new InputStreamReader(conn.getInputStream())); is less clear to read, then:
var url = new URL(""); var conn = url.openConnection(); var reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); Implementation
var only servers the cleaner-code and better readability purpose, it doesn't amend the Type System of the Java language. That's why, you can't use it in the class level (for static or instance fields), because fields might be used with polymorphism, might be injected by IoC, or etc. and at the bytecode, it's not possible to dynamically change the field type for each different case.
The other answers so far don't stress one important point, the distinction between compile-time deducible type and run-time instance class.
Suppose we have
var data = Collections.singleton("test"); Then, the compiler can see that Collections.singleton("test") is declared to return Set<String>. So data effectively gets declared as Set<String> (not e.g. Collection<String> nor Object nor Collections.SingletonSet). Set<String> is the most specific info the compiler can find out.
When running, the instance referenced in data will be of some implementation class (e.g. Collections.SingletonSet), decided upon by the Collections.singleton() method, meaning that data.getClass() will not return the Set class, but something different that implements the Set interface, i.e. Collections.SingletonSet.
So we have to consider three types:
- The run-time class of the instance that gets assigned to the variable (e.g. a
Collections.SingletonSet). This will of course always be compatible with (2) and (3), and cannot be known at compile-time. - The compile-time type of the expression that you assign to the variable (e.g.
Set<String>). - The declared type of the variable. Classically, you'd find that explicitly left of the variable name, and when using the
varkeyword, the compiler treats it as if declared with the type from (2) (i.e.Set<String>).
The 'official' Local Variable Type Inference style guide () raises this concern, but says:
"It must be reiterated here that var can only be used for local variables. It cannot be used to infer field types, method parameter types, and method return types. The principle of "programming to the interface" is still as important as ever in those contexts."
and
0"If, as recommended in guideline G2, the scope of the local variable is small, the risks from "leakage" of the concrete implementation that can impact the subsequent code are limited."
The type will be exactly the same of the value the variable gets assigned to.
In case you are more concerned with interface over implementation idea: you can create function which returns interface type but creates a specific implementation instance inside.
1