Answers are included under Java Classic Interview Questions

insert image description here

21. What is the difference between String, StringBuffer and StringBuilder?

thread safety:

  • Objects in String are immutable and thread-safe
  • StringBuffer adds a synchronization lock to the method, so it is thread-safe
  • StringBuilder does not add a synchronization lock to the method, so it is not thread-safe

Efficiency:

  • When String is operated, a new String object will be generated every time, and then the pointer will point to the new String object.
  • However, StringBuffer and StringBuilder will operate on themselves instead of generating new objects each time. StringBuilder is more efficient than StringBuffer, but not thread-safe

Variability:
String:
insert image description here
The class modified by fianl cannot be inherited, the modified method cannot be overridden, the modified basic type data cannot be changed, and the modified reference type cannot point to other objects. Because the final modified array is not the fundamental reason why String is immutable, because the internal data stored in this array is mutable. The real reasons are as follows:

  1. The string array is final and private, and String does not provide a method to modify this string
  2. The String class is final modified so that it cannot be inherited, preventing subclasses from destroying String immutability

StringBuilder与StringBuffer:
insert image description here
Both StringBuilder and StringBuffer inherit from AbstractStringBuilder, which also uses character arrays to store strings, but is not decorated with final and private. And it also provides many methods of manipulating strings.
insert image description here
How to choose the three:

  • A small number of operations use String
  • A large number of operations under a single thread use StringBuilder
  • A large number of operations under multi-threading use StringBuffer

String splicing using + or StringBuilder?

public static void main(String[] args) {
    
    
        String str = "";
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
    
    
            str += "a";
        }
        long end = System.currentTimeMillis();
        System.out.println("String拼接100000次花费时间: " + (end - start));
        StringBuilder stringBuilder = new StringBuilder();
        start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
    
    
            stringBuilder.append("a");
        }
        end = System.currentTimeMillis();
        System.out.println("StringBuilder拼接100000次花费时间: " + (end - start));
    }

insert image description here
First of all, we can conclude that when the amount of data is large, the splicing efficiency of StringBuilder is much higher than that of String splicing, so why?

Because when String is concatenated by "+", the implementation will first create StringBuilder and then call append() and call toString() to get a String object. When we use "+" in the loop to splice,A large number of StringBuilder objects will be created, one will be created every time the loop

String constant pool:
The string constant pool is mainly to improve performance and reduce memory consumption. A special area has been opened for strings to prevent repeated creation of strings.

public static void main(String[] args) {
    
    
        // 将字符串"abc"保存在字符串常量池
        String s1 = "abc";
        // 从字符串常量池直接返回"abc"的引用
        String s2 = "abc";
        System.out.println(s1 == s2);
    }

insert image description here
String s = new String("a") How many objects will be created?
There are two situations here:

  1. There is a reference to "abc" in the constant pool, then only one object will be created in the heap space
  2. There is no reference to "abc" in the constant pool, it will be created in the string constant pool first, and then created in the heap, then a total of 2 string objects will be created

What does intern() do?
intern() is a native method, its function is to save the string in the constant pool, and it is also divided into the following two situations:

  1. There is a reference to the string in the string constant pool, and the reference is returned directly
  2. If there is no reference to the string in the string constant pool, create an object pointing to the string in the constant pool and return the reference

What happens when the + operation is performed on the String variable and the constant?

public static void main(String[] args) {
    
    
        String str1 = "abc";
        String str2 = "efg";
        String str3 = "abc" + "efg";
        String str4 = str1 + str2;
        String str5 = "abcefg";
        System.out.println(str3 == str4);
        System.out.println(str3 == str5);
        System.out.println(str4 == str5);
    }

insert image description here
Why does this happen?
Because for the string that the compiler can determine, that is, the string constant, the JVM will store it in the string constant pool. The spliced ​​string constants will also be stored in the string constant pool in the compiler, benefiting from compiler optimization.

For example:

		String str3 = "abc" + "efg";
        String str3 = "abcefg";

You need to pay attention that not all constants can be folded (constant folding is to embed the value of a constant expression in the final code, which is an optimization done by the Javac compiler heap source code), only the constants that can be determined by the compiler can:

  • Final modified basic data types and string variables
  • Primitive data types are based on string constants

The above str4 is a quoted value that cannot be determined by the compiler, so our compiler cannot optimize
it. It is equivalent to:

String str4 = new StringBuilder().append(str1).append(str2).toString();

But if we add final modification to the string variable, we can let the compiler treat it as a constant

public static void main(String[] args) {
    
    
        final String str1 = "abc";
        final String str2 = "efg";
        String str3 = "abc" + "efg";
        String str4 = str1 + str2;
        String str5 = "abcefg";
        System.out.println(str3 == str4);
        System.out.println(str3 == str5);
        System.out.println(str4 == str5);
    }

insert image description here
After we add final modification to str1 and str2, String will be treated as a constant by the compiler, and its value can be determined during compilation, which is equivalent to constant access.

22. Method common knowledge

Why can't static methods call non-static members?
1. Static methods belong to the class, memory is allocated when the class is loaded, and can be directly accessed through the class name.
Non-static members belong to the instance object, and only exist after the object is instantiated, and need to be accessed through the instance object of the class. The presence of non-static members is illegal

What is the difference between static methods and instance methods?
1. Call method:
When calling a static method, you can useclass name. method name, you can also useobject.methodnameInstance methods can only use the latter method, static methods do not depend on objects
But in order to avoid confusion between static methods and non-static methods, we generally recommend using the method of class name. method name to call static methods

2. Are there restrictions on accessing class members?
When a static method accesses members of this class, it only needs to access static members and methods, and cannot access instance members and methods.

What is a variable length parameter?
Starting from Java5, Java supports variable length parameters, that is, parameters of variable length can be passed in when calling methods, such as:

public static int add(int... n) {
    
    
        int sum = 0;
        for (int i : n) {
    
    
            sum += i;
        }
        return sum;
    }

insert image description here
It should be noted that the variable parameter can only be used as the last parameter of the function, and there can be any number of parameters in front of it, including 0

public static int add(String name,int... n) {
    
    
}

If the method is overloaded, should the fixed parameter or the variable parameter be called first?
Here is the method that will match fixed parameters first, because the method with fixed parameters has a higher matching degree

public static int add(int n) {
    
    
        return 0;
    }
    public static int add(int... n) {
    
    
        return 1;
    }

insert image description here
In fact, our variable parameters in Java will be converted into an array after compilation

23. Numerical operation precision problem

Why is there a problem of loss of precision in floating-point operations?

public static void main(String[] args) {
    
    
        float a = 2.6f - 1.7f;
        float b = 1.6f - 0.7f;
        System.out.println(a);
        System.out.println(b);
        System.out.println(a == b);
    }

insert image description here
It has to do with the way the computer stores floating point numbers. Our computer is expressed in binary. When calculating a number, the width is limited. The small tree with infinite loop can only be truncated when stored in the computer. This is why floating-point numbers cannot be accurately represented in binary

How to solve the problem of loss of precision in floating-point arithmetic?
We can use BigDecimal to implement operations on floating-point numbers. Most of the business scenarios that require high operational precision are done through BigDecimal.

public static void main(String[] args) {
    
    
        BigDecimal a = new BigDecimal("3.0");
        BigDecimal b = new BigDecimal("2.0");
        BigDecimal c = new BigDecimal("1.0");
        System.out.println(a.subtract(b));
        System.out.println(b.subtract(c));
        System.out.println(a.subtract(b).equals(b.subtract(c)));
    }

insert image description here
How should the data exceeding the long integer be represented?
In Java, the 64-bit long integer is the largest integer type, but if it exceeds this range, there is a risk of numerical overflow

public static void main(String[] args) {
    
    
        long a = Long.MAX_VALUE;
        System.out.println(a+1);
    }

insert image description here
We can use BigInteger to represent:

public static void main(String[] args) {
    
    
        BigInteger a = new BigInteger("111111111111111111111111111111111111111");
        BigInteger b = new BigInteger("111111111111111111111111111111111111111");
        System.out.println(a.add(b));
    }

insert image description here
insert image description here
We can find that BigInteger internally uses an int[] array to store integer data of any size, but the operation efficiency of BigInteger is relatively low

24. Abnormal

The structure of Java (Throwable) can be divided into three types: error (Error), checked exception (CheckedException), runtime exception (RuntimeException)
insert image description here
What is the relationship between Exception and Error?
In Java, all exceptions have a common ancestor: the Throwable class in the java.lang package, and Exception and Error are two important subclasses of the Throwable class:

Error: When resources are insufficient, constraints fail, or other conditions that the program cannot continue to run occur, Error is generated, an error that the program cannot handle. For example: OutOfMemoryError, Virtual MachineError, NoClassDefFoundError, etc. When these exceptions occur, the JVM will choose to terminate the thread

Exception: The exception that the program itself can handle. We can catch exceptions through try-catch. Exception can be divided into checked exceptions that must be handled (Checked Exception) and unchecked exceptions that can not be handled (Unchecked Exception)

What is the difference between Checked Exception and Unchecked Exception?

Unchecked Exception: This type of error will not be checked by the Java compiler. When this type of exception occurs, even if it is not thrown through the throws statement or caught by the try-catch statement, it will still compile and pass.
RuntimeException and its subclasses are collectively referred to as unchecked exceptions, such as:

  • NullPointerException: null pointer exception
  • illegalArgumentException: parameter exception
  • ArrayIndexOutOfBoundsException: Array out of bounds exception
  • ClassCastException: type conversion exception
  • ArithmeticException: Arithmetic exception
  • SecurityException: security exception
  • IllegalStateException: illegal state exception
  • UnsupportedOperationException: Unsupported operation exception
  • NumberFormatException: Numeric format exception
    insert image description here

Checked Exception: If the checked exception is not handled by catch or throws, it cannot pass the compiler. In addition to RuntimeException and its subclasses, other Exception classes and subclasses are checked exceptions. The common ones are:

  • ClassNotFoundException
  • IOException
  • FileNotFoundException
  • SQLException

Summary: The checked exception is usually not an error caused by the program, for example: the file does not exist when reading the file: FileNotFoundException. Unchecked exceptions are usually caused by poor programming, such as: NullPointerException when using without ensuring that the object reference is not null

What are the common methods of Throwable?
insert image description here

  • String getMessage(): returns a brief description of the exception
  • String toString(): returns the details of the exception
  • void printStackTrace(): Print the exception information encapsulated by the Throwable object on the console
  • String getLocalizedMessage(): returns the localized message of the exception object. Override this method with a Throwable subclass to generate localized information. If not overridden, it returns the same result as getMessage()

25. What situations have you encountered in OOM, and what situations have you encountered in SOF

OOM
1. OutOfMemoryError exception:
In addition to the program calculator, OOM exceptions may occur in several other areas of the virtual machine memory.
Java Heap overflow: The general exception information is java.lang.OutOfMemoryError: Java heap space The Java
heap is used to store object instances, as long as we continue to create objects and ensure that there is a reachable path between GC Roots and objects to avoid garbage collection mechanisms Cleaning up these objects will cause a memory overflow exception after the number of objects reaches the maximum heap capacity limit. When this exception occurs, we generally first analyze the dumped snapshot through the heap dump of the Eclipse Memory Analyzer. The key point is to confirm whether the objects in the memory are necessary, and to distinguish whether it is due to a memory leak (Memory Leak) or a memory overflow (Memory Overflow).
If there is a memory leak, you can further use the tool to view the reference chain from the leaked object to GCRoots, and check the path Being associated with GCRoots causes the garbage collector to fail to recycle automatically

If there is no leak, check whether the virtual machine parameters (-Xmx and -Xms) are appropriate

2. Virtual machine and local method stack overflow:
If the stack depth requested by the thread is greater than the maximum depth allowed by the virtual machine, a StackOverflowError will be thrown. If the virtual machine cannot apply for enough memory space when expanding the stack, an OutOfMemoryError exception will be thrown

3. Method area overflow:
The method area is used to store Class-related information, such as class name, access modifier, field description, method description, etc. The exception information is: java.lang.OutOfMemoryError: PermGenspace, it may be that the class object saved in the method area has not been recycled in time or the memory occupied by the class information exceeds our configuration

Method area overflow is also a common memory overflow exception. If a class is to be recycled by the garbage collector, the judgment conditions are relatively harsh.

SOF (StackOverflow):
This exception is generally thrown when the application recurses too deep and a stack overflow occurs

It should be noted that stack overflow errors often mean that there are problems in the code, and too deep call levels may cause performance and maintainability problems. Therefore, when solving StackOverflowError, it is recommended to carefully check and optimize the code to ensure the robustness and performance of the code.

26. Syntactic sugar

Syntactic sugar: Syntactic sugar refers to a special syntax designed by a programming language for the convenience of programmers. This syntax has no effect on the function of the compiled language. To achieve the same function, the code written based on syntactic sugar is often more concise. .
What are the common syntactic sugars:
generics, lambda expressions, automatic unboxing, try-with-resources syntax, variable length parameters, enhanced for loops, etc.

For example: for-each in Java

public static void main(String[] args) {
    
    
        int[] arr = {
    
    1,2,3,4,5,6,7};
        for (int i : arr) {
    
    
            System.out.println(i);
        }
    }

Our JVM itself cannot recognize grammatical sugar. If Java grammatical sugar is to be executed correctly, it needs to be desugared by the compiler. In the compilation stage, the grammatical sugar is converted into the syntax recognized by the JVM. It also shows that it is the Java compiler rather than the JVM that really supports syntactic sugar. One of the parts in compile() is desugar(), which is responsible for syntactic sugar desugar.

27. The function and principle of Java reflection

Reflection: At runtime, for any class, you can know all the properties and methods of this class; for any object, you can call any of its methods. In java, as long as the name of the class is given, all the information of the class can be obtained through reflection. This dynamically obtained information and the function of dynamically calling the method of the object are called the reflection mechanism of the Java language.

Where will the reflection mechanism be used?
jdbc is a typical reflection:

Class.for("com.mysql.jdbc.Drivice.class");//加载MySQL的驱动类

This is reflection. Most of us are writing business code, and we seldom come into contact with scenarios where reflection is used directly. This does not mean that reflection is useless. On the contrary, it is precisely because of reflection that we can use various frameworks so easily. The reflection mechanism is widely used in frameworks such as Spring/Spring Boot and MyBatis

Implementation of reflection:

  1. Get Class object: There are four methods in total: 1) Class.forName("class path"); 2) class name. class; 3) object name. getClass(); 4) basic type of wrapper class, which can be called The Type attribute class to get the Class object of the wrapper class
Class<?> clazz = Class.forName("com.example.zd")
  1. Get the field of the class: getField("filename") method: you can get the field modified by public. getDeclaredField("filedName") can get the field with the specified name, no matter what the modifier is
Field field = clazz.getDeclaredField("fieldName")
  1. Get the method information of the class: getMethod("methodName", parameterTypes), you can get the public method with the specified name and parameter type; use the getDeclaredMethod("methodName", parameterTypes) method, you can get the method with the specified name and parameter type, whatever the modifier is
Method method = clazz.getDeclaredMethod("methodName", String.class, int.class)
  1. Create an object instance: use the newInstance() method to create an object instance through a no-argument constructor, for example:
Object obj = clazz.newInstance()

Use the getConstructor(parameterTypes).newInstacne(arguments) method to create an object by specifying the constructor and parameters

Constructor<?> constructor = clazz.getConstructor(String.class, int.class); 
Object obj = constructor.newInstance("arg1", 123)

Advantages and disadvantages of reflection:
Reflection can make our code more flexible and provide convenience for various frameworks to provide out-of-the-box functions. However, reflection gives us the ability to analyze operation classes at runtime, but also increases security issues, such as: the security check of generic parameters can be ignored (the security check of generic parameters occurs at compile time). In addition, the performance of reflection is slightly worse, but it has little effect on the framework

Guess you like

Origin blog.csdn.net/buhuisuanfa/article/details/131365335