Java programmers' online painful stepping on pits

1. The empty pointer is abnormal due to the automatic unpacking of the packaging type

public int getId() {
    Integer id = null;
    return id;
}

What happens if the above method is called? The id is of Integer type, and the return value of the method is of int type, which will be automatically unpacked and converted. Because the id is null, a NullPointerException exception will be reported when it is converted to int type.

Both Alibaba java development manual, code cleanliness and Effective Java recommend that the method return value type be written as a wrapper type, similar to Integer. In addition, the attributes in the entity class, the receiving front-end parameter class and the response class to the front-end should be written as packaging types to avoid unpacking errors.

2. The packaging type is judged equal with = = which leads to incorrect judgment

Let's first look at the running results of a piece of code:

public class IntegerTest {
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        Integer c = 200;
        Integer d = 200;
        System.out.println(a == b); // Output true
        System.out.println(c == d); // Output false
    }
}

Many people wonder why the two output results are different?

When an Integer type is assigned a value, Integer. Is called Valueof() method

static final int low = -128;
static final int high = 127;

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

When the value value is between - 128 and 127, the cache is reused. Objects are created when they are not in this interval.

The = = compares the memory addresses. The memory addresses of different objects are different, so the above results appear.

Integer overrides the equals() method:

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

When the equals() method is used, the comparison is whether the int values are equal.

Therefore, when judging whether the packing class is equal, it must not be judged with = = but with the equals() method.

3. Null switch parameter leads to null pointer exception

Guess the result of the following code:

public class Test {
    public static void main(String[] args) {
        String name = null;
        switch (name) {
            case "yideng":
                System.out.println("One lamp");
                break;
            default:
                System.out.println("default");
        }
    }
}

Do you think default will be output? In fact, the code will throw a NullPointerException exception.

When switch compares whether two objects are equal, it calls name Hashcode () method and name The equals () method throws a NullPointerException because the name is null.

Therefore, before calling the switch method, the passed parameters must be judged null.

4. Precision is lost when creating BigDecimal type

Guess the result of the following code:

public class Test {
    public static void main(String[] args) {
        BigDecimal bigDecimal = new BigDecimal(0.1);
        System.out.println(bigDecimal);
    }
}

You think it will output 0.1. In fact, the output result is:

0.1000000000000000055511151231257827021181583404541015625

What? What is such a big string?

Why does this happen? The reason is that when we create an object with new BigDecimal(0.1), this construction method of BigDecimal will be called:

public BigDecimal(double val) {
    this(val,MathContext.UNLIMITED);
}

The parameter 0.1 is regarded as a double type. When double is calculated, the value will be converted into binary, and the conversion of 0.1 into binary cannot be divided, so it brings a large string of decimal places.

What should I do when I need to create a BigDecimal type?

You can convert a numeric value to a string type before creating a BigDecimal object, like this:

BigDecimal bigDecimal = new BigDecimal(String.valueOf(0.1));

Another question, how does BigDecimal solve the problem of precision loss?

The answer is that BigDecimal will first multiply the value by an integer multiple of 10, remove the decimal places, convert it into a long type, then perform the operation, and finally divide the operation result by an integer multiple of 10.

5. When the list is converted to Map, the primary key is repeated, resulting in an exception

Can the grouping of the following codes succeed?

public class SteamTest {
  
    static class User {
        // User ID
        private Integer id;
        // user name
        private String name;
    }

    public static void main(String[] args) {
        List<User> users = Arrays.asList(
                new User(1, "Tom"),
                new User(1, "Tony"),
                new User(2, "Jerry")
        );
         // User sets are grouped by id
        Map<Integer, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getId, user -> user));
      System.out.println(userMap);
    }
}

The result is an exception, Exception in thread "main"
java.lang.IllegalStateException: Duplicate key SteamTest.User(id=1, name=Tom)

The reason is the primary key conflict. There are two data with id=1. When grouping by ID, the program does not know how to deal with it.

You can do this

public class SteamTest {
  
    static class User {
        // User ID
        private Integer id;
        // user name
        private String name;
    }

    public static void main(String[] args) {
        List<User> users = Arrays.asList(
                new User(1, "Tom"),
                new User(1, "Tony"),
                new User(2, "Jerry")
        );
         // User sets are grouped by id. when the primary keys conflict, the first user is selected
        Map<Integer, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getId, user -> user, (user1, user2) -> user1));
      System.out.println(userMap); // Output {1:{"id":1,"name":"Tom"},2:{"id":2,"name":"Jerry"}}
    }
}

6. True or false ArrayList causes an exception to be added

Can the following add() method be added successfully?

public class Test {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2);
        list.add(3);
    }
}

As a result, Exception in thread "main" is thrown
java.lang.UnsupportedOperationException

Threw an exception that does not support this method. Why? Let's take a look at arrays Source code of aslist() method:

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

An ArrayList is returned. Why can't you add it successfully?

The truth is that this ArrayList is not another ArrayList. It has the same name as our commonly used ArrayList. This ArrayList is only an internal class of the Arrays object. There is no add() method in it, so an error will be reported when adding.

Isn't that obvious? The list interface is implemented. Why not implement the add() method?

In fact, the author deliberately designed this way. In addition to not implementing the add() method, the author has not implemented the modification methods such as addAll(), remove(), clear(). The purpose is not to allow users to modify after creation. What's the use of such a collection?

In fact, it is useful in some immutable scenarios, such as creating a closed order status set:

List<String> list = Arrays.asList("Failure", "Cancelled","Completed");

Generally, this kind of collection will not change, and it is not allowed to be modified during use to avoid errors.

7. Summary

Every time you step on a pit, there is at least one online problem record behind it. These summaries are obtained from lessons, not only yourself, but also others. How can we avoid similar problems in future development?

  • From the perspective of users, write detailed unit tests, print necessary logs, and track code execution results
  • From the perspective of the creator, explore the architecture design and source code implementation of the framework, and understand the author's intention

Added by hkucsis on Tue, 18 Jan 2022 16:34:09 +0200