Java functional development of optional NULL pointer processing _java

Source: Internet
Author: User
Tags lowercase java se

Summary

Spare time to learn groovy and Scala running on the JVM, discovering that their handling of NULL is much more discreet than earlier versions of Java. In Java8, Optional gives a very elegant solution for null processing of functional programming. This article will illustrate the long term Java's crappy processing of NULL, and then introduce the use of optional to implement Java functional programming.

The years that haunt us are null

In the Java River, there is a legend: until you really understand the null pointer exception, can be counted as a qualified Java developer. In our career of Java code characters, we encounter various kinds of NULL processing every day, and code like the following may be written on a daily basis:

if (null!= obj1) {
 if (null!= obje2) {
   //do Something
 }
}

A little bit of an eye-opener. Javaer to do some of the slightly forced things, to find a way to judge Null:

Boolean checknotnull (Object obj) {return
 null = = obj. False:true 
}

void Do () {
 if (Checknotnull (obj1)) {
   if (Checknotnull (obj2)) {
    //do something
   }
}}

Then the question goes: If a null represents an empty string, what does "" mean?

Then inertia thought tells us, "" and null is not all empty string code? Simply put the judgment on the null value to upgrade a bit:

Boolean Checknotblank (Object obj) {return
 null!= obj &&! "". Equals (obj)? True:false; 
}
void Do () {
 if (Checknotblank (obj1)) {
   if (Checknotnull (obj2)) {
    //do something
   }
}}

If you have time, you can look at the current project or your own past code, exactly how many and similar to the above code.

I wonder if you've seriously thought about a question: what does a null mean?

    1. Plain understanding--null Of course means "value does not exist".
    2. A bit of an understanding of memory management--null indicates that the memory is not allocated and the pointer points to an empty address.
    3. A slightly more thorough understanding--null may indicate a problem with a local process, or it may indicate that a value does not exist.
    4. The knowledge of the battered million-ouch, another nullpointerexception anomaly, it seems I have to add an if (null!= value).

Recall how many java.lang.NullPointerException anomalies have we encountered in the previous code career? NullPointerException as a runtimeexception level exception does not show capture, and if handled carelessly we often see various exception stack outputs caused by nullpointerexception in the production log. And based on this exception stack information we simply cannot locate the cause of the problem, because it is not the place where the nullpointerexception is thrown. We have to go deeper to find out where this null is generated, and this time the log is often unable to track.

Sometimes it's even more tragic that the places that produce null values are often not in our own project code. There is a more embarrassing fact that when we invoke a variety of third-party interfaces, it is not certain that an interface will return a null in the event of a coincidence ...

Back to the previous cognitive problem of NULL. Many Javaer think that null means "nothing" or "value does not exist." According to this inertial thinking our code logic is: You call my interface, according to the parameters you give me the corresponding "value", if this condition can not find the corresponding "value", then of course I return a null to you that there is no "anything". Let's look at the following code, written in a very traditional and standard Java coding style:

Class myentity{
  int id;
  String name;
  String GetName () {return
   name;
  }
}

Main public
class test{public
  static void Main (string[] args) 
    final myentity myentity = getmyentity (fals e);
    System.out.println (Myentity.getname ());
  }

  Private Getmyentity (Boolean issuc) {
    if (issuc) {return
      new myentity ();
    } else{return
      null;}}


This piece of code is very simple, the day-to-day business code is certainly more complex than this, but in fact, our large number of Java coding is written in this routine, people who understand the goods can be seen in the end will definitely throw nullpointerexception. But when we write business code, we rarely think about dealing with this possible null (perhaps the API document has already been written clearly that it will return null in some cases, but are you sure you'll be able to read the API documents carefully before you start writing code?). Until we get to a certain stage of the test and suddenly jump out of a nullpointerexception anomaly, we realize that we have to add a judgment like this to fix the null value that might be returned.

Main public
class test{public
  static void Main (string[] args) 
    final myentity myentity = Getmyentity (False );
    if (null!= myentity) {
      System.out.println (Myentity.getname ());
    } else{
      System.out.println ("ERROR");}}

Think about it all these years, do we all do this? If some null-induced problems are not discovered until the test phase, then the question now is-how much of the null is not properly handled in the elegant, hierarchical business code?

With regard to null processing attitude, often can see a project mature and rigorous degree. For example, guava early in the JDK1.6 before the elegant method of NULL treatment, can be seen deep foundation.

Ghostly null hinders our progress.

If you are a javaer focused on traditional object-oriented development, you may be accustomed to the problems of NULL. But as early as many years ago, the great God said null this thing is a pit.

Tony Hall (Don't you know who the goods are?) Check it yourself) once said: "I call it my billion-dollar mistake." It is the invention of the null reference in 1965. I couldn ' t resist the temptation to put in a null reference, simply because it is so easy to implement. (The effect is: "Brother will invent null" is called a priceless mistake.) Because in the 1965 of the computer's wild age, the empty reference is too easy to achieve, so that brother can not resist the temptation to invent the empty pointer this thing. ”)。

Then we'll see what the problem is with NULL.

Look at the following code:

String address = Person.getcountry (). Getprovince (). getcity ();

If you've played some functional languages (Haskell, Erlang, Clojure, Scala, etc.), this is a natural way to write. Java, of course, can also achieve the above way of writing.

But in order to handle all the possible null exceptions satisfactorily, we have to change this elegant functional programming paradigm to this:

if (person!= null) {
 Country Country = Person.getcountry ();
 if (country!= null) {
 Province province = country.getprovince ();
 if (province!= null) {Address
  = Province.getcity ();}}}

In an instant, the JAVA8 functional programming was back 10 years ago. Such a layer of nesting judgment, increase the amount of code and not elegant or trivial. It is more likely that, for most of the time, people will forget to judge the possible null, even for the elderly who have written years of code.

The above layer of nested null processing, is also the traditional Java has long been criticized place. If you use the early version of Java as your initiation language, this get->if Null->return will affect you for a long time (remember in a foreign community, this is called: Entity development).

Implementation of Java functional programming with optional

Well, all sorts of problems, and then we can go into the new era.

Before the introduction of the Java SE 8 version, other similar functional development languages already had their own solutions. Here's the code for Groovy:

String Version = computer?. Getsoundcard ()? Getusb ()? GetVersion (): "Unkonwn";

Haskell handles null values with a Maybe type class identity. Scala, which is known as the multi-paradigm development language, provides a option[t that maybe almost the meaning of the word, and is used to package null.

Java8 introduced java.util.optional<t> to handle the null problem of functional programming,optional<t> is similar to Haskell, Scala, but slightly different. Let's take a look at the following examples of Java code:

public class Test {public
 static void Main (string[] args) {
 final String text = "Hallo world!";
 Optional.ofnullable (text)//display creates a Optional shell
   . Map (test::p rint).
  Map (test::p rint)
  . Ifpresent ( System.out::p rintln);

 Optional.ofnullable (text)
  . Map (S->{ 
  System.out.println (s);
  Return s.substring (6);
  })
  . Map (s-> null)//returns null
  . Ifpresent (system.out::p rintln);
 }
 String
 private static string print (String str) {
 System.out.println (str) after printing and intercepting str[5];
 Return str.substring (6);
 }
}
Consol output
//num1:hallo world!
num2:world!
NUM3:
//num4:hallo world!

(You can run the above code copy into your IDE if you have to install JDK8.) )

The above code creates 2 optional that are essentially the same, using optional as a shell for string truncation. When a null value is encountered during processing, the processing is no longer resumed. We can find that after the S->null in the second optional, subsequent ifpresent no longer execute.

Note that the//num3 of the output is observed: This indicates that a "" character was exported, not a null.

Optional provides a rich interface to handle various situations, such as modifying code to:

public class Test {public
 static void Main (string[] args) {
 final String text = "Hallo world!";
 System.out.println (lowercase (text)),//method one
 lowercase (null, System.out::p rintln);/Method Two
 }

 private static string lowercase (string str) {return
 optional.ofnullable (str). Map (S-> s.tolowercase ()). Map (s-> S.replace ("World", "Java")). OrElse ("NaN");

 private static void lowercase (String str, consumer<string> Consumer) {
 consumer.accept (lowercase (str));
}
Output
//hallo java!
NaN

In this way, we can dynamically process a string, and if the value is found to be null at any time, use OrElse to return the preset default "NaN".

In general, we can wrap any data structure in optional and then process it in a functional way without having to worry about null that might occur at any time.

Let's look at the previous mentioned Person.getcountry (). Getprovince (). Getcity () How to deal with a bunch of if.

The first approach is to not change the previous entity:

Import java.util.Optional;
public class Test {public
 static void Main (string[] args) {
 System.out.println (the new person ( ). Map (x->x.country). Map (X->X.PROVINEC). Map (x->x.city). Map (
  x->x.name)
  . OrElse ("Unkonwn"));
 }
Class Person {
 Country Country;
}
Class Country {
 province Provinec;
}
Class Province {City City
 ;
}
Class City {
 String name;
}

Here the optional is used as the shell to return each time, and if a null is returned from a certain position, the "UNKONWN" is directly obtained.

The second approach is to define all values in optional:

Import java.util.Optional;
The public class Test {public
 static void Main (string[] args) {
 System.out.println () is new person ()
  . Country.flatmap (x-> X.provinec). Flatmap (province::getcity). Flatmap (
  x-> x.name).
  OrElse (" Unkonwn "));
 }
Class Person {
 optional<country> Country = Optional.empty ();
}
Class Country {
 optional<province> Provinec;
}
Class Province {
 optional<city> city;
 Optional<city> getcity () {//For:: Return city
 ;
 }
}
Class City {
 optional<string> name;
}

The first approach can be smoothed and integrated with existing JavaBean, entity, or poja without changing anything, and can be more easily integrated into Third-party interfaces (such as spring's beans). The proposal is still to use the first kind of optional mainly, after all, not everyone in the team can understand each get/set with a optional intention.

Optional also provides a filter method for filtering data (actually JAVA8 stream-style interfaces provide the filter method). For example, in the past we judged the value to exist and dealt with accordingly:

if (province!= null) {City City
 = Province.getcity ();
 if (null!= city && "Guangzhou". Equals (City.getname ()) {
  System.out.println (City.getname ());
 } else{
  System.out.println ("Unkonwn");
 }

Now we can change it to

Optional.ofnullable (province)
  . Map (x->x.city)
  . Filter (x-> "Guangzhou". Equals (X.getname ()))
  . Map (X->x.name)
  . OrElse ("unkonw");

To this end, the use of optional to introduce functional programming is complete. Optional in addition to the above mentioned methods, there are orelseget, Orelsethrow and so on according to the more needs of the method provided. Orelseget throws a null pointer exception because of a null value, and Orelsethrow throws a consumer custom exception when null occurs. You can view the API documentation to find out the details of all the methods.

Written at the end of the

Optional is just the tip of Java functional programming, it needs to combine the features of lambda, stream, and Funcationinterface to really understand the utility of Java8 functional programming. Originally also want to introduce some optional source code and operation principle, but the optional itself is very little, API interface is not much, think carefully also have nothing to say to omit.

Optional although elegant, but personally feel some efficiency problems, but not to verify. If anyone has the exact data, please let me know.

I am not a "supporter of functional Programming". From the perspective of Team managers, the cost of using and team interaction is higher for each increase in learning difficulty. Like in legend, Lisp can be 30 times times less than C + +, development is more efficient, but if a domestic conventional IT companies really use Lisp to do projects, where to go, how much money to spend on these Lisp buddies ah?

But I am very encouraged to learn and understand the idea of functional programming. Java8 is a good opportunity, especially in the past, in the Java language, and the developers who are not sure what the JAVA8 will bring. To encourage the introduction of new JAVA8 features into the current project, a long-term team and an old programming language need to constantly inject new vitality, otherwise.

The above is the Java Optional Data collation, follow-up continue to supplement the relevant information, thank you for your support of this site!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.