[Java] Tips for Java, Tips

4 minute read

Overview

All you have to do is write and spell it out. I don’t know if it helps. And I don’t think it’s necessarily Java-specific.

Content

multiple assignment

You can assign the same value to multiple variables.

int x, y;
x = y = 10;
System.out.println(x); // 10
System.out.println(y); // 10

This seems to be interpreted as follows. Although 10 is assigned to y, the value returned by Java is also the assignment expression, so the evaluation value of the entire (y = 10) is assigned to x.

x = (y = 10);

How to write the main method

The main method is generally written as follows.

public static void main(String[] args) {
    System.out.println("Hello world!");
}

If you are using Java 5 or later, you can write the following.

public static void main(String... args) {
    System.out.println("Hello world!");
}

The only difference is String[] or String.... The former is an array and the latter is a variable length argument, but it seems that either main method may be used.

Just a scope

A new scope is created by using an if statement or for statement, but you can also create a simple scope without conditional branching or looping.

{
    int x = 10;
    System.out.println(x); // 10
}

{
    int x = 100;
    System.out.println(x); // 100
}

// System.out.println(x); // compilation error

x is defined twice, but the scope is different, so no compilation error occurs. Also, the scope of x is only the range enclosed by braces, so if you try to refer to x outside the braces, you get a compilation error.

HashSet implementation

HashSet is a class that just wraps a HashMap as an implementation. (*It’s about implementation details, so it may change in the future)

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

AbstractStringBuilder

Although StringBuilder and StringBuffer are written in JavaDoc as if they were subclasses directly under the Object class, they are actually subclasses of AbstractStringBuilder. AbstractStringBuilder is package private (not public API), so it may not be written in JavaDoc. (*It’s about implementation details, so it may change in the future)

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
{
// omitted
 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
{
// omitted

Define the method within the method

Normally in Java you cannot define a method inside a method. But you can do something like that with the var introduced in Java10. (I wrote it in another article)

Main.java


public class Main {
    public static void main(String[] args) {
        // Can be called with func.capitalize()
        // 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
    }
}

Run Java source code without compilation

I wrote this in another article, but since Java11, you can specify a source file with the java command and execute it without using javac. It may be useful for a little operation check. Well, I don’t think it’s really run without compilation, but I think it’s compiled behind the scenes.

Embed the process in the method of the existing class

In Java, you can embed processing in existing methods using anonymous classes.

List<String> list = new ArrayList<>() {
    @Override
    public boolean add(String s) {
        System.out.println("add called. arg: "+ s);
        return super.add(s);
    }
};
list.add("hello"); // add called. arg: hello
list.add("world"); // add called. arg: world
System.out.println(list); // [hello, world]

use instanceof for null

You can use instanceof for null.

System.out.println(null instanceof Object); // false

Of course, it doesn’t become true, but I think the point of interest is that NullPointerException is not thrown. You can get the same result with a variable assigned null, so you don’t have to do a null check before the instanceof.

thull the null

If a variable of exception type contains null, throw throws NullPointerException regardless of the variable type.

RuntimeException e = null;
throw e; // NullPointerException

cast null

It doesn’t make much sense, but for now I can’t throw any exceptions.

Object obj = null;
String str = (String)obj;
System.out.println(str); // null

Type judgment that does not allow subclasses

If you use instanceof, it will be true even if the instance type is a subclass of the specified class.

System.out.println("str" instanceof Object); // true

For subclasses, if you want to set it to false, you can compare Class types with equals as shown below.

System.out.println(new Object().getClass().equals(Object.class)); // true
System.out.println("str".getClass().equals(Object.class)); // false

Array is not type safe

Arrays are assignment compatible with arrays of one type and subclasses of that type. Therefore, the following code will be compiled and an error will occur at the time of execution.

Object[] array = new String[3];
array[0] = new Integer(10); // ArrayStoreException

If the list uses generics, a compilation error will occur and the above problem will not occur.

List<Object> list = new ArrayList<String>(); // incompatible types: ArrayList<String> cannot be converted to List<Object>

Detect overflow

If an overflow occurs during the operation, you will get an incorrect calculation result without any error. Since there is a utility method in the Math class that throws an exception when an overflow occurs, you can detect the overflow by catching the exception.

System.out.println(Integer.MAX_VALUE + 1); // -2147483648
Math.addExact(Integer.MAX_VALUE, 1); // ArithmeticException: integer overflow

Well, I feel like I should use BigInteger from the beginning.

At the end

I would be happy if there is any item that can be used as a reference. If you come up with something else, you may or may not add it.