Java background development interview questions sharing two

Why is the String class final?

  1. For efficiency. If it is allowed to be inherited, its high usage rate may reduce the performance of the program.

  2. for safety. Many core classes such as String provided in the JDK, the implementation of many internal methods of the class are not written in the java programming language itself, and many methods are called the native API of the operating system. This is the famous "local method call", and only Only in this way can things be done. This kind of class communicates frequently with the operating system. If this class can be inherited and its methods are rewritten, then a piece of malicious code can be written into the operating system.

  3. Do not want to be modified. This class is like a tool, the provider of the class does not want to be changed. If you can change it casually, then the program written in java will be unstable, and one of the advantages of java and C++ is that it is more stable.


What is the difference between String, StringBuffer and StringBuilder?

String type is immutable, StringBuffer and StringBuilder are mutable.

速度:StringBuilder > StringBuffer > String。

The bottom layer of StringBuffer and StringBuilder is realized by char[] array.

StringBuffer is thread-safe, while StringBuilder is thread-unsafe.

If you want to manipulate a small amount of data use String, use StringBuilder for single-threaded manipulation of large amounts of data, and use StringBuffer for multi-threaded manipulation of large amounts of data.


The principle and use of TreeSet (Comparable and Comparator)

  1. The elements in the TreeSet are not allowed to repeat, but are in order.

  2. TreeSet uses a tree structure to store data. When storing elements, it needs to be compared with the elements in the tree, and a comparison strategy needs to be specified. The comparison strategy can be specified by Comparable and Comparator.

  3. System classes that implement Comparable can be stored in TreeSet smoothly; custom classes can implement Comparable interface to specify comparison strategies.

  4. You can create a Comparator interface implementation class to specify the comparison strategy, and pass it in through the TreeSet constructor parameters; this method is especially suitable for system classes.


Please briefly describe Java's garbage collection mechanism

Garbage collection is automatically executed by the java virtual machine without human intervention. The system will automatically execute the garbage collection mechanism when it is idle. You can use the System.gc() method to suggest garbage collection, but you cannot determine when to return to the collection.

Before the JVM garbage collector collects an object, it is generally required that the program call the appropriate method to release the resource, but in the case of not explicitly releasing the resource, Java provides a default mechanism to terminate the object and release the resource. This method is finalize().

Garbage collection refers to the recovery of memory, and the memory here mainly refers to the memory in the heap area and method area of ​​the JVM.


What is the difference between sleep() and wait()

The sleep() method is a static method of the thread class Thread. It allows the calling thread to enter the sleep state and gives execution opportunities to other threads. After the sleep time is over, the thread enters the ready state and competes with other threads for the execution time of the cpu. sleep() is a static method. It cannot change the lock of the object. When the sleep() method is called in a synchronized block, although the thread enters sleep, the machine lock of the object is not released, and other threads still cannot access the object.

wait() is a method of the Object class. When a thread executes to the wait method, it enters a waiting pool related to the object, and at the same time releases the lock of the object so that other threads can access it. It can be accessed through the notify or notifyAll method. Wake up the waiting thread.


Frog jumping steps: A frog can jump 1 step/2 steps at a time. How many ways are there to jump to the nth step?

/**
 * @author Renda Zhang
 * @create 2020-06-24 16:40
 */
public class FrogJumpStairs {

    // 总台阶数
    private static final int TOTAL_STAIRS = 10;

    /**
     * 数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
     * 使用 Fibonacci sequence(斐波那契数列)来解答
     * 时间复杂度:O(n) 单循环到 n
     * 空间复杂度:O(1)
     *
     * @param total 总的台阶数量
     * @return 所有跳法的总数量
     */
    private static int jumpStairsFibonacci(int total) {
        if (total == 1) {
            return 1;
        }
        int firstNum = 1;
        int secondNum = 2;
        for (int i = 3; i <= total; i++) {
            int third = firstNum + secondNum;
            firstNum = secondNum;
            secondNum = third;
        }
        return secondNum;
    }

    /**
     * Dynamic Programming (动态规划)
     * 时间复杂度:O(n) 单循环到 n
     * 空间复杂度:O(n) dp 数组用了 n 空间
     *
     * @param total 总的台阶数量
     * @return 所有跳法的总数量
     */
    private static int jumpStairsDp(int total) {
        if (total == 1) {
            return 1;
        }
        int[] dp = new int[total + 1];
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= total; i++) {
            dp[i] = dp[i - 1] + dp[i -2];
        }
        return dp[total];
    }

    // 记忆每一层递归对应的数值
    private static int[] memo;

    /**
     * 递归解法的优化
     * 时间复杂度:O(n)
     * 空间复杂度:O(n)
     *
     * @param current 青蛙已经跳过的台阶数量
     * @param total 总的台阶数量
     * @return 所有跳法的总数量
     */
    private static int jumpStairsMemo(int current, int total) {
        // 如果目前已经跳过的台阶数大于总台阶数,说明传入的参数不合理,返回 0 代表跳法为 0
        if (current > total) {
            return 0;
        }
        // 如果相等,说明青蛙已经跳完一次。
        if (current == total) {
            return 1;
        }
        // 说明已有记录,直接返回
        if (memo[current] > 0) {
            return memo[current];
        }
        // 通过递归把所有次数相加即得到总次数。
        memo[current] = jumpStairsMemo(current + 1, total) + jumpStairsMemo(current + 2, total);
        return memo[current];
    }

    /**
     * 递归暴力破解法
     * 时间复杂度:O(2ⁿ)  - 递归树的所有节点数
     * 空间复杂度:O(n) - 递归树可达深度
     *
     * @param current 青蛙已经跳过的台阶数量
     * @param total 总的台阶数量
     * @return 所有跳法的总数量
     */
    private static int jumpStairs(int current, int total) {
        // 如果目前已经跳过的台阶数大于总台阶数,说明传入的参数不合理,返回 0 代表跳法为 0
        if (current > total) {
            return 0;
        }
        // 如果相等,说明青蛙已经跳完一次。
        if (current == total) {
            return 1;
        }
        // 通过递归把所有次数相加即得到总次数。
        return jumpStairs(current + 1, total) + jumpStairs(current + 2, total);
    }

    public static void main(String[] args) {
        System.out.println(jumpStairs(0, TOTAL_STAIRS));

        memo = new int[TOTAL_STAIRS + 1];
        System.out.println(jumpStairsMemo(0, TOTAL_STAIRS));

        System.out.println(jumpStairsDp(TOTAL_STAIRS));

        System.out.println(jumpStairsFibonacci(TOTAL_STAIRS));
    }
}

The difference and connection between HashMap and Hashtable

The implementation principle is the same, the function is the same, the bottom layer is a hash table structure, the query speed is fast, and it can be used in many cases.

The main differences between the two are as follows

  1. Hashtable is the interface provided by the early JDK, and HashMap is the interface provided by the new version of the JDK.

  2. Hashtable inherits the Dictionary class, and HashMap implements the Map interface.

  3. Hashtable is thread-safe, HashMap is not thread-safe.

  4. Hashtable does not allow null values, HashMap allows null values

  5. Both Hashtable and HashMap use Iterator. For historical reasons, Hashtable also uses Enumeration.

  6. The difference between the initial size and the size of each expansion: the default initial size of Hashtable is 11, and each time it is expanded, the capacity becomes the original 2n+1; the default initial size of HashMap is 16, and each time it is expanded, the capacity becomes 2 times the original.

  7. The use of hash value is different, HashTable directly uses the hashCode of the object. And HashMap recalculates the hash value. HashCode is an int type value calculated by jdk according to the address or string or number of the object. Hashtable calculates the hash value by directly using the hashCode() of the key; while HashMap recalculates the hash value of the key. Hashtable when evaluated position index hash value corresponding to a modulo operation; and HashMap when evaluated location index, the use and operation, and where usually first with hash &amp; 0x7FFFFFFFpost, and then the length modulo &amp; 0x7FFFFFFFthe purpose of applying a negative hash values were converted to a positive value, because there is a hash value may be negative, and &amp; 0x7FFFFFFFafter that only the sign bit changes.


The connection and difference between character stream and byte stream. When to use byte stream and character stream?

Character Stream and Byte Stream are the divisions of IO streams. They are divided according to the data unit processing the stream. Both types are divided into input and output operations.

The output data in the byte stream is mainly done using the OutputStream class, and the input is done using the InputStream class; the output in the character stream is mainly done using the Writer class, and the input stream is mainly done using the Reader class. These four are abstract classes.

The unit of character stream processing is a 2-byte Unicode character, which operates "character, character array or string"; the unit of byte stream processing is 1 byte, which operates "byte and byte array".

Byte stream is the most basic. All InputStrem and OutputStream subclasses are mainly used to process binary data, which is processed by bytes; but in reality, a lot of data is text, so the concept of character stream is also proposed , It is processed according to the character encoding of the virtual machine, that is, the character set conversion is required.

Byte stream and character stream are related through InputStreamReader and OutputStreamWriter, and the bottom layer is related through byte[] and String.


Name the storage performance and characteristics of ArrayList and LinkedList

1. ArrayList supports indexing to get the corresponding elements (random access); but LinkedList needs to traverse the entire linked list to get the corresponding elements. Therefore, the access speed of ArrayList is generally faster than LinkedList.
2. Because ArrayList is an array structure, the consumption is relatively large for deletion and modification (requires copying and moving the array); while LinkedList is a doubly linked list, deletion and modification only need to modify the corresponding pointer, and its consumption is very small . Therefore, in general, LinkedList adds and deletes faster than ArrayList.

3. They are all thread-unsafe, but the dynamic array Vector class collection relies on synchronous access to achieve thread-safety.

4. The initial length of ArrayList is 0 after calling the no-parameter construction. When add is called for the first time, the length becomes 10; and LinkedList is a doubly linked list with no initial size and no expansion mechanism, that is, it is always at the beginning or end. Additions and deletions.


Null value as a parameter overload problem

Examine the accuracy of overloaded function calls.

Consider the output of the following program

public class TestNull { 
    public void show(String a){ 
        System.out.println("String"); 
    } 
    public void show(Object o){ 
        System.out.println("Object"); 
    } 
    public static void main(String args[]){ 
        TestNull t = new TestNull(); 
        t.show(null); 
    } 
} 

Java's overload resolution process runs in two stages: the first stage selects all available and applicable methods or constructors; the second stage selects the most accurate method or constructor selected in the first stage One. If a method or constructor can accept any parameters passed to another method or constructor, then the first method is considered less precise than the second method.

This program show(Object o)can be passed to accept any show(String a)arguments, so the show(Object o)relative lack of accuracy.

Therefore, the result of the operation is: "String".

Want to know more, welcome to follow my WeChat public account: Renda_Zhang

Guess you like

Origin blog.csdn.net/qq_40286307/article/details/108877519