Basic interview knowledge of Java

1, IO and NIO of Java

1. Java NIO provides different IO working modes from standard IO

  • Channels and Buffers: standard IO operates based on byte stream and character stream, 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;
  • Asynchronous IO: Java NIO can use IO asynchronously. For example, when a thread reads data from a channel to a buffer, the thread can also do other things. When the data is written to the buffer, the thread can continue to process it, and the writing channel from the buffer is similar;
  • Selector: Java NIO introduces the concept of selector, which is used to listen to events of multiple channels (such as connection opening and data arrival). Therefore, a single thread can listen to multiple data channels.

2. Usage scenario

NIO

  • The advantage is that one thread manages multiple channels; But data processing will become complex;
  • If you need to manage thousands of connections opened at the same time, these connections only send a small amount of data each time, this method is adopted;

Traditional IO

  • It is applicable to the case that a thread manages a channel, because the stream data reading is blocked;
  • If you need to manage and open not too many connections at the same time, these connections will send a large amount of data. Use this method.

3. Difference between NiO and IO

Conceptual difference: NIO gives the blocking to the background thread for execution;

(1) IO is stream oriented and NIO is buffer oriented

Java IO is stream oriented, which means that one or more bytes are read from the stream at a time until all bytes are read, and they are not cached anywhere. In addition, it cannot move the data in the stream back and forth. If you need to move the data read from the stream back and forth, you need to cache it into a buffer first;

The buffer oriented method of Java NIO is slightly different. It reads the data to a buffer that it will process later. When necessary, it can move the data back and forth in the buffer. This increases the flexibility in the processing process. However, you also need to check whether the buffer contains all the data to be processed, and you need to ensure that when more data is read into the buffer, the unprocessed data in the buffer is not overwritten.

(2) IO flow is blocked, NIO is not blocked

In terms of name, N of NIO has two meanings: New IO and non blocking io

Various streams of Java IO are blocked, which means that when a thread calls read() or write(), the thread is blocked until some data is read or completely written, and the thread can't do anything during this period;

The non blocking mode of Java NIO enables a thread to send a request to read data from a channel, but it can only get the currently available data. If there is no data available, it will not get anything; NIO allows users to manage multiple channels (network connections or files) using only one (or more) single thread, but the cost is that parsing data may be more complex than reading data from a blocked stream; The same is true for non blocking write. A thread requests to write some data to a channel, but does not need to wait for it to write completely. This thread can do other things at the same time.

(3) Selector

The selector of Java NIO allows a single thread to monitor multiple input channels. You can register multiple channels, use a selector, and then use a single thread to "select" channels: these channels already have input that can be processed, or select channels that are ready to be written. This selection mechanism makes it easy for a single thread to manage multiple channels.

2, Java reflection

reference material

Java reflection explanation

1. What is reflection

Java reflection is to know all the properties and methods of any class in the running state; For any object, you can call any of its methods and properties; And can change its properties. This is also a key property that Java is regarded as dynamic (or quasi dynamic, because generally speaking, the definition of dynamic language is that the program structure or variable type can be changed when the program is running. This language becomes a dynamic language. From this point of view, Perl, Python and Ruby are dynamic languages, while C + +, Java and c# are not dynamic languages).

2. What can reflection do

Reflection mechanism allows the program to obtain the internal information of any class with known name at runtime, including its modifiers, fields, methods, etc., and can change the contents of fields or call methods at runtime. In this way, the code can be written more flexibly. The code can be matched when running, and there is no need to link the source code between components, so as to reduce the coupling degree of the code; There are also the implementation of dynamic agent and so on; However, it should be noted that improper use of reflection will cause high resource consumption.

3. Concrete realization of reflection

For example, a basic class Person:

public class Person {
    //Private property
    private String name = "Tom";
    //Public attribute
    public int age = 18;
    //Construction method
    public Person() {
    }
    //Private method
    private void say(){
        System.out.println("private say()...");
    }
    //public Method 
    public void work(){
        System.out.println("public work()...");
    }
}

(1) Three ways to get Class

  • It is usually obtained by calling the getClass() method through an Object. For example, when an Object of type Object is passed, but we don't know what class it is, we use this method:

    Person p1 = new Person();
    Class c1 = p1.getClass();
    
  • Directly through the class name Class, this method is the most safe and reliable, and the program performance is higher, which shows that any class has an implicit static member variable class

    Class c2 = Person.class;
    
  • It is obtained through the static method forName() of Class class. It is most used, but ClassNotFoundException may be thrown

    Class c3 = Class.forName("com.ys.reflex.Person");
    

It should be noted that there will only be one Class instance in the JVM for a Class, that is, if we compare the equals of C1, C2 and C3 above, the result is true.

(2) Get member variables, member methods, interfaces, superclasses, construction methods, etc. through Class

Looking at the API, you can see that Class has many methods:

getName(): get the full name of the class

getFields(): get the public type attributes of the class, including the attributes inherited from the parent class

getDeclaredFields(): you can get all the attributes of this class, including private, but you can't get the inherited fields. (Note: only the private field can be obtained here, but the value of the private field cannot be accessed unless setaccessible (true) is added.)

getMethods(): all public methods, including the public methods of their inherited classes and, of course, the methods of the interfaces it implements

getDeclaredMethods(): get all the methods of the class. Package, protected (default), and inherited methods are not included. Of course, it also includes the methods of the interface it implements

getMethod(String name, Class[] parameterTypes): get the specific method of the class. The name parameter specifies the name of the method, and the parameterTypes parameter specifies the parameter type of the method

getConstructors(): get the constructor of the public type of the class

getConstructor(Class[] parameterTypes): get the specific constructor of the class. The parameterTypes parameter specifies the parameter type of the constructor

newInstance(): create an object of this class through the class's construction method without parameters

Examples:

//Get the full name of the class
String className = c2.getName();
System.out.println(className);//Output com ys. reflex. Person

//Get the public type property of the class.
Field[] fields = c2.getFields();
for(Field field : fields){
   System.out.println(field.getName());//age
}

//Get all properties of the class. Including private
Field [] allFields = c2.getDeclaredFields();
for(Field field : allFields){
    System.out.println(field.getName());//name    age
}

//Gets the method of the public type of the class. Here are some methods of the Object class
Method [] methods = c2.getMethods();
for(Method method : methods){
    System.out.println(method.getName());//work waid equls toString hashCode, etc
}

//Get all the methods of the class.
Method [] allMethods = c2.getDeclaredMethods();
for(Method method : allMethods){
    System.out.println(method.getName());//work say
}

//Gets the specified property
Field f1 = c2.getField("age");
System.out.println(f1);
//Gets the specified private property
Field f2 = c2.getDeclaredField("name");
//The switch to enable and disable access security check. If the value is true, it means that the access check of java language should be cancelled when the reflected object is used; Otherwise, it will not be cancelled
f2.setAccessible(true);
System.out.println(f2);

//Create an object of this class
Object p2 =  c2.newInstance();
//Assign the f2 attribute of p2 object to Bob, and the f2 attribute is the private attribute name
f2.set(p2,"Bob");
//Using reflection mechanism can break the encapsulation, which leads to the unsafe properties of java objects.
System.out.println(f2.get(p2)); //Bob

//Get construction method
Constructor [] constructors = c2.getConstructors();
for(Constructor constructor : constructors){
    System.out.println(constructor.toString());//public com.ys.reflex.Person()
}

4. Get parent class attribute according to reflection

Parent class:

public class Parent {
    public String publicField = "parent_publicField";
    protected String protectField = "parent_protectField";
    String defaultField = "parent_defaultField";
    private String privateField = "parent_privateField";

}

Subclass:

public class Son extends Parent {
}

Test:

public class ReflectionTest {

    @Test
    public void testGetParentField() throws Exception{
        Class c1 = Class.forName("com.ys.model.Son");
        //Gets the private property value of the parent class
        System.out.println(getFieldValue(c1.newInstance(),"privateField"));
    }

    public static Field getDeclaredField(Object obj,String fieldName) {
        Field field = null;
        Class c = obj.getClass();
        for(; c != Object.class ; c = c.getSuperclass()){
            try {
                field = c.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field;
            }catch (Exception e){
                //Don't do anything here! And the exception here must be written like this and cannot be thrown.
                //If the exception here is printed or thrown out, c = c.getSuperclass() will not be executed, and finally it will not enter the parent class
            }
        }
        return null;
    }
    public static Object getFieldValue(Object object,String fieldName) throws Exception{
        Field field = getDeclaredField(object,fieldName);

        return field.get(object);
    }
}

By executing the above code, you can obtain the private attribute value of the parent Class. It should be noted that the object that obtains the subclass directly through reflection cannot obtain the parent Class attribute value. You must obtain the subclass Class object according to the reflection, call the getSuperclass() method to obtain the parent Class object, and then obtain the parent Class attribute value through the parent Class object.

5. Reflection summary

Java reflection is to know all the properties and methods of any class in the running state; For any object, you can call any of its methods and properties; And can change its properties.

Combined with the JVM class loading process:

Class.forName and classloader Loadclass() difference

Class.forName except for the class When the class file is loaded into the JVM, it will also parse the class and execute the static block in the class; The classloader only does one thing, that is, it will When the class file is loaded into the JVM, the static block will not be executed. The static block will be executed only when newInstance(). The class obtained by forName("") has been initialized;

The most important difference is that forName initializes the Class, but loadClass does not. Therefore, if the static variables of the Class are required to be initialized during loading or the code of the static block is executed, forName can only be used, while loadClass can only be initialized when the Class instance is created.

Class.forName(className)Method. The method actually called internally is  Class.forName(className,true,classloader);

2nd boolean Parameter indicates whether the class needs to be initialized, Class.forName(className)Initialization is required by default. Once initialized, the target object is triggered static Block code execution, static The parameter will also be initialized again.

    
ClassLoader.loadClass(className)Method. The method actually called internally is  ClassLoader.loadClass(className,false);

2nd boolean Parameter, indicating whether the target object is linked, false It means no linking. As described above, no linking means that some steps including initialization are not carried out, so static blocks and static objects will not be executed

Flexible use of reflection can make our code more flexible. For example, JDBC native code registration driver, Hibernate entity class and Spring AOP all have the implementation of reflection, but the disadvantage of reflection is to consume system performance and increase complexity.

3, final keyword

It is used to modify data, including member variables and local variables. This variable can only be assigned once and its value cannot be changed;

For member variables, the modified class variables must be initialized at the time of declaration; A modified instance variable must be assigned a value when it is declared or in the constructor;

Used to modify method parameters, indicating that its value cannot be changed in the life cycle of a variable;

Modifier class, indicating that the class cannot be inherited.

4, ArrayList and LinkedList

(1) ArrayList is a data structure based on dynamic array, and LinkedList is a data structure based on linked list;

(2) For random access to get and set, ArrayList is better than LinkedList because LinkedList needs to move the pointer;

(3) For add and remove operations, LinkedList is better than ArrayList because ArrayList moves data.

Tags: Java

Posted by mikemessiah on Wed, 11 May 2022 23:09:19 +0300