Summary of Java interview questions | Java basics part 2 (continuously updated)

Advantages and Disadvantages of Reflection

The function of dynamically obtaining program information and dynamically calling objects is called the reflection mechanism of the Java language.

  • When the program is running, you can obtain the Class object of any class through reflection, and view the information of this class through this object;
  • When the program is running, you can create an instance of any class through reflection and access the members of the instance;
  • When the program is running, a dynamic proxy class or dynamic proxy object of a class can be generated through the reflection mechanism.

Determine the class to which any object belongs at runtime; construct an object of any class at runtime; determine the member variables and methods of any class at runtime; call the method of any object at runtime; generate a dynamic proxy.

Benefits: Reflection can make our code more flexible and provide out-of-the-box functionality for various frameworks.

However, while reflection gives us the ability to analyze operation classes at runtime, it also increases security issues, such as the ability to ignore the security checks of generic parameters (security checks of generic parameters occur at compile time). In addition, the performance of reflection is slightly worse, but it actually has little impact on the framework.

BIO、AIO、NIO

Synchronous and asynchronous concepts

Synchronization and asynchronous focus on *message communication mechanism* (synchronous communication/ asynchronous communication). Synchronization means that when something is called, the caller has to wait for the call to return the result before continuing to execute. Asynchronous, as opposed to synchronous. When an asynchronous procedure call is issued, the caller does not get the result immediately. Instead, after the call is issued, the callee notifies the caller through the status, or handles the call through a callback function.

Blocking and non-blocking

Blocking and non-blocking focus on the state of the program while waiting for the call result (message, return value). Blocking call means that the current thread will be suspended before the call result is returned. The calling thread will return only after getting the result. A non-blocking call means that the call will not block the current thread until the result cannot be obtained immediately.

BIO

img

Java BIO : Synchronization and blocking (traditional blocking type), the server implementation mode is one connection and one thread, that is, when the client has a connection request, the server needs to start a thread for processing. If the connection does not do anything, unnecessary threads will be created. overhead.

BIO problem analysis

  1. Each request needs to create an independent thread to process data with the corresponding client.

  2. When the number of concurrent connections is large, a large number of threads need to be created to handle connections, which takes up a lot of system resources.

  3. After the connection is established, if the current thread has no data to read temporarily, the current thread will always be blocked in the Read operation, resulting in a waste of thread resources.

When the number of client connections is not high, there is no problem. However, when faced with hundreds of thousands or even millions of connections, the traditional BIO model is powerless. Therefore, we need a more efficient I/O processing model to cope with higher concurrency

NIO

img

Java NIO : Synchronous and non-blocking, the server implementation mode is for one thread to process multiple requests (connections), that is, the connection request sent by the client will be registered to the multiplexer, and the multiplexer polls for I/O The O request will be processed. The specific method is that the multiplexer polls the connection and starts a thread for processing only when there is an I/O request. The user process also needs to ask from time to time whether the IO operation is ready, which requires the user process to keep asking.

img

Comparison between NIO and BIO

  1. BIO processes data in a stream manner, while NIO processes data in a block manner. Block I/O is much more efficient than stream I/O.

  2. BIO is blocking, while NIO is non-blocking.

  3. BIO operates based on byte streams and character streams, while NIO operates based on Channel and Buffer. Data is always read from the channel to the buffer, or written from the buffer to the channel.

AIO

AIO (asynchronous non-blocking I/O) The user process only needs to initiate an IO operation and then return immediately. After the IO operation is actually completed, the application will be notified that the IO operation is completed.

img

Summarize

img

Analysis of applicable scenarios of BIO, NIO and AIO

  1. The BIO method is suitable for architectures with a relatively small and fixed number of connections . This method has relatively high requirements for server resources and concurrency is limited to applications. It was the only choice before JDK1.4, but the program is intuitive, simple and easy to understand.

  2. The NIO method is suitable for architectures with a large number of connections and relatively short connections (light operations) , such as chat servers. Concurrency is limited to applications and programming is complex. JDK1.4 begins to support it.

  3. The AIO method is used in architectures with a large number of connections and relatively long connections (heavy operations) , such as photo album servers. It fully calls the OS to participate in concurrent operations. The programming is relatively complicated, and JDK7 begins to support it.

Long connection means that after establishing a Socket connection, the connection is maintained regardless of whether it is used, but the security is poor.

Benefits of design patterns

  • Code reusability (ie: code with the same function, no need to write it multiple times)
  • Readability (ie: programming standardization, making it easier for other programmers to read and understand)
  • Scalability (that is, it is very convenient when new functions need to be added, which is called maintainability)
  • Reliability (that is: when we add new functions, there will be no impact on the original functions)
  • Make the program exhibit high cohesion and low coupling characteristics

Are design patterns necessarily useful?

Design patterns are general solutions used to solve a specific problem

Over-design may lead to program complexity

The difference between Integer.ValueOf and new Integer

  • new Integer() will create a new object every time;
  • Integer.valueOf(): You can convert the basic type int to the wrapped type Integer;
    • Objects in the cache pool will be used between -128-127, and multiple calls will obtain a reference to the same object.
    • Numbers greater than 128 will first create a new object and then reference it.
Integer x = new Integer(100);
Integer y = new Integer(100);
System.out.println(x == y);    // false
Integer z = Integer.valueOf(100);
Integer k = Integer.valueOf(100);
System.out.println(z == k);   // true

The difference between Integer.parseInt(s) and Integer.valueOf(s)

  • The int basic type data obtained by parsing the same string multiple times through Integer.parseInt(s) is equal. You can directly use "==" to determine whether they are equal.
  • When Integer.valueOf(s) parses the same string multiple times, the object obtained is an Integer type object . Sometimes the object obtained is the same object, and sometimes it is a different object. It depends on the integer value of the s string parsed. Determine the size: if the integer value corresponding to the s string is between -128~127, the parsed Integer type object is the same object; if the integer value corresponding to the s string is not between -128~127, then The parsed Integer type object is not the same object. Regardless of whether the objects are equal, the value values ​​in the objects are equal.

Is String thread-safe?

The String class is modified by final, the value of the String class is stored in the value array, and the value array is modified by private final, and the String class does not provide a method to modify the string.

1. Private modification, indicating that external classes cannot access value, and subclasses cannot access it. Of course, the String class cannot have subclasses, because the class is final modified.
2. Final modification, indicating that the reference to value is not will be changed, and value will only be initialized in the constructor of String, and there is no other way to modify the value in the value array, ensuring that neither the reference nor the value of value will change.

So we say that String class is immutable.

Why is there a constant pool?

The constant pool is used to avoid frequent creation and destruction of objects that affects system performance, and it implements object sharing.

Changes in the new version

Java 9 changes the underlying implementation of String from char[] to byte[]

The difference between StringBuffer and StringBuilder

StringBufferA synchronization lock is added to the method or a synchronization lock is added to the calling method, so it is thread-safe.

StringBuilderThere is no synchronization lock added to the method, so it is not thread-safe.

The difference between StringBuilder and StringBuffer in buffers:

Every time StringBuffer gets toString, it will directly use the toStringCache value of the buffer area to construct a string. and

StringBuilder needs to copy the character array each time and then construct a string.

Performance of String, StringBuffer and StringBuilder

Every Stringtime the type is changed, a new Stringobject is generated and the pointer is pointed to the new Stringobject.

StringBufferEach time StringBufferthe operation is performed on the object itself, rather than creating a new object and changing the object reference.

StringBuilderCompared with using under the same circumstances StringBuffer, you can only get about 10%~15% performance improvement, but you will run the risk of multi-threading insecurity.

What is the difference between String#equals() and Object#equals()?

StringThe method in equalshas been overridden, and compares whether the values ​​of String strings are equal. ObjectThe equalsmethod compares the memory addresses of objects.

Advantages of String being non-edgeable

  1. Facilitates the implementation of string constant pool

  2. String is often used as a parameter. String immutability can ensure that the parameters are immutable.

    For example, the username and password of the database are passed in as strings to obtain the database connection, or in socket programming, the host name and port are passed in as strings. Because a string is immutable, its value cannot be changed, otherwise hackers can exploit loopholes and change the value of the object pointed to by the string, causing a security vulnerability.

  3. Guaranteed thread safety

  4. Speed ​​up string processing, because strings are immutable, so the hashcode is cached when it is created and does not need to be recalculated. This makes strings very suitable as keys in Maps, and strings can be processed faster than other key objects. This is why the keys in HashMap often use strings.

What is the difference between List<? super T> and List<? extends T>?

Reference answer

  • ? is a type wildcard, List<?>which can represent the parent class of various generic Lists, meaning a List whose element type is unknown;
  • List<? super T>Used to set the lower limit of type wildcards, where ? represents an unknown type, but it must be the parent type of T;
  • List<? extends T>Used to set the upper limit of type wildcards, where ? represents an unknown type, but it must be a subtype of T.

Further reading

In the early design of Java, it was allowed to assign Integer[] arrays to Number[] variables. At this time, if you try to save a Double object into the Number[] array, the compilation will pass, but an ArrayStoreException exception will be thrown at runtime. This is obviously an unsafe design, so Java has made improvements in the generic design. It no longer allows List<Integer>objects to be assigned to List<Number>variables.

Arrays are different from generics. Suppose Foo is a subtype (subclass or subinterface) of Bar, then Foo[] is still a subtype of Bar[], but not a subtype G<Foo>of G<Bar>. The way Foo[] is automatically upcast to Bar[] is called type variation. That is to say, Java arrays support type variation, but Java collections do not support type variation. The design principle of Java generics is that as long as the code compiles without warnings, it will not encounter runtime ClassCastException exceptions.

What are the commonly used methods in the Object class?

wait notifyAll notify getClass hashcode equals clone toString

The difference between == and equals()

==The effects are different for basic types and reference types:

  • For basic data types, ==values ​​are compared.
  • For reference data types, ==the comparison is the memory address of the object.

equals()It cannot be used to determine variables of basic data types, but can only be used to determine whether two objects are equal. equals()Methods exist in Objectclasses, and Objectclasses are the direct or indirect parent class of all classes, so all classes have equals()methods.

equals()There are two usage cases for the method:

  • The class has no overridden equals()method : equals()comparing two objects of this class is equivalent to comparing the two objects through "==", and the default method used is the Objectclass equals()method.
  • The class overrides equals()the method : Generally, we override equals()the method to compare whether the attributes in the two objects are equal; if their attributes are equal, true is returned (that is, the two objects are considered equal).

HashCode和equals

If equals is not rewritten, the default is "==". For reference objects, the comparison is the memory address. In business, what is compared is whether the contents are equal, so equals needs to be rewritten.

If equals is equal, then according to the rules in Java, the hashcode of the object is also equal.

The Hashcode method returns the memory address of the object mapped to a hash value, so if the hashCode() method is not overridden, the hashCode() method of any object is not equal.

Why provide two methods, hash and equals?

This is because in some containers (such as HashMap, HashSet), hashCode()it will be more efficient to determine whether the element is in the corresponding container (refer to the process of adding elements HastSet)!

We also mentioned HastSetthe process of adding elements earlier. If there are multiple objects HashSetof the same type during comparison hashCode, it will continue to use equals()to determine whether they are really the same. In other words, hashCodeit helps us greatly reduce the search cost.

Do you understand the exception class in Java?

Both Exception and Error inherit from the Throwable class. In Java, only instances of the Throwable type can be thrown or caught by the program. It is the basic type of the exception handling mechanism.

Error, which indicates an error that the program cannot handle. For example, Java virtual machine running error ( Virtual MachineError), virtual machine insufficient memory error ( OutOfMemoryError), class definition error ( NoClassDefFoundError), etc. Will terminate the running of the JVM

Exception, which represents an exception that the program may catch or that the program can handle. The exception class Exception is divided into runtime exception (RuntimeException) and compile-time exception. Compile-time exception means that during the compilation process of Java code, if the checked exception is not handled by the catchor throwskeyword, it will not be able to pass the compilation. Runtime exceptions are during the compilation process of Java code. We can compile normally even if we do not handle unchecked exceptions. For example: NullPointerException(null pointer error), ArrayIndexOutOfBoundsException(array out of bounds error), etc.

Differences in relationships between JDK JVM JRE

The Java Virtual Machine (JVM) is a virtual machine that runs Java bytecode. The JVM has specific implementations for different systems (Windows, Linux, macOS) with the goal that using the same bytecode they will all give the same results. Bytecode and JVM implementation of different systems are the key to "compile once, run anywhere" of the Java language.

JDK is a java development kit, [Java Development Kit], including Java Runtime Envirnment, a bunch of Java tools (javac/java/jdb, etc.) and Java basic class libraries (i.e. Java API including rt.jar ).

      bin:最主要的是编译器(javac.exe)
      include:java和JVM交互用的头文件
      lib:类库
      jre:java运行环境

JRE (Java Runtime Environment, Java runtime environment) includes JVM standard implementation and Java core class library. JRE is a Java runtime environment, not a development environment, so it does not include any development tools (such as compilers and debuggers)

  1. JDK is used for development, and JRE is used to run Java programs; if you only want to run Java programs, you can install only JRE and install JDK out of order.
  2. JDk includes JRE, and both JDK and JRE include JVM.
  3. JVM is the core of java programming language and is platform independent.

Rounding function of Math class

  • The English meaning of ceil is the ceiling. This method means rounding up. The result of Math.ceil (11.3) is 12, and the result of Math.ceil (-11.6) is -11;
  • Floor means floor in English. This method means rounding down. The result of Math.floor(11.6) is 11, and the result of Math.floor(-11.4) is -12;
  • The most difficult thing to master is the round method, which means "rounding". The algorithm is Math.floor(x+0.5), which means adding 0.5 to the original number and then rounding down. Therefore, the result of Math.round(11.5) is 12. The result of Math.round(-11.5) is -11.

Parent delegation mechanism

Parental delegation refers to the rules for searching classes when calling the loadClass method of the class loader.

(1) If a class loader receives a class loading request, it will not try to load the class itself first, but will delegate the request to

Parent class loader to complete;

(2) If the parent class loader still has its parent class loader, it will delegate further upwards, recursively, and the request will eventually reach the top-level startup class loader.

carrier;

(3) If the parent class loader can complete the class loading task, it will return successfully; if the parent class loader cannot complete the loading task, the child loader will

The server will try to load it itself.

In conclusion:

(1) Check the loaded class. If there is no class, delegate it to the superior and search for it in the superior.

(2) If it is not found in the superior class loader, search it in your own class loader.

(3) If found in the upper level, load it in the upper level.

Advantages: (1) Avoid repeated loading of classes; (2) Protect program security and prevent core APIs from being modified (sandbox security mechanism); enable Java classes to have a priority hierarchy along with its class loader relationship, thereby unifying the base classes.

Ps: How does the Java virtual machine determine that two Java classes are the same:

(1) The full names must be the same

(2) The class loader that loads this class must be the same

Two classes are considered to be the same only if both are the same. Even if the same byte code is loaded by different class loaders, the classes obtained are different.

The parent delegation model is designed to ensure the type safety of the Java core library. All Java applications need to reference at least the java.lang.Object class, which means that the java.lang.Object class needs to be loaded into the Java virtual machine at runtime. If this loading process is completed by the Java application's own class loader, it is likely that there will be multiple versions of the java.lang.Object class, and these classes will be incompatible with each other. Through the parent delegation model, the loading of Java core library classes is uniformly completed by the startup class loader, ensuring that Java applications use the same version of the Java core library classes and are compatible with each other.

How to write a custom loader

You need to inherit the ClassLoader class or URLClassLoader and at least rewrite the findClass(String name) method. If you want to break the parental delegation mechanism, you need to rewrite the loadClass method.

Mainly loaded: class file with the path specified by yourself

abstract class

Not all classes in Java are used to describe objects. If a class does not contain enough information to describe a specific object, such a class is an abstract class.

Except that abstract classes cannot instantiate objects, other functions of the class still exist. Member variables, member methods, and constructors can be accessed in the same way as ordinary classes.

Since abstract classes cannot instantiate objects, abstract classes must be inherited before they can be used. For this reason, it is usually decided during the design stage whether to design an abstract class.

The parent class contains common methods for collections of subclasses, but because the parent class itself is abstract, these methods cannot be used.

The difference between abstract class and interface

From the design purpose, the two have the following differences:

**The interface embodies a specification. For the implementer of the interface, the interface stipulates what services the implementer must provide to the outside world; ** For the caller of the interface, the interface stipulates which services the caller can call and how to call these services. When an interface is used in a program, the interface is a coupling standard between multiple modules; when an interface is used between multiple applications, the interface is a communication standard between multiple programs.

Abstract classes embody a template design . As the abstract parent class of multiple subclasses, an abstract class can be regarded as an intermediate product in the system implementation process. This intermediate product has implemented some functions of the system, but this product still cannot be regarded as the final product and must be further improved. This This perfection may occur in several different ways.

In terms of usage, the differences between the two are as follows:

  • Interfaces can only contain abstract methods, static methods, default methods and private methods, and cannot provide method implementations for ordinary methods; abstract classes can contain ordinary methods.
  • Only static constants can be defined in interfaces, and ordinary member variables cannot be defined; in abstract classes, both ordinary member variables and static constants can be defined.
  • The interface does not contain a constructor; the abstract class can contain a constructor. The constructors in the abstract class are not used to create objects, but to let its subclasses call these constructors to complete the initialization operations belonging to the abstract class.
  • Interfaces cannot contain initialization blocks; but abstract classes can contain initialization blocks.
  • A class can only have at most one direct parent class, including abstract classes; but a class can directly implement multiple interfaces, and the shortcomings of Java single inheritance can be made up by implementing multiple interfaces.

Summary: The interface embodies a specification, while the abstract class embodies a template design. From the perspective of usage, the interface cannot contain ordinary methods, ordinary member variables, constructors and initialization blocks, but in abstract classes It can be included, in which the constructor method of the abstract class is not used to create objects, but to let its subclasses call these constructors to complete the initialization operation of the abstract class. A Java class can only inherit one parent class, but can implement multiple interfaces, which can make up for the shortcomings of Java single inheritance.

Further reading

Interfaces are very similar to abstract classes. They all have the following common characteristics:

  • Neither interfaces nor abstract classes can be instantiated. They are located at the top of the inheritance tree and are used to be implemented and inherited by other classes.
  • Both interfaces and abstract classes can contain abstract methods, and ordinary subclasses that implement the interface or inherit the abstract class must implement these abstract methods.

Usage scenarios of abstract classes and interfaces

The application scenarios of abstract classes are generally used to extract the common characteristics of different things , and then interfaces can be used to implement different behaviors of different things . When encountering a need, first analyze whether different objects have something in common. For example, doors can be opened and closed. This can be extracted and defined as an abstract class. Some doors have doorbells that can be pressed, and some doors do not. Then use The object with the doorbell implements the interface for the action of pressing the doorbell.

I流

IO (Input Output) is used to implement input and output operations on data. Java abstractly expresses different input/output sources (keyboard, file, network, etc.) as streams. A stream is an ordered stream of data from origin to reception that allows a program to access different input/output sources in the same way.

  • According to the data flow direction, the stream can be divided into input stream and output stream. The input stream can only read data but cannot write data, while the output stream can only write data but cannot read data.
  • According to the data type, the stream can be divided into byte stream and character stream. The data unit of byte stream operation is 8-bit byte, while the data unit of character stream operation is 16-bit character.
  • According to the processing function, the flow can be divided into node flow and processing flow. The node flow can directly read/write data from/to a specific IO device (disk, network, etc.), also known as low-level flow, while the processing flow is the processing flow. A connection or encapsulation of node streams used to simplify data read/write functionality or improve efficiency, also known as high-level streams.

The difference between final and finally

Final can be used to modify classes, methods, and variables, each with different meanings. The final- modified class means that it cannot be inherited and extended, the final variables cannot be modified, and the final methods cannot be overridden. Finally is a mechanism in Java to ensure that key code must be executed.

Generics

Java generics (generics) are a new feature introduced in JDK 5. Generics provide a compile-time type safety detection mechanism, which allows programmers to detect illegal types at compile time. The essence of generics is a parameterized type, which means that the data type being operated on is specified as a parameter.

Generics are generally used in three ways: generic classes, generic interfaces, and generic methods.

Generic class

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T> {
    private T key;
    public Generic(T key) {
        this.key = key;
    }
    public T getKey() {
        return key;
    }
}

Generic interface:

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

Generic methods

public static <E> void printArray(E[] inputArray) {
    for (E element : inputArray) {
        System.out.printf("%s ", element);
    }
    System.out.println();
}

use:

// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = {
    
     1, 2, 3 };
String[] stringArray = {
    
     "Hello", "World" };
printArray(intArray);
printArray(stringArray);

Guess you like

Origin blog.csdn.net/qq_43167873/article/details/130076692