Some mistakes of Java basic knowledge

1, Use equals() correctly

Object's equals method is easy to throw null pointer exceptions. You should call equals with a constant or an object with a value.

String str = null;
if (str.equals("abcd")) {
  ...
} else {
  ...
}

If the variable str is null, a null pointer exception will be thrown. If there is no catch to catch and handle (we generally do not add a try on equals()), the program will stop running directly.

 

abcd".equals(str)

Write the constant in the front, "abcd"! =null, the result is false, no exception will be thrown.

But what about two variables?

 

The most recommended way is to use the tool class Objects (provided by JDK7)

Objects.equals(str,"abcd")

Even if two are variables and two are null, no exception will be thrown. If both are null, null==null, return true.

 

Some source codes of Objects are as follows:

public static boolean equals(Object a, Object b) {
        // If a==null At this time a.equals(b)It will not be executed to avoid null pointer exceptions.
        return (a == b) || (a != null && a.equals(b));
}

||Both & & and & & are open-circuit. If the front of | is true, the subsequent judgment will not be executed; if the front of & & is false, the subsequent judgment will not be executed.

 

equals() has a larger range of action than = =.

==Only data of the same type can be judged. For example, two data types are numerical (numerical type is classified as one type), all data types are strings, and all data types are User types. If two types are different, such as if(1 = = "1"), one is numeric type and the other is String, it can't be compiled.

equals() has no such requirement, no matter the two data types are different.

 

 

 

 

2. Comparison of basic type and packing type values

Two are basic types, or two are constants of basic types,

Or basic type, packing type (packing type belongs to reference type), or constant of basic type, basic type, or constant of packing type, basic type,

As long as the two are not all packing types, they can be compared. Whether they use = =, or equals(), they all use values for comparison.

 

If both of them are wrapper types, = = the addresses of the two objects are compared, which must be different.

There is a special case: if two integers are all integers, when the value is - 128 ~ 127, the created Integer object will be cached. When the value appears next time, the corresponding Integer object will be directly taken out of the cache.

Integer x = 3;  
Integer y = 3;  //Both are integers with the same value, and between - 128 and 127, a new Integer object will not be created, but directly points to the object pointed to by x, that is, x and y all point to the same Integer object in the heap
System.out.println(x == y); // Are reference types,==Compare by address, x,y The address of is the same, return true

 

Both of the wrapper types override equals(), and both of them use values for comparison. Both wrapper types should use equals() for comparison.

 

 

 

 

 

3. Use of BigDecimal

The way in which computers represent floating-point numbers will result in the loss of the precision of floating-point numbers. Computers cannot accurately represent floating-point numbers

        float a = 1.0f - 0.9f;
        float b = 0.9f - 0.8f;
        System.out.println(a);// 0.100000024
        System.out.println(b);// 0.099999964
        System.out.println(a==b);// false

Whether it's single precision or double precision, whether it's the basic type of floating-point number or the packing type of floating-point number, this problem exists.

Of course, double precision can represent more decimal places, which is more accurate than single precision, but after more decimal places, precision will still be lost.

 

Using the BigDecimal class to represent floating-point numbers solves the problem of floating-point precision loss because it stores values as strings.

BigDecimal a = new BigDecimal("1.0");  //Parameter is a string, passing value will lose precision
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);// 0.1
BigDecimal y = b.subtract(c);// 0.1
System.out.println(x.equals(y));// true 

The method provided in BigDecimal shall also be used for mathematical operation to ensure the accuracy is not lost.

The BigDecimal class overrides equals(), which compares two BigDecimal objects based on their values.

 

Size comparison:

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
System.out.println(a.compareTo(b));// 1

a.compareTo(b): Return - 1 for the previous small, 0 for equality, and 1 for the previous large.

 

Keep several decimal places:

BigDecimal m = new BigDecimal("1.255433");
BigDecimal n = m.setScale(3,BigDecimal.ROUND_HALF_DOWN); //The first parameter specifies the number of decimal places to be reserved, and the second parameter specifies the processing method of the later part,BigDecimal.ROUND_HALF_DOWN I.e. rounding
System.out.println(n);// 1.255

 

Constructor for BigDecimal:

//Recommend this
BigDecimal a = new BigDecimal("1.6");
System.out.println(a); //1.6

//The second is this. It will be implemented first Double Of toString()The method will be 1.6 Convert to string and call the above method to create BigDecimal Object. Compared with the first,More expensive
BigDecimal b = BigDecimal.valueOf(1.6);
System.out.println(b); //1.6

//Other direct input values are not recommended because precision will be lost
BigDecimal c=new BigDecimal(1.6);
System.out.println(c); //1.600000000000000088817841970012523233890533447265625

 

The second source code is as follows:

public static BigDecimal valueOf(double val) {
     return new BigDecimal(Double.toString(val));
}

 

BigDecimal is mainly used to operate (large) floating-point numbers, and BigInteger is mainly used to operate large integers (over long).

The implementation of BigDecimal uses BigInteger, but the difference is that BigDecimal adds the concept of decimal places

 

 

 

 

4. Use standard of basic data type and packaging data type

Reference: Alibaba Java development manual

  • Force: all POJO class attributes must use the packing data type.
  • The return value and parameters of the force RPC method must use the wrapper data type.
  • [recommended] all local variables use basic data types.

For example, if we customize a Student class, one of its attributes is score. If we use Integer instead of int to define it, a Student may fail in an exam, with a value of null or 0. The two expressions are obviously different

Note: the POJO class attribute has no initial value to remind users that when they need to use it, they must explicitly assign values themselves. Any NPE problem or warehousing check is guaranteed by users.

The query result of the database may be null because of the NPE risk of unboxing automatically and receiving with basic data type.

For example, display the rise and fall of the total transaction amount, i.e. plus or minus x%. X is the basic data type. When the call is unsuccessful, the default value is returned and the page is displayed as 0%. This is unreasonable and should be displayed as a middle dash. Therefore, the null value of the wrapper data type can represent additional information, such as remote call failure and abnormal exit.

 

 

 

 

 

5. Array to List

Arrays.asList() is a static method that can convert arrays to lists:

String[] myArray = { "Apple", "Banana", "Orange" };
List<String> myList = Arrays.asList(myArray);
//You can also pass in array elements directly
List<String> myList = Arrays.asList("Apple","Banana", "Orange");

 

Look at the source code of this method:

public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

        @Override
        public int size() {
            return a.length;
        }

        @Override
        public Object[] toArray() {
            return a.clone();
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<? extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        @Override
        public E get(int index) {
            return a[index];
        }

        @Override
        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        @Override
        public int indexOf(Object o) {
            E[] a = this.a;
            if (o == null) {
                for (int i = 0; i < a.length; i++)
                    if (a[i] == null)
                        return i;
            } else {
                for (int i = 0; i < a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        @Override
        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }

        @Override
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator(a, Spliterator.ORDERED);
        }

        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            for (E e : a) {
                action.accept(e);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            E[] a = this.a;
            for (int i = 0; i < a.length; i++) {
                a[i] = operator.apply(a[i]);
            }
        }

        @Override
        public void sort(Comparator<? super E> c) {
            Arrays.sort(a, c);
        }
    }

 

1. Although it is a new ArrayList(), the return value of the method is declared as a List, so the result of this method is a List, to be declared as a List:

List<String> myList = Arrays.asList(myArray);  

Cannot change to ArrayList

 

 

2. The ArrayList of its new is not the ArrayList in the collection, but the internal class ArrayList of Arrays.

Although the surface is List, the bottom layer is still array:

private final E[] a;  //E is generic.

 

 

3. Take a look at the constructor of this inner class:

ArrayList(E[] array) {
   a = Objects.requireNonNull(array);
}

For the array passed directly, java only passes the value (shallow copy). When passing the reference type, it passes the address. The operation is actually the actual array (the array passed in).

There is only one element in the array of the internal class ArrayList. This element is the passed in array, so call size() to return 1; get(0) to return the passed in array; get(1) to report an error, indicating that the subscript is out of range, because the subscript is only 0.

 

 

4. Take a look at the inheritance diagram of this inner class:

private static class ArrayList<E> extends AbstractList<E>  //This inner class inherits AbstractList
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>  //AbstractList and implements List

That is to say, the internal class ArrayList implements List, which is the List interface in the collection, defines the methods of adding(), remove(), set(), get(), and other columns to operate the List collection.

Let's take a look at the source code of the internal class ArrayList, which only implements set(), get(), and other methods, but not add(), remove(), clear(),

So the objects of this inner class can use add() and remove() methods, which can be prompted by code or compiled by compiler. Because of the implements list, these method definitions are all available. However, the runtime exception will be reported once running, because these methods are abstract, and the inner class ArrayList does not provide an implementation.

 

 

 

5. The internal class ArrayList is obviously weak. How to convert it to the ArrayList class in the collection?

There are many methods. The following is the simplest:

ArrayList list = new ArrayList<>( Arrays.asList("a", "b", "c") )  //Use the constructor of the ArrayList class in the collection and pass in the internal ArrayList object

How do you know if ArrayList is the inner class or the one in the collection? Let's take a look at the declaration of the inner class:

private static class ArrayList<E>

private, the internal class ArrayList can only be used in Arrays, so the ArrayList above is the one in the collection.

It is also because private, List < string > mylist = Arrays.aslist (myArray); the return value of this method should be declared as a List, not an internal class ArrayList (this internal class cannot be used outside the Arrays class).

 

 

The complete way to convert an array into a List set:

String[] myArray = { "Apple", "Banana", "Orange" };  //array
List<String> myList = Arrays.asList(myArray);  //Internal class ArraysList, intermediary, bridge

//The above two codes can also be written as
List<String> myList = Arrays.asList( "Apple", "Banana", "Orange" );
ArrayList list = new ArrayList<>( mylist );  //ArrayList in collection

 

 

Array inversion:

        String[] arr= {"gailun", "huangzi", "zhaoxin"};
        List<String> list = Arrays.asList(arr); //Convert an array to an inner class ArrayList
        Collections.reverse(list); //Static method implementation of calling Collections tool classArray inversion, array has been modified

        System.out.println(list); //[zhaoxin, huangzi, gailun]

        for (String s1:arr)
            System.out.println(s1);
        
        // zhaoxin
        // huangzi
        // gailun

As mentioned above, when creating the internal class ArrayList object, the array address is passed, the operation is the array itself, and the inversion of ArrayList is the inversion of array.

 

 

Whether you use the enhanced for loop or use the while+iterator to traverse the set|array, you cannot add or delete the set|array elements in the loop because:

1. The operation is temporary variable, not original array element, and can only be read

2. After adding or deleting elements, the number of iterations changes, which is inconsistent with the original number of iterations, resulting in iteration errors

Tags: Java Attribute Database

Posted on Sat, 14 Mar 2020 00:11:09 -0700 by iffo