java core technology Volume I -- Book Sharing meeting

Main shared content

(1) Keywords final and static

(2) Data type

(3)BigDecimal

(4) Generics

Keywords final and static

(1)final

1. Data

The declared data is a constant, which can be a compile time constant or a constant that cannot be changed after initialization at run time.

  • For basic types, final keeps the value unchanged;
  • For reference types, final makes the reference unchanged, so other objects cannot be referenced, but the referenced object itself can be modified.
final int x = 1;
// x = 2;  // cannot assign value to final variable 'x'
final A y = new A();
y.a = 1;
2. Method

Declared methods cannot be overridden by subclasses.
The private method is implicitly specified as final. If the signature of the method defined in the subclass is the same as that of a private method in the base class, the subclass method does not override the base class method, but defines a new method in the subclass.

3. Class

Declared classes are not allowed to be inherited.

(2)static

1. Static variables
  • Static variable: also known as class variable, that is, this variable belongs to a class. All instances of the class share a static variable, which can be accessed directly through the class name. Static variables exist only once in memory.
  • Instance variable: every time an instance is created, an instance variable will be generated, which will live and die with the instance.
public class A {

    private int x;         // Instance variable
    private static int y;  // Static variable

    public static void main(String[] args) {
        // int x = A.x;  // Non-static field 'x' cannot be referenced from a static context
        A a = new A();
        int x = a.x;
        int y = A.y;
    }
}
2. Static method

Static methods exist when the class is loaded and do not depend on any instances. Therefore, static methods must be implemented, that is, they cannot be abstract methods.

public abstract class A {
    public static void func1(){
    }
    // public abstract static void func2();  // Illegal combination of modifiers: 'abstract' and 'static'
}

You can only access the static fields and static methods of the class. The method cannot have this and super keywords, because these two keywords are associated with a specific object.

public class A {

    private static int x;
    private int y;

    public static void func1(){
        int a = x;
        // int b = y;  // Non-static field 'y' cannot be referenced from a static context
        // int b = this.y;     // 'A.this' cannot be referenced from a static context
    }
}
3. Static statement block

Static statement blocks are run once during class initialization.

public class A {
    static {
        System.out.println("123");
    }

    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new A();
    }
}
123
4. Static internal class

The non static inner class depends on the instance of the outer class, that is, you need to create an outer class instance before you can use this instance to create a non static inner class. Static inner classes do not.

public class OuterClass {

    class InnerClass {
    }

    static class StaticInnerClass {
    }

    public static void main(String[] args) {
        // InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
        OuterClass outerClass = new OuterClass();
        InnerClass innerClass = outerClass.new InnerClass();
        StaticInnerClass staticInnerClass = new StaticInnerClass();
    }
}

Static internal classes cannot access non static variables and methods of external classes.

5. Initialization sequence

Static variables and static statement blocks take precedence over instance variables and ordinary statement blocks. The initialization order of static variables and static statement blocks depends on their order in the code.

public static String staticField = "Static variable";
static {
    System.out.println("Static statement block");
}
public String field = "Instance variable";
{
    System.out.println("Common statement block");
}

The last is the initialization of the constructor.

public InitialOrderTest() {
    System.out.println("Constructor");
}

In case of inheritance, the initialization order is:

  • Parent class (static variable, static statement block)
  • Subclasses (static variables, static statement blocks)
  • Parent class (instance variable, common statement block)
  • Parent class (constructor)
  • Subclasses (instance variables, common statement blocks)
  • Subclass (constructor)

data type

Basic type bit Packaging type
byte 8 Byte
char 16 Character
short 16 Short
int 32 Integer
float 32 Float
long 64 Long
double 64 Double
boolean ~ Boolean

1. Packing and unpacking

Integer x = 2;     // Boxing called Integer.valueOf(2)
int y = x;         // Unpacking called X.intValue()

Cache pool

The difference between new Integer(123) and Integer.valueOf(123) is:

  • new Integer(123) creates a new object each time;
  • Integer.valueOf(123) will use the objects in the cache pool, and multiple calls will get the reference of the same object.
Integer x = new Integer(123);
Integer y = new Integer(123);
System.out.println(x == y);    // false
Integer z = Integer.valueOf(123);
Integer k = Integer.valueOf(123);
System.out.println(z == k);   // true

The implementation of valueOf() method is relatively simple, that is, first judge whether the value is in the cache pool, and if so, directly return the contents of the cache pool.

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

The compiler calls the valueOf() method during the auto boxing process, so if multiple Integer instances with the same value and within the cache pool are created using auto boxing, the same object will be referenced.

Integer m = 123;
Integer n = 123;
System.out.println(m == n); // true

The buffer pool corresponding to the basic type is as follows:

  • boolean values true and false
  • all byte values
  • short values between -128 and 127
  • int values between -128 and 127
  • char in the range \u0000 to \u007F

When using the wrapper type corresponding to these basic types, if the value range is within the buffer pool range, you can directly use the objects in the buffer pool.

BigDecimal

1. Use of BigDecimal

Alibaba Java development manual mentions that for the equivalence judgment between floating-point numbers, the basic data type cannot be compared with = = and the packaging data type cannot be judged with equals. The specific principle is related to the encoding method of 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

With basic mathematical knowledge, we clearly know that the output is not the result we want (precision loss). How can we solve this problem? A very common method is to use BigDecimal to define the value of floating-point numbers, and then carry out the operation of floating-point numbers.

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");

BigDecimal x = a.subtract(b); 
BigDecimal y = b.subtract(c); 

System.out.println(x); /* 0.1 */
System.out.println(y); /* 0.1 */
System.out.println(Objects.equals(x, y)); /* true */
2.BigDecimal size comparison

a.compareTo(b): returns - 1 to indicate that a is less than B, 0 to indicate that a is equal to B, and 1 to indicate that a is greater than B

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
System.out.println(a.compareTo(b));// 1
3.BigDecimal retains several decimal places

Set the number of decimal places and retention rules through the setScale method. There are many retention rules. You don't need to remember them. IDEA will prompt you.

BigDecimal m = new BigDecimal("1.255433");
BigDecimal n = m.setScale(3,BigDecimal.ROUND_HALF_DOWN);
System.out.println(n);// 1.255
4. Precautions for use of BigDecimal

Note: when using BigDecimal, in order to prevent precision loss, we recommend using its BigDecimal(String) construction method to create objects. Alibaba Java development manual also mentions this part, as shown in the figure below.

generic paradigm

1. General

Generics play an important role in java and are widely used in object-oriented programming and various design patterns.

What is generics? Why use generics?

  • Generic, or "parameterized type". When referring to parameters, the most familiar thing is that there is a formal parameter when defining the method, and then the arguments are passed when the method is called. So what about parameterized types? As the name suggests, it is to parameterize the type from the original specific type, which is similar to the variable parameters in the method. At this time, the type is also defined in the form of parameters (which can be called type parameters), and then the specific type (type arguments) is passed in during use / call.
  • The essence of generics is to parameterize types (the types of formal parameters are controlled by different types specified by generics without creating new types). In other words, in the process of using generics, the data type of the operation is specified as a parameter. This parameter type can be used in classes, interfaces and methods, which are called generic classes, generic interfaces and generic methods respectively.
2. An example
List arrayList = new ArrayList();
arrayList.add("aaaa");
arrayList.add(100);

for(int i = 0; i< arrayList.size();i++){
    String item = (String)arrayList.get(i);
    System.out.println("Generic testing"+"item = " + item);
}

There is no doubt that the running result of the program will end in a crash:

ArrayList can store any type. In the example, a String type and an Integer type are added. When they are used again, they are used in the form of String, so the program crashes. In order to solve such problems (which can be solved at the compilation stage), generics came into being.

We will change the first line of code to initialize the list, and the compiler will help us find such problems at the compilation stage.

List<String> arrayList = new ArrayList<String>();
...
//arrayList.add(100);  During the compilation phase, the compiler will report an error
3. Characteristics

Generics are only valid at compile time. Look at the following code:

List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();

Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();

if(classStringArrayList.equals(classIntegerArrayList)){
    System.out.println("Generic testing"+"Same type");
}

Output result: the generic test type is the same.

The above example can prove that the program will take de genericization measures after compilation. In other words, generics in Java are only valid at the compilation stage. In the compilation process, after the generic results are correctly verified, the relevant information of the generic will be erased, and the methods of type checking and type conversion will be added at the boundary where the object enters and leaves the method. That is, generic information does not enter the runtime phase.

4. Use of generics

There are three ways to use generics: generic class, generic interface and generic method

4.1 generic classes

Generic types are used in the definition of classes and are called generic classes. Through generics, you can complete the operation of a group of classes and open the same interface to the outside world. The most typical are various container classes, such as List, Set and Map.

The most basic way to write generic classes

//Here, T can be written as any identifier. Common parameters such as T, E, K and V are often used to represent generics
//When instantiating a generic class, you must specify the concrete type of T
public class Generic<T>{ 
    //key the type of this member variable is t, and the type of T is specified externally  
    private T key;

    public Generic(T key) { //The type of generic constructor parameter key is also t, and the type of T is specified externally
        this.key = key;
    }

    public T getKey(){ //The return value type of the generic method getKey is t, and the type of T is specified externally
        return key;
    }
}


//Type parameters of generic types can only be class types (including custom classes), not simple types
//The type of the passed in argument must be the same as that of the generic type parameter, that is, Integer
Generic<Integer> genericInteger = new Generic<Integer>(123456);

//The input argument type must be the same as the type parameter type of the generic type, that is, String
Generic<String> genericString = new Generic<String>("key_vlaue");

Do you have to pass in generic type arguments for a defined generic class? This is not the case. When using generics, if you pass in generic arguments, you will make corresponding restrictions according to the passed in generic arguments. At this time, generics will play the role of restriction that they should play. If the generic type argument is not passed in, the type defined by the generic method or member variable in the generic class can be any type.

Generic generic = new Generic("111111");
Generic generic1 = new Generic(4444);
Generic generic2 = new Generic(55.55);
Generic generic3 = new Generic(false);
4.2 generic interfaces

The definition and use of generic interfaces and generic classes are basically the same. Generic interfaces are often used in various kinds of producers.
A simple generic interface

public interface Generator<T> {
    public T next();
}

When a class implementing a generic interface does not pass in a generic argument:

class FruitGenerator<T> implements Generator<T>{
    @Override
    public T next() {
        return null;
    }
}

When a class implementing a generic interface passes in a generic argument:

public class FruitGenerator implements Generator<String> {

    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}
4.3 generic methods
public class GenericTest {
   //This class is a generic class, which has been introduced above
   public class Generic<T>{     
        private T key;

        public Generic(T key) {
            this.key = key;
        }

        //Although generics are used in methods, this is not a generic method.
        //This is just an ordinary member method in the class, but its return value is the declared generic of the declared generic class.
        //Therefore, we can continue to use the generic type T in this method.
        public T getKey(){
            return key;
        }

      
    }

    /** 
     * This is a real generic method.
     * First, the < T > between public and the return value is essential, which indicates that this is a generic method and declares a generic t
     * This T can appear anywhere in the generic method
     * The number of generics can also be any number 
     *    For example: public < T, k > k showkeyname (generic < T > container){
     *        ...
     *        }
     */
    public <T> T showKeyName(Generic<T> container){
        System.out.println("container key :" + container.getKey());
        T test = container.getKey();
        return test;
    }

    //This is not a generic method, but a common method. It just uses the generic < number > class as a formal parameter.
    public void showKeyValue1(Generic<Number> obj){
        System.out.println("Generic testing"+"key value is " + obj.getKey());
    }
   

    public static void main(String[] args) {


    }
}
4.4 static methods and generics

Static methods need to pay attention to one situation, that is, static methods in classes use generics: static methods cannot access the generics defined on the class; if the reference data type of static method operation is uncertain, generics must be defined on the method.

That is, if static methods want to use generics, static methods must also be defined as generic methods.

public class StaticGenerator<T> {
    ....
    ....
    /**
     * If you define a static method that uses generics in a class, you need to add additional generic declarations (define this method as a generic method)
     * Even if static methods want to use generics already declared in generic classes, they can't.
     * For example: public static void show (T) {..}, the compiler will prompt an error message:
          "StaticGenerator cannot be refrenced from static context"
     */
    public static <T> void show(T t){

    }
}

Posted by n8w on Mon, 22 Nov 2021 00:09:41 -0800