[Java] Handling null or missing data in Java

This article is for learning reference only!

Related tutorial address:

https://juejin.cn/post/7234924083842154556

https://cloud.tencent.com/developer/article/1107739?areaSource=106005.3

https://www.developer.com/java/null-data-java/

insert image description here

Representing something as blank or absent is always a problem in programming. For example, there is no item in the bag, which simply means that the bag is empty or that there is nothing in the bag. But how does one signal that something is missing from the computer's memory? For example, an object declared in memory contains some value (it doesn't matter whether the variable is initialized or not), even though it might not have any meaning in the context - this is called garbage value . Programmers can throw it away at best, but the point is that the declared object is not null. We can initialize it by a value or put a null . However, this still has some value; even being empty is something that doesn't represent anything. In this programming tutorial, we analyzed the case of missing data and null to see what Java has to offer in dealing with this problem.

What is null in Java?

The idea that there is no data in a computer is just a conceptual idea; the internal representation is actually the opposite of it. We can relate this to set theory, which defines an empty set with cardinality 0 . However, in the actual expression, it uses a symbol called null to represent emptiness. Therefore, if we ask the question "what does the empty set contain?", one possible answer is null , that is, nothing or is empty. However, in software development, we know that null is also a value.

Typically, the value 0 , or all bits in memory that are 0 , is used to represent a constant, whose name is null . Unlike other variables or constants, null means that there is no value associated with the name, which is represented as a built-in constant, which contains a value of 0.

A piece of data is actually represented as a reference to it. So, in order to represent something in the absence of data, developers have to invent something that represents nothing. So null (called nil in Go - maybe because they figured out that nil is one character less than null , and fewer are better) is chosen. This is what we call a null pointer . Therefore, we can see that null is both a pointer and a value. In Java, some objects (static variables and instance variables) are created with null by default , but can be changed to point to values ​​later.

It is worth mentioning here that null as a reference in programming was invented by Tony Hoare when he designed ALGOL in 1965. Later in his life, he regretted that it was a multibillion-dollar mistake , saying:

I call it my billion dollar mistake. This was the invention of the null reference in 1965. At the time, I was designing the first comprehensive type system referenced in an object-oriented language (ALGOL W). My goal is to make sure that all references are used absolutely safe, with checks performed automatically by the compiler. But I can't resist the temptation to put in a null reference, just because it's so easy to do. This has resulted in countless bugs, bugs, and system crashes that have probably caused billions of dollars in pain and loss over the past forty years.

This seemingly innocuous thing named null has caused some serious trouble over the years. However, perhaps the importance of null cannot be completely ignored in programming . This is why many later compiler creators thought it wise to preserve the legacy. However, Java 8 and later try to provide a type called Optional that directly handles some of the problems associated with using null .

Problems with null pointers in Java

NullPointerException is a common error that every Java programmer encounters frequently**. This error is thrown when we try to dereference an identifier that doesn't point to anything - it just means we expected to fetch some data, but the data is missing. The identifier we are trying to access points to null**.

Here is a code example of how we throw a NullPointerException error in Java :

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Object obj = null;
        System.out.println(obj.toString());
    }
}

Running this code in an integrated development environment (IDE) or code editor produces the following output:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Object.toString()" because "obj" is null
	at Main.main(Main.java:4)

Often in programming, the best way to avoid problems is to know how to create them. Now, while null references are well known to be avoided , the Java API still makes heavy use of null as a valid reference. One such example is as follows. The documentation of the Socket class constructor in the java.net package is as follows:

public Socket( InetAddress address, int port, InetAddress localAddr,             int localPort ) throws IOException

This piece of Java code:

  • Creates a socket and connects it to the specified remote address on the specified remote port. The Socket will also **bind()** to the provided local address and port.
  • If the specified local address is null , it is equivalent to specifying the address as an AnyLocal address (see InetAddress.isAnyLocalAddress() ).
  • A local port number of zero will cause the system to choose a free port during a bind operation.
  • If there is a security manager, its checkConnect method is called with the host address and port as parameters. This may result in a SecurityException .

According to the Java documentation, the highlighted point clearly shows that a null reference is used as a valid parameter. This null is harmless here and is used as a sentinel value to indicate that something is missing (here in case of missing port value in socket). So we can see that null is not completely avoided, although it can be dangerous at times. There are many examples of this in Java.

How to handle missing data in Java

A perfect programmer will always write perfect code and actually have no problem with null . However, for those of us who are fallible and need some sort of safer alternative to express the absence of something without resorting to innovative uses of null, we need some support. So Java introduced a type (a class called Optional ) that handles absent values ​​that don't happen due to errors in a more decent way.

Now, before discussing any code samples, let's take a look at the following excerpt from the Java API documentation:

public final class Optional
extends Object

This excerpt shows:

  • A container object, which may or may not contain non-null values. isPresent() will return true if the value is present , and **get()** will return the value.
  • Other methods are also provided that depend on the presence of the contained value, such as orElse() (returns the default value if the value is not present) and ifPresent() (executes the code block if the value is present).
  • This is a value-based lesson; using identity-sensitive operations (including reference equality ( == ), identity hashcodes, or synchronization) on Optional instances may have unpredictable results and developers should avoid.

In fact, there are many optional classes in Java, such as Optional , OptionalDouble , OptionalInt, and OptionalLong— all of which handle situations where the developer is not sure whether a value exists or not. Before the introduction of these classes in Java 8, it was customary for programmers to use the null value to indicate the absence of a value. Hence, the bug called NullPointerException is a common occurrence when we intentionally (or not) try to dereference a null reference ; a workaround is to check for null frequently to avoid generating an exception.

These lessons provide better strategies for dealing with the situation. Note that all optional classes are value-based, so they are immutable and have various restrictions, such as not using instances for synchronization and avoiding any use of reference equality. In the next section, we will pay special attention to the Optional class. Other optional classes function similarly.

T in the Optional class represents the type of stored value, which can be any value of type T. It may also be empty. Although the Optional class defines several methods, it does not define any constructor**. Developers can determine whether a value exists, get the value if it exists, get the default value if it doesn't exist, or construct an optional value**. Check the Java documentation for details on the functions available for these classes.

How to use Optional in Java

The following code example shows how to gracefully handle objects returning null or missing elements in Java. The Optional class acts as a wrapper for objects that may not exist:

package org.app;

public class Employee {
    
    
    private int id;
    private String name;
    private String email;

    public Employee(int id, String name, String email) {
    
    
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public String getEmail() {
    
    
        return email;
    }

    public void setEmail(String email) {
    
    
        this.email = email;
    }

    @Override
    public String toString() {
    
    
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}




package org.app;

import java.util.HashMap;
import java.util.Optional;

public class Main {
    
    
    private HashMap <Integer,Employee>db = new HashMap<>();
    public Main() {
    
    
        db.put(101, new Employee(101, "Pravin Pal", "[email protected]"));
        db.put(102, new Employee(102, "Tuhin Shah", "[email protected]"));
        db.put(103, new Employee(103, "Pankaj Jain", "[email protected]"));
        db.put(104, new Employee(104, "Anu Sharma", "[email protected]"));
        db.put(105, new Employee(105, "Bishnu Prasad", "[email protected]"));
        db.put(106, null);
        db.put(107, null);
    }

    public Optional findEmployeeById(int id){
    
    
         return Optional.ofNullable(db.get(id));
    }

    public Employee findEmployeeById2(int id){
    
    
        return db.get(id);
    }

    public static void main(String[] args) {
    
    
        Main m = new Main();
        Optional opt = m.findEmployeeById(108);
        opt.ifPresent(emp->{
    
    
            System.out.println(emp.toString());
        });

        if(opt.isPresent()){
    
    
            System.out.println(opt.get().toString());
        } else {
    
    
            System.out.println("Optional is empty.");
        }

        System.out.println(m.findEmployeeById2(106));
    }
}

Some key functions of the Optional class are isPresent() and get() . The isPresent() function determines whether the value is present. The function returns boolean true if the value exists , otherwise returns false .

Existing values ​​can be retrieved using the **get() function. However, if the get() function is called and it has no value, a NoSuchElementException will be thrown. Ideally, always check for the presence of a value using the ifPresent()** function before calling the get() function.

END

If there's anything you can't programmatically eliminate, but remind everyone to use, it's null . In databases, when storing values, it is recommended to avoid storing null values ​​in tables . A database table that is not properly normalized may have too many null values. In general, it's not very well defined what it means for a value to be missing in a calculation. Anyway, using the Optional class in Java handles issues related to nulls to some extent.

Guess you like

Origin blog.csdn.net/m0_47015897/article/details/131416886