[Java] When var should be used and when it should not be used

Overview

Starting with Java10, you can use type inference for local variables using var. Although it is convenient, it may reduce readability if used incorrectly, so I thought about when to use it. (Java 10 came out more than a year ago, so it's a further story now)

Operating environment

Java 10 or later

What is var in the first place?

When declaring a local variable, you can omit the type specification by writing "var" instead of specifying the variable type. This is so-called type inference.

//Traditional writing style
String s = "hogehoge";
//How to write using var
var s = "hogehoge";
//String class method toUpperCase()(Variable s is recognized as a String type)
System.out.println(s.toUpperCase());  // => HOGEHOGE

What are you happy about

No matter how long the model name is, all you have to do is write "var", which makes it easier to write. It should also be easier to read as it eliminates redundant information and is neat.

//Traditional writing style
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");
//How to write using var
var dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");

The reasonably long name DateTimeFormatter has appeared twice, and I think it's a little easier to write and read.

Not dynamically typed!

Using var is still statically typed. Variables are not detyped, they are simply typed automatically when they are defined. You cannot reassign a value of another type to a variable once defined with var. (Compile error occurs) [^ 1]

[^ 1]: Of course, this is not the case for assignment compatible types such as subclasses.

//Since the right side is a string literal, the variable s is automatically of type String
var s = "hogehoge";
//Since s is a String, you cannot assign a value of another type such as int
s = 123;
//error:
//Incompatible type:int java.lang.Cannot convert to String:
//  s = 123;
//      ^-^

It is also a compile error if the type cannot be uniquely specified from the right side when defining a variable with var.

//Compile error because null doesn't know what type it is
var v = null;
//error:
//Unable to infer the type of local variable v
//    (The variable initializer is'null'is)
//  var v = null;
//  ^-----------^

It's completely different from JavaScript var etc., so don't get me wrong.

Whether to use var

You know what var is. (maybe) From here, as the title suggests, we will consider when to use var and when not to use it.

When to use var

In a word, it is a case where you can tell at a glance what type you have by looking at the right side. Specifically, the following cases are assumed.

When instantiated on the right side

//Since the model name is written as it is on the right side, you can see what type it is at a glance
var date = new Date();

var scanner = new Scanner(System.in);

var list = new ArrayList<String>();

If the right side is literal

//Since the right side is a string literal, you can see at a glance that it is a String type.
var s = "hogehoge";
//Since the right side is an integer literal, you can see at a glance that it is an int type.
var n = 123;

When calling a method that can easily guess the return type on the right side

//You can tell because the method name contains the type name
var br = Files.newBufferedReader(Paths.get("filename"));

//It gets the current date and time, but since it is a static method of LocalDateTime, it can be inferred that it is a LocalDateTime type.
var date = LocalDateTime.now();

//Since you get an instance of Calendar, you can guess that it is a Calendar type.
var cal = Calendar.getInstance();

If you shouldn't use var

The opposite of when you should use var, in a nutshell, when you're calling a method that doesn't accurately guess the return type by looking at the right-hand side.

// Date#getTime()
//Since there are various types that represent dates, you cannot tell by just "Time" (actually, it is a long type).
var time = date.getTime();

// Path#getFileName()
//Is it a String because it is a file name? (Actually Path type)
var filename = path.getFileName();

// File#getAbsolutePath()
//Since there is Path, is this also Path type? (Actually String type)
var path = file.getAbsolutePath();

// Files#copy(Path, OutputStream)
//I've received something but I don't know what it is. It looks like a numerical value, so int? (Actually, a long type value that represents the number of bytes copied)
var size = Files.copy(path, out);

bonus

When used in combination with an anonymous class, you can define methods that are valid only within a particular method. It has nothing to do with the main subject, but I will write it because it may be useful.

Main.java


public class Main {
    public static void main(String[] args) {
        // func.capitalize()Can be called with
        //func is a local variable and cannot be called from outside this method
        var func = new Object() {
            private String capitalize(String s) {
                return s.substring(0, 1).toUpperCase() + s.substring(1, s.length()).toLowerCase();
            }
        };

        System.out.println(func.capitalize("tokyo")); // => Tokyo
        System.out.println(func.capitalize("TOKYO")); // => Tokyo
    }
}

Summary

Reference link

Recommended Posts

[Java] When var should be used and when it should not be used
Three reasons why wrapper classes should not be used in Java
Map keySet, values should not be used
[Java10] Be careful of using var and generics together
Syntax and exception occurrence conditions that can be used when comparing with null in Java
Spring should be suspected when Rails commands do not work properly
Why Java Vector is not used
java jshell and var are too recommended!
[Rails] [Memo] When to add = to <%%> and when not
Story when migration could not be done
[NetBeans] Story when it does not start
[Java] When checking URL format with Bean Validation, it may be better not to use @URL of Hibernate Validator.
[CentOS8] Since the javac command could not be used, install the java development environment.
Be careful with requests and responses when using the Serverless Framework in Java
ValidationMessages.properties should not be multiple on the classpath
Gekitsuyo RestTemplate should be used for REST communication
Things to be aware of when writing Java
Java switch statement and break, Kotlin when expression ...
About var used in Java (Local Variable Type)
Java Servlet should be aware of multithreaded environment
Why Java String typeclass comparison (==) cannot be used
[Java] Precautions when referencing a reference type in a parent class and instantiating it in a child class
The story that the variable initialization method called in the Java constructor should not be overridden