There are online problems every year, but this year there are so many. Record a few painful steps on the line pit record, hope everyone to take history as a mirror.


1. The null pointer is abnormal due to automatic unpacking

public int getId(a) {
    Integer id = null;
    return id;
}
Copy the code

What happens if the above method is called? Id is an Integer, and the returned value of the method is an int, which is automatically converted into an Integer. Since id is null, NullPointerException is reported when the value is converted to an int.

Ali Java Development Manual, Clean Code Practices, and Effective Java all recommend that the method return type be as wrapper as possible, like Integer. There are entity classes, receiving front-end parameter classes, attributes in the response class to the front-end should be written as wrapper types to avoid unpacking errors.

2. The packaging type is judged equal by ==, resulting in incorrect judgment

Let’s take a look at the result:

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 is false}}Copy the code

Many people will wonder why the two output results are different.

When assigning a value to an Integer type, the integer.valueof () method is called

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);
}
Copy the code

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

== compares memory addresses, and different objects have different memory addresses, hence the above result.

Integer overrides equals() :

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

When you use the equals() method, you compare whether int values are equal.

So, when wrapping classes to determine equality, never use ==, always use equals().

3. The null pointer is abnormal due to the null parameter passed by the Switch

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");
                break;
            default:
                System.out.println("default"); }}}Copy the code

If you think it will print default, the code will actually throw a NullPointerException.

When the Switch compares two objects to be equal, name.hashcode () and name.equals() are called. Since name is null, NullPointerException is thrown as a result.

Therefore, before calling the switch method, make sure that the pass parameter is nulled.

4. Precision loss 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); }}Copy the code

You expect it to print 0.1, but it actually prints:

0.1000000000000000055511151231257827021181583404541015625
Copy the code

What? What is this whole bunch of stuff?

Why does this happen? The reason is that when we create an object with new BigDecimal(0.1), this constructor for BigDecimal is called:

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

Double (0.1); double (0.1); double (0.1); double (0.1);

What do you do when you need to create a BigDecimal type?

You can first convert a numeric value to a string type and then create a BigDecimal object like this:

BigDecimal bigDecimal = new BigDecimal(String.valueOf(0.1));
Copy the code

How does BigDecimal solve the precision loss problem?

The answer is that BigDecimal multiplies the value by a multiple of 10, removes the decimal place, converts it to a long, performs the operation, and finally divides the result by a multiple of 10.

5. Group The primary key is repeated during group, causing an exception

Can the following code be grouped successfully?

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 IDMap<Integer, User> userMap = users.stream() .collect(Collectors.toMap(User::getId, user -> user)); System.out.println(userMap); }}Copy the code

Results submitted to the Exception, the Exception in the thread “is the main” Java. Lang. An IllegalStateException: Duplicate key SteamTest. The User (id = 1, name = Tom)

The primary key conflicts, and the program does not know how to group the data by ID.

You can do that

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"));// The user group is grouped by id. If the primary key conflicts, 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); / / o {1: {" id ": 1," name ":" Tom "}, 2: {" id ": 2," name ":" Jerry "}}}}Copy the code

6. Exception of adding true and false ArrayList

Does the add() method below add successfully?

public class Test {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1.2);
        list.add(3); }}Copy the code

The result is thrown Exception, the Exception in the thread “is the main” Java. Lang. UnsupportedOperationException

An exception was thrown that does not support this method. Why? Arrays.aslist ()

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

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

ArrayList is just an inner class of Arrays objects that doesn’t implement the Add () method.

Isn’t that obvious? Implement the list interface, why not implement the add() method?

AddAll (), remove(), clear() and other modification methods have not been implemented. The purpose is not to let users modify the collection after creation. What is the use of such a collection?

It is useful in some immutable scenarios, such as the set of finished order states:

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

This kind of set will not change in general, and is not allowed to be modified in the process of use to avoid mistakes.

7. To summarize

For every pit, there is at least one online problem recorded behind it, which is a lesson learned, not only by myself, but also by others. How can we avoid similar problems in future development?

  • Write detailed unit tests, print necessary logs, and track code execution from the user’s perspective
  • Stand in the perspective of the creator, explore the framework design and source code implementation, understand the author’s intention

What other holes did you step in on the line?