I have been coding in Java 8 for a few years, both for new applications and migrating existing applications, and it felt like it was time to write about some "best practices" that I have found very useful. I personally don't like the term "best practices" because it implies a "one-size-fits-all" solution, and that's not how coding works - we need to discover for ourselves what solutions work. But I found some options in Java 8 code that can help us, let's take a look.
Optional is a seriously underrated feature and has the potential to remove a lot of NullPointerExceptions that plague us. This is particularly useful within code boundaries (either the API being used or the API being exposed) because it allows you and your calling code to reason about what to expect.
However, applying Optional without thought and design may result in affecting a large number of classes and may result in poorer readability. Here are some tips on how to use Optional effectively.
Optional should only be used for return types
…not parameters, nor fields. Fortunately, IntelliJ IDEA lets you turn on a check to see if you are following these recommendations.
Optional values should be handled where they are encountered. IntelliJ IDEA's suggestions will prevent Optional leaks in your code, so remember to handle Optional wherever you find it and act quickly.
Should not simply call get()
The function of Optional is to express that the value may be empty and allow you to deal with this situation. Therefore, be sure to check if there is a value before doing anything with it. Simply calling get() without first checking isPresent() may result in a null pointer at some point. Fortunately, IntelliJ IDEA also has checks to remind you of this.
## There may be a more elegant way
Of course isPresent() combined with get() would be great...
…but there are more elegant solutions. You can use orElse to give an alternative in case the value is null.
…Or you can use orElseGet to indicate which method to call if the value is empty. This seems to be the same as the example above, but the supplier method will only be called when needed, so if this is an expensive method, there will be better performance using a lambda.
Keep it short
Functional programmers will be more comfortable with longer lambda expressions, but those who have been immersed in Java for many years will find that keeping lambda expressions to just a few lines of code easier. You might even prefer to limit it to a single line of code, and you can easily refactor longer expressions into a method.
These may even become method references. Method references may feel a little unfamiliar at first, but there is actually value in sticking to method references because they aid readability in certain situations, which I will discuss later.
Explicit
Type information is missing from lambda expressions, so you might find it useful to include type information for parameters.
As you can see, this time it got pretty clumsy. So I prefer to give the parameters a useful name. Of course, whether you have done this or not, IntelliJ IDEA allows you to see the type information of the parameters.
Even the functional interface represented by lambda:
I think lambda expressions are a bit like generics - together with generics, we often use them (for example, adding type information to a List<> ), but preferably we could design a method or a class with a generic type (e.g. Person
But if you find yourself in this situation, here are some great tips.
IntelliJ IDEA can help you introduce functional parameters
This allows you to create a parameter where someone would pass a lambda instead of an Object. The benefit of this feature is that it shows that the existing functional interface matches the specification.
This results in...
Using existing functional interfaces
As developers become more familiar with Java 8 code, We can see what happens when using interfaces like Supplier and Consumer, and how creating a local ErrorMessageCreator (for example) can be confusing and wasteful. Take a look at this package to see what is already available.
[email protected]/* */
If you really need to create your own functional interface, then mark it with this comment. This may not seem to have much effect, but IntelliJ IDEA will tell you when your interface cannot match the exceptions used for functional interfaces. When you do not specify a method to override, it will flag:
When you specify too many methods, it will flag:
And if you apply it to a class instead of an interface, it will warn you:
Lambda expressions can be used with a single Abstract methods of any interface, but they cannot be used in abstract classes that conform to the same criteria. Seems illogical, but that's what it is.
The Stream API is another big feature of Java 8, and I think we really don’t know how much of a change it will make to the way we code. Here are some things I found helpful.
Queuing point operator
I personally prefer to queue my stream operations. Of course, you don't have to do this, as I found it helpful to do this: The ability to set breakpoints on any number of lambda expressions, but splitting to different lines would make it easier)
Comment out actions when I'm testing stuff
Easily insert peek( ) for debugging or testing
Also, in my opinion, it's neater. If we follow this pattern, we don't gain much in terms of reducing lines of code.
You may need to adjust the formatting settings to arrange the dot operators.
Using method references
Yes, it does take some time to get used to this strange syntax. However, if used correctly, it does increase readability. See:
Compare with the helper methods on the (relatively) new Objects class:
The latter The code is more explicit about which values are to be saved. IntelliJ IDEA will usually let you know when a lambda can be collapsed into a method reference.
When iterating over a collection, use the Streams API where feasible
…or new collection methods such as forEach. IntelliJ IDEA's suggestion for you is:
Generally, using the Streams API is more clear than the combination of loops and if statements. For example:
IntelliJ IDEA suggests that this can be refactored to:
The performance testing I did showed this Refactoring is surprising - it's not always predictable whether performance will stay the same, improve, or get worse. As always, if performance is key in an application, measure it before committing one style to another.
Use loops when iterating over arrays
However, using Java 8 doesn’t necessarily mean you have to use streams and new collection methods everywhere. IntelliJ IDEA will suggest converting to a stream, however, this does not mean you have to answer "yes" (remember that the check can be suppressed or turned off).
In particular, looping over small arrays of primitive types will almost certainly be used for better performance and probably (at least for Java developers new to streams) more readable.
# As with any technique, the rules are not hard and fast, but you should decide whether to use the Streams API as much as possible or still use loops for some operations. In short, be consistent.
Finally
The above is the content of the five development skills of Java 8. For more related content, please pay attention to the PHP Chinese website (m.sbmmt.com)!
-->