The five most common errors in Java are java errors.

Source: Internet
Author: User
Tags stream api concurrentmodificationexception google guava

The five most common errors in Java are java errors.

[Editor's note] developers often encounter various inexplicable errors during programming. Recently, Sushil Das listed five common errors in Java Development On Geek On Java 」.

The following is a translation:

1. Excessive use of Null

It is a best practice to avoid over-using null values. For example, it is better to let the method return an empty array or collection instead of a null value, because this can prevent the program from throwing NullPointerException. The following code snippet obtains a set from another method:

</>List<String> accountIds = person.getAccountIds();for (String accountId : accountIds) {    processAccount(accountId);}

If a person does not have an account, getAccountIds () returns null, and the program throws an NullPointerException. Therefore, we need to add an empty check to solve this problem. If the returned null value is replaced with an empty list, NullPointerException will not appear. Besides, because we no longer need to check the variable accountId, the code will become more concise.

When you want to avoid null values, different scenarios may adopt different approaches. One method is to use the Optional type, which can be either an empty object or some value encapsulation.

</>Optional<String> optionalString = Optional.ofNullable(nullableString);if(optionalString.isPresent()) {    System.out.println(optionalString.get());}

In fact, Java 8 provides a more concise method:

</>Optional<String> optionalString = Optional.ofNullable(nullableString);optionalString.ifPresent(System.out::println);

Java supports the Optional type since Java 8, but it is well known in the world of functional programming. Previously, it was used in earlier versions of Google Guava for Java.

2. Ignore exceptions

We often ignore exceptions. However, for beginners and experienced Java programmers, the best practice is to deal with them. Exception throws are usually purposeful, so you need to record the events that cause exceptions in most cases. Don't underestimate it. If necessary, you can throw it again, display the error information to the user in a dialog box, or record the error information in the log. At least, to let other developers know the cause and effect, you should explain why this exception was not handled.

</>selfie = person.shootASelfie();try {    selfie.show();} catch (NullPointerException e) {    // Maybe, invisible man. Who cares, anyway?}

An easy way to emphasize that an exception is not important is to use this information as the variable name of the exception, as shown in the following code:

</>try { selfie.delete(); } catch (NullPointerException unimportant) {  }
3. An error occurred while modifying the concurrency.

This exception occurs when the set object is modified and the content in the set is not updated using the method provided by the iterator object. For example, there is an hats list and you want to delete all values containing the ear flaps:

</>List<IHat> hats = new ArrayList<>();hats.add(new Ushanka()); // that one has ear flapshats.add(new Fedora());hats.add(new Sombrero());for (IHat hat : hats) {    if (hat.hasEarFlaps()) {        hats.remove(hat);    }}

If you run this code, ConcurrentModificationException is thrown because the code traverses this set and modifies it. When multiple processes act on the same list, when one of the processes traverses the list, another process tries to modify the list content. The same exception may also occur.

It is very common to modify the set content concurrently in multiple threads. Therefore, you need to use common methods in concurrent programming, such as synchronization locks and special sets for concurrent modifications. There is a slight difference between Java and multithreading in solving this problem.

Collect objects and delete them in another loop

The direct solution is to put the hats with ear flaps into a list, and then delete it in another loop. However, this requires an additional set to store the hats to be deleted.

</>List<IHat> hatsToRemove = new LinkedList<>();for (IHat hat : hats) {    if (hat.hasEarFlaps()) {        hatsToRemove.add(hat);    }}for (IHat hat : hatsToRemove) {    hats.remove(hat);}

UseIterator.removeMethod

This method is simpler and does not need to create additional sets:

</>Iterator<IHat> hatIterator = hats.iterator();while (hatIterator.hasNext()) {    IHat hat = hatIterator.next();    if (hat.hasEarFlaps()) {        hatIterator.remove();    }}

UseListIteratorMethod

When the set to be modified implements the List interface, list iterator is a very suitable choice. The iterator that implements the ListIterator interface not only supports the delete operation, but also supportsaddAndsetOperation. The ListIterator interface implements the Iterator interface.IteratorOfremoveThe method is similar. The only difference is the hat iterator type and the way we get iterator -- UselistIterator()Method. The following snippet shows how to useListIterator.removeAndListIterator.addMethod to replace hat with ear flaps with sombreros.

</>IHat sombrero = new Sombrero();ListIterator<IHat> hatIterator = hats.listIterator();while (hatIterator.hasNext()) {    IHat hat = hatIterator.next();    if (hat.hasEarFlaps()) {        hatIterator.remove();        hatIterator.add(sombrero);    }}

Use ListIterator to callremoveAndaddThe method can be replaced by calling only onesetMethod:

</>IHat sombrero = new Sombrero();ListIterator<IHat> hatIterator = hats.listIterator();while (hatIterator.hasNext()) {    IHat hat = hatIterator.next();    if (hat.hasEarFlaps()) {        hatIterator.set(sombrero); // set instead of remove and add    }}

In Java 8streamMethod

In Java 8, developers can convert a collection to stream and filter the stream based on some conditions. This example describes how stream api filters hats and avoidsConcurrentModificationException.
Hats = hats. stream (). filter (hat->! Hat. hasEarFlaps ()))

</> .collect(Collectors.toCollection(ArrayList::new));

Collectors.toCollectionThe method creates a new ArrayList, which stores the filtered hats values. If the filter condition filters out a large number of entries, a large ArrayList is generated. Therefore, use it with caution.

In Java 8List.removeIfMethod

You can use another more concise and clear method in Java 8 --removeIfMethod:

</>hats.removeIf(IHat::hasEarFlaps);

At the underlying layer, it usesIterator.removeTo complete this operation.

Use a special set

If you decide to useCopyOnWriteArrayListInsteadArrayListThen there will be no problems. BecauseCopyOnWriteArrayListProvides the modification method (such as set, add, remove). Instead of changing the original set array, it creates a new version. This allows you to traverse the original version set and modify it without throwingConcurrentModificationExceptionException. The disadvantages of this set are also obvious-a new set is generated for each modification.

There are other sets suitable for different scenarios, suchCopyOnWriteSetAndConcurrentHashMap.

Another error that may occur when a set is modified concurrently is that a stream is created from a collection and the back-end collection is modified when the stream is traversed. The general rule for stream is to avoid modifying the back-end collection when querying stream. The following example shows how to process stream correctly:

</>List<IHat> filteredHats = hats.stream().peek(hat -> {    if (hat.hasEarFlaps()) {        hats.remove(hat);    }}).collect(Collectors.toCollection(ArrayList::new));

peekMethod to collect all the elements and perform the specified action on each element. Here, the action is to try to delete data from a basic list, which is obviously incorrect. To avoid such operations, you can try some methods described above.

4. Default

Sometimes, for better collaboration, Code provided by a standard library or a third party must comply with common dependency standards. For examplehashCodeAndequalsTo ensure a series of collection classes in the Java Collection framework and otherhashCodeAndequalsThe method class works normally. Non-compliance does not produce exceptions or corrupt code compilation errors; it is very sinister because it may change application behavior at any time without any danger.

The error code may sneak into the production environment, causing a lot of adverse effects. This includes poor UI experience, incorrect data reports, poor application performance, data loss, or more. Fortunately, these catastrophic errors won't happen frequently. The hashCode and equals conventions have been mentioned before. They may occur in the following scenarios: A set depends on hashing or comparing objects, just like HashMap and HashSet. In short, this Convention has two principles:

  • If the two objects are the same, the hash code must be the same.
  • If two objects have the same hash code, they may be equal or not equal.

If you attempt to retrieve data from a hashmap, the first criterion of the conventions will be broken. The second criterion means having the samehash codeObjects are not necessarily equal.

The following describes the consequences of undermining the first criterion:

</>public static class Boat {    private String name;    Boat(String name) {        this.name = name;    }    @Override    public boolean equals(Object o) {        if (this == o) return 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 is rewritten.equalsAndhashCodeMethod. However, it breaks the Convention because hashCode returns a random value for the same object in each call. The following code may not find a name in hashsetEnterpriseAlthough 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"));    System.out.printf("We have a boat named 'Enterprise' : %b\n", boats.contains(new Boat("Enterprise")));}

Another example of the convention isfinalizeMethod. Here is a reference to the official Java documentation on its function description:

finalizeThe General Convention is: when the JavaTM Virtual Machine determines that no thread can access the specified object in any way, this method will be called, and then this object can only be in a certain other (to be terminated) an object or a class is ended as a result of an action.finalizeMethods have multiple functions, including re-enabling this object to be available to other threads; howeverfinalizeThe main purpose is to clear the object before it can be undone. For examplefinalizeMethod can execute explicit I/O transactions to interrupt the connection before the object is permanently discarded.

You can decide to usefinalizeMethod to release resources, but this usage is very bad. Because it is called during garbage collection, and the GC time is not determinedfinalizeThe called time cannot be guaranteed.

5. Use the original type instead of parameterized

According to the description in the Java document, the original type is either non-parameterized or non-static member of the class R (and also non-inherited R parent class or parent interface. Before Java generics are introduced, there is no replacement type for the original type. Java has supported generic programming since version 1.5, which is undoubtedly an important feature improvement. However, due to backward compatibility, there is a trap that may damage the entire type system. Focus on the following example:

</>List listOfNumbers = new ArrayList();listOfNumbers.add(10);listOfNumbers.add("Twenty");listOfNumbers.forEach(n -> System.out.println((int) n * 2));

A list composed of numbers is defined as the original ArrayList. Because it does not specify a type parameter, you can add any object to it. However, the last line maps the contained elements to the int type and multiplied by 2 to print the data after doubling to the standard output.

This Code does not cause errors during compilation, but once it is run, it throws a runtime error because it attempts to map the character type to an integer. Obviously, if necessary information is hidden, the type system cannot help write security code.

To solve this problem, you need to specify a specific type for the objects stored in the Set:

</>List<Integer> listOfNumbers = new ArrayList<>();listOfNumbers.add(10);listOfNumbers.add("Twenty");listOfNumbers.forEach(n -> System.out.println((int) n * 2));

The only difference from the previous code is the line that defines the set:

</>List<Integer> listOfNumbers = new ArrayList<>();

The modified code compilation cannot be passed because it attempts to add a string to the set that only expects to store the integer. The compiler will display an error message and point to an attempt to addTwentyThe line of the character. Parameterized generic type is a good idea. In this way, the compiler can check all possible types, thus greatly reducing the chance of running exceptions caused by inconsistent types.

Original article: Top 5 Common Mistake in Java

This article is compiled by OneAPM engineers. OneAPM is an emerging leader in the application performance management field. It helps enterprise users and developers easily achieve slow real-time crawling of program code and SQL statements. For more technical articles, visit the official OneAPM blog.

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.