The following is displayed to everyone for each misunderstanding.
1. NULL's excessive use
Avoiding excessive use of NULL is the best practice. For example, a better approach is to make the method return to the empty Array or Collection instead of the NULL value, because this can prevent the program from throwing NullPointerexception. The following code fragment will get a collection from another method:
List <string> accountids = Person.getaccountids (); for (string accountid: accountids) {Processaccount (accountid);}
When a figure does not have an account, getaccountids () will return the Null value, and the program will throw out NullPointerexception exception. Therefore, it is necessary to join the air check to solve this problem. If you replace the returned Null value with an empty list, then nullpointerexception will not appear. Moreover, because we no longer need to take a short check of the variable accountid, the code will become more concise.
When you want to avoid NULL values, different scenarios may take different practices. One method is to use the Optional type, which can be both an empty object or a package of some values.
Optional <string> OptionalString = optional.ofnullable (nulledString); if (optionalstring.ispRersent ()) {system.out.println (optionalstring.get ()); }
In fact, Java8 provides a more concise way:
Optional <string> OptionalString = OPTIONAL.OFNULLABLE (nulLialString); optionalstring.ifpreennt (system.out :: println);
Java has supported the Optional type from the Java8 version, but it has been widely known in the functional programming world. Before that, it was used in the early version of Java in Google Guava.
2. Ignore abnormalities
We often ignore abnormalities. However, the best practice is to deal with them for beginners and experienced Java programmers. The abnormal throwing is usually purposeful, so in most cases, it is necessary to record events that cause abnormalities. Don't underestimate this matter. If necessary, you can re -throw it and display the error message to the user or record the error message in a dialog box. At least, in order to let other developers know the cause and effect, you should explain why this abnormalities have not been dealt with.
Selfie = Person.shootaselfie (); Try {Selfie.show ();} Catch (NullpoIntterexception E) {// Maybe, Invisible Man. Who Cares, Anyway?}
A simple way to emphasize a certain unimportant is to use this information as an abnormal variable name, like this:
Copy code code as follows:
try {Selfie.delete ();} Catch (nullpoIntterexception unimportant) {}
3. Modify abnormalities concurrently
This abnormality occurs in the collection object, and at the same time does not use the method provided by the Iterator object to update the content in the collection. For example, there is a Hats list here, and you want to delete all the values containing Ear Flaps:
List <iHats = New ArrayList <> (); Hats.add (New USHANKA ()); // That One Has Ear Flaps Hats.add (New Fedora ())); for (ihat: Hats) {if (hat.hasearflaps ()) {hats.remove (hat);}}
If this code runs, ConcurrentModificationException will be thrown, because the code will modify it while traversing this collection. When multiple processes act on the same list, when one of the processes traverses the list, the other process tries to modify the list content, and the same abnormalities may also occur.
It is very common in multi -threaded concurrent modification collection content, so it is necessary to use the method commonly used in concurrent programming, such as synchronous locks, special sets for concurrent modification, and so on. Java solves this problem in a single thread and multi -threaded situation.
Collect objects and delete them in another cycle
The direct solution is to put HATS with Ear Flaps into a list, and then delete it with another cycle. However, this requires an additional set to store HATS to be deleted.
List <iHatstoremove = New LinkedList <> (); for (IHAT HATS) {if (Hat.hasearflaps ()) {Hatstoremove.add (HAT);} for (iHatstoremove) {Hats.Remov E (Hat);}
Use the Iterator.remove method
This method is simpler, and at the same time does not need to create an additional collection:
Iterator <iHatitrator = Hats.Iterator (); While (hatientRator.hasnext ()) {iHat = Hatitors.next (); if (hat.hasearflaps ()) {hatt interior.remove ();}}}}}
The method of using listiterator
When the collection of the collection of the List interface is implemented, the list iterator is a very suitable choice. ITERATOR that implements the Listitoror interface not only supports deletion operations, but also supports ADD and SET operations. The listotrator interface implements the ITERATOR interface, so this example looks similar to the Remove method of Iterator. The only difference is the type of Hat ITERATOR and we obtain the ITERATOR method -using the Listotrator () method. The following fragments show how to use the ListTerator.remove and Listotrator.add method to replace the Ear Flaps HAT with Som <OMBREROS.
IHAT SOMBRERO = New Sombrero (); Listitrator <iHatotrator = Hats.listitors (); While (Hatiterator.hasnext ()) {iHathaat = Hatiterator.next (); If (HAT.HASEARFLA ps ()) {Hattenrator.remove (); Hattenrator.add (sombrro);}}
Using listiterator, calling Remove and ADD method can be replaced to call only one set method:
IHAT SOMBRERO = New Sombrero (); Listitrator <iHatotrator = Hats.listitors (); While (Hatiterator.hasnext ()) {iHathaat = Hatiterator.next (); If (HAT.HASEARFLA ps ()) {hattrateor.set (sombrro); // Set Instead of Remove and Add}}}
Use the Stream method in Java 8
In Java8, developers can convert a collection into stream and filter Stream according to some conditions. This example tells how the Stream Api filter HATS and avoid the ConcurrenTModificationException. hats = hats.stream (). Filter ((Hat->! Hat.hasearflaps ())))))))))))
Copy code code as follows:
.Collect (Collectors.tocollection (ArrayList :: New));
The Collectors.Tocollection method will create a new ArrayList, which is responsible for storing the filtered HATS value. If the filtering conditions are filtered out a large number of entries, a large ArrayList will be generated here. Therefore, you need to use it with caution.
Use the list.removeif method in Java 8
You can use another more concise and clear method in Java 8 -Removeif Method:
Copy code code as follows:
Hats.removeif (iHat :: hasearflaps);
At the bottom, it uses Iterator.remove to complete this operation.
Use a special collection
If you decide to use CopyOnWritearrayList instead of ArrayList at the beginning, there will be no problem. Because CopyOnWriteArrayList provides modified methods (such as set, add, Remove), it will not change the original collection array, but creates a new modified version. This allows traversal to modify the original version, so that the ConcurrentModificationException is not thrown out. The disadvantages of this collection are also very obvious -a new collection is generated for each modification.
There are other sets suitable for different scenarios, such as CopyonWriteSet and ConcurrenThashMap.
Regarding another error that may occur during concurrent modifications, it creates a Stream from a collection. When traversing stream, it modifies the back -end collection. The general criterion for Stream is to avoid modifying the back -end collection when checking Stream. The next example will show how to properly handle the stream:
List <iHat> filedhats = hats.stream (). Peek (HAT-> {if (hat.hasearflaps ()) {Hats.remove (Hat);}}). )) ;;
The Peek method collects all elements and performs established actions for each element. Here, the action is to try to delete data from a basic list, which is obviously wrong. To avoid such operations, you can try some methods explained above.
4. Defense
Sometimes, in order to better collaborate, the code provided by the standard library or third party must comply with common dependencies. For example, it is necessary to comply with the joint agreement between HashCode and Equals to ensure that a series of collection classes in the Java collection framework and other classes using the HashCode and Equals methods can work normally. Do not comply with errors such as Exception or destroying code compilation; it is insidious because it may change application behavior at any time without dangerous prompts.
Error code may sneak into the production environment, causing a lot of adverse effects. This includes poor UI experience, wrong data reports, poor application performance, data loss or more. Fortunately, these catastrophic errors do not often occur. The HashCode and Equals have been mentioned before that the scene it appears may be: the collection depends on the target to compare the objects or compares, just like HashMap and HashSet. In simple terms, there are two criteria for this agreement:
If the two objects are equal, then the Hash Code must be equal.
If the two objects have the same Hash Code, they may be equal or different.
The first criterion for destruction, when you try to retrieve data from a HashMap, it will cause errors. The second criterion means that objects with the same Hash Code are not necessarily equal.
Let's take a look at the consequences of destroying the first criterion:
Public Static class boat {Private String name; Boat (String name) {this.Name = name;} @Override Public Boolean Equest (Object o) {if (this == o) turn true; if (o == null || getClass ()! = O.getClass ()) Return false; boat boat = (boat) o; Return! (name! = Null?! name.equals (boat.name): Boat.name! = Null); Override public int hashcode () {Return (int) (math.random () * 5000);}}
As you can see, the Boat class rewrite the Equals and HashCode methods. However, it destroyed the agreement because HashCode returned the random value for the same object for each call. The following code is likely to not find a Boat called Enterprise in HashSet, although in fact we have added this type of BOAT in advance:
Public static void main (string [] args) {set <boat> boats = new hashSet <> (); boats.add (new boat ("Enterprise"); ed ' Enterprise ': %B/N ", Boats.contains (New Boat (" Enterprise "));};}
Another agreement is the finalize method. Here is a reference to the official Java document on its functional description:
Finalize's conventional agreement is: When the Javatm virtual machine determines that any thread can no longer access the specified object in any way, this method will be called. Since then As a result of a certain behavior. The finalize method has multiple functions, including the use of this object to be available to other threads again; however, the main purpose of finalize is to perform clear operations before discarding objects irrevbleved. For example, the finalize method that indicates the input/output connection object can execute the explicit I/O transaction to interrupt the connection before the permanent discarded object.
You can decide to use the finalize method in a file processor to release resources, but this usage is bad. Because it is called during the garbage recycling and the time of GC is not sure, the time for Finalize will not be guaranteed.
5. Use the original type instead of parameterization
According to the Java document description: The original type is either non -parameterized, or a non -static member of RM (also non -inheritance of R parent or parent interface). Before the Java generic type was introduced, there was no primitive alternative type. Java has supported generic programming from version 1.5, and there is no doubt that this is an important function improvement. However, due to backward compatibility, there is a trap here that may destroy the entire type system. Strive the example:
ListOfnumbers = New ArrayList (); listofnumbers.add (10); Listofnumbers.add ("Twenty"); 2);
This is a list of numbers that is defined as the original ArrayList. Since it does not specify the type parameters, it can add any object to it. However, the last line maps the elements it contains to int type and multiplied by 2, printed out the data after double the data to the standard output.
This code will not make an error during compilation, but once it runs, it will throw an error when it is running, because it is trying to map the character type to plastic surgery. Obviously, if the necessary information is hidden, the type system will not help write a security code.
To solve this problem, you need to specify the specific type for the objects in the collection:
List <integer> listofnumbers = new arrayList <() (); listofnumbers.add (10); Listofnumbers.add ("Twenty"); n ((int) n * 2)) ;;
The only difference from the previous code is the line that defines the collection:
Copy code code as follows:
List <integer> listofnumbers = New ArrayList <();
The modified code compilation cannot be passed because it is trying to add a string to the collection of only expected storage plastic. The compiler will display an error message and point to the line that adds Twenty characters to the list. Parameterization generic type is a good idea. In this case, the compiler can check the possible types, so that the abnormal chance of runtime due to inconsistencies will be greatly reduced.
The main summary of the above five Java programmers often make mistakes, I hope everyone can like it.