Writing Quality Code: 151 Suggestions for Improving Java Applications [26~36]

Beware of null values for wrapper types

public static int testMethod(List<Integer> list) {
        int count = 0;
        for(Integer i : list) { count += (i ! =null)? i :0;
        }
        return count;
    }
Copy the code

It is true that wrapped and unboxed objects can be converted freely, but null values are excluded, which cannot be converted to primitive types. One thing to keep in mind about this problem is that when a wrapper type participates in an operation, it is null checked.

Be careful with size comparisons of package types

  1. I ==j: In Java, “==” is used to determine whether two operands are equal. If they are basic types, then values are equal. If they are objects, then two references to the same object, i.e. addresses are equal.
  2. I > I < j and j: In Java, “>” and “<” are used to determine the size relationship between two numeric types. Note that only numeric types can be determined. IntValue () is compared against the value returned by its intValue() method. (Other wrapper types are compared against their value, doubleValue,floatValue, etc.).

Integer pools are preferred

(1) The Integer object generated by new

The new declaration is to generate a new object, no doubt, these are two objects, the address must not be different, the comparison result is false.

(2) Objects generated by boxing

The first thing to note about this is that the boxing action is implemented by the valueOf method, which means that the last two algorithms are the same, so the result must be the same. Now the question is: how does valueOf generate the object? Let’s read the source code for integer.valueof:

 public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
Copy the code
 private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if(integerCacheHighPropValue ! =null) {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low));
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache(a) {}}Copy the code

A cache is a static array of IntegerCache internal classes that hold Integer objects ranging from -128 to 127. When valueOf generates a wrapper object, if the int argument is between -128 and 127, the object is fetched directly from the integer pool. Ints that are not in that range are generated by new.

Do not set random seeds

In Java, the generation of random numbers depends on seeds. The relationship between random numbers and seeds follows the following two principles: Different seeds generate different random numbers and the same seeds, and the same random numbers are generated even if the instances are different

import java.util.Random;

public class Client30 {
    public static void main(String[] args) {
        Random r = new Random();
        for(int i=1; i<=4; i++){
            System.out.println("The first"+i+"Time."+r.nextInt()); }}}Copy the code
Random r = new Random(1000);
Copy the code

1000 is a random seed, run many times, although the instance is different, but will get the same four random numbers. #### Do not have implementation code in the interface

public class Client31 {
    public static void main(String[] args) {
        // Invoke the interface implementationB.s.doSomeThing(); }}// There is implementation code in the interface
interface B {
    public static final S s = new S() {
        public void doSomeThing(a) {
            System.out.println("I implemented it in the interface."); }}; }// The interface to be implemented
interface S {
    public void doSomeThing(a);
}
Copy the code

In interface B, a static constant S is declared, whose value is an instance object of an Anonymous Inner Class. It is this Anonymous Inner Class that implements interface S. #### Static variables must be declared before they are assigned. Static variables are loaded first when a class is initialized. The JVM looks for all static declarations in the class and allocates space. The JVM then performs static assignments (both static class assignments and static block assignments) in the order in which they occur. For a program, it reads the address space of type int, passes the address to I, and then executes the assignment in class order, first performing the static block I = 100, then performing the assignment I =1, and finally producing the result I =1.

#### Do not override static methods

Avoid initializing other classes in constructors

public class Client35 {
    public static void main(String[] args) {
        Son son = newSon(); son.doSomething(); }}/ / parent class
class Father {
    public Father(a) {
        newOther(); }}/ / related classes
class Other {
    public Other(a) {
        newSon(); }}/ / subclass
class Son extends Father {
    public void doSomething(a) {
        System.out.println("Hi, show me Something!"); }}Copy the code

Causes the constructor to loop

The original link: https://www.cnblogs.com/androidsuperman/p/9358122.html8122