Java basic interview -- serialization, reflection, copy

Posted by damien@damosworld.com on Sat, 05 Feb 2022 10:41:55 +0100

In the previous article, I have published common interview questions. Here I took some time to sort out the corresponding answers. Due to my limited personal ability, they may not be in place. If there are unreasonable answers, please give me some advice. Thank you here.

 

This paper mainly describes the basic content serialization, reflection and copy of java. These are often asked in the interview, especially the reflection, which is so powerful that the basic framework makes use of this knowledge point. In actual project development, serialization, reflection and copying are common knowledge points, so it is necessary to focus on mastering these contents.

 

How many methods can java create a class?

This is an interview question with byte beating. The original question means that in addition to new an object, what methods can Java use to build an object? This is a topic of java basic syntax, involving basic knowledge such as deserialization, copying, reflection and so on. These knowledge points are also common interview questions in Java interview. If the above method is suitable after answering, we can also properly expand the principles of serialization, copy and reflection. This will appear to have a relatively solid grasp of some knowledge points and leave some good impressions.

serialize

What is the role of Java serialization?

What is the principle of its underlying implementation?

What common serialization frameworks do you know, and what are their advantages and disadvantages?

There is a final Long id in the Java serialization class. What is the function of this serialization id? If not, can it be serialized successfully?

What if you don't want to serialize a field?

The questions described above are common interview questions in serialization, which are also explained here.

Functions of serialization:

As we all know, java takes object as the basic core concept. In java, everything is an object. In some scenarios, we need to transfer objects to other machines or write them to disk for storage. At this time, it is necessary to convert objects into binary. It is a process of converting objects into binary streams, and the serialization process is to complete this work. The corresponding process is the process of converting binary into objects, which is called deserialization process.

Steps for serialization:

The process of serialization in Java consists of the following processes:

  1. Implement Serializable interface in class object
  2. Define serialization id in class

Principle of serialization:

Here, we introduce java's default serialization and deserialization functions. That is, only the serialized interface is implemented according to the above steps. The underlying java is to convert objects into binary streams through ObjectOutputStream in the iO package. The core method in ObjectOutputStream is the writeObject. Its implementation is also to write to the stream by depth and type, array and string, null writing, etc. The core of the writeObject method is writeObject0 (if you look at the source code, you will find that many source codes like to use 0 to represent the real implementation or start with do). If you want to know more about the source code, you can see the previous jdk1 8 series of source code reading articles. On the contrary is the method of inverse sequence, that is, ObjectInputStream

public final void writeObject(Object obj) throws IOException {  
        if (enableOverride) {//If this method is allowed to be overridden, use the serialization method
            writeObjectOverride(obj);  
            return;  
        }  
        try {  
            writeObject0(obj, false);//Use default serialization method
        } catch (IOException ex) {  
            if (depth == 0) {  
                writeFatalException(ex);  
            }  
            throw ex;  
        }  
    }  

Serialization id:

In serialization, serialization id is actually a problem of version management. In fact, we will use it many times, because it is inevitable to modify fields during the use of an object. At this time, it is necessary to upgrade the serialization id to a version to distinguish the previous version. If we don't write the serialization id, we can serialize it successfully. If we don't write the serialization id, the jvm will generate one by default according to the corresponding rules, but there may be a problem at this time. However, if we upgrade the jdk, the serialization id may be different from the previous one, which will lead to the problem that the code cannot be serialized. Therefore, for the sake of safety, a serialization id is added at the time of code generation.

Transient:

If you don't want to serialize a field, you can use transient. Of course, static cannot be serialized. Static is the concept of class, while transient is a temporary concept.

Common serialization frameworks:

This kind of topic generally appears in the later aspects, because it is not a basic topic, but more an extension of knowledge system and knowledge. This is generally what architects need to understand and understand the advantages, disadvantages and selection of different frameworks. This general answer is a few, and its advantages and disadvantages are introduced. Generally, the serialization framework will compare the speed, the size after serialization, and whether it is cross language. The following is the result from the blog [java serialization performance comparison] (details: https://www.bbsmax.com/A/8Bz841mVzx/ ), there are several kinds of methods I usually use. protobuf, fastjosn and jdk have their own methods. You can have time to focus on them.

 

 

advantage

shortcoming

Kryo

Fast speed and small volume after serialization

Cross language support is complex

Hessian

Cross language support by default

slower

Protostuff

Fast, based on protobuf

Static compilation required

Protostuff-Runtime

There is no need for static compilation, but the schema needs to be passed in before serialization

Classes without default constructor are not supported. During deserialization, the user needs to initialize the serialized object, which is only responsible for assigning values to the object

Java

It is easy to use and can serialize all classes

Slow speed, occupying space

 

Copy

  1. What do you know about java copy? What is a deep copy and what is a shallow copy?
  2. How to implement a deep copy of java?

Deep and shallow copies:

The frequency of Java copy technology in the interview will be less than that of serialization. The content to be copied is to assign a value to an object. For a basic type, deep copy and shallow copy are the same, and a new copy will be copied. For an object type, if it is a shallow copy, the underlying access is the same object, which is similar to aliasing the object. Deep copy is as like as two peas. We will create a new object that is exactly the same as the object before, but the address at the bottom is completely different.

How to implement a deep copy of java:

In java, there is a clone method in the most basic parent class Object, and this method implements shallow copy, which is a native method. If we want to implement deep copy, we need to implement clonable interface and clone method. If the Object contains other objects, other objects should also be implemented. Let's see how to copy a class through clone.

import lombok.AllArgsConstructor;  
import lombok.Data;  
import lombok.NoArgsConstructor;  
@NoArgsConstructor  
@AllArgsConstructor  
@Data  
public class User implements Cloneable{  
    private String name;  
    private LoginInfo loginInfo;  
  
    @Override  
    protected Object clone() throws CloneNotSupportedException {  
        User clone= (User)super.clone();  
        //Call the underlying clone method to re assign the value, otherwise it is a shallow copy
        clone.loginInfo =(LoginInfo) clone.getLoginInfo().clone();  
        return clone;  
    }  
  
    @NoArgsConstructor  
    @AllArgsConstructor  
    @Data  
    public static class LoginInfo implements Cloneable{  
        private String id;  
        private String name;  
        //Also implement the clone interface
        @Override  
        protected Object clone() throws CloneNotSupportedException {  
            return super.clone();  
        }  
    }  
}  

 

Of course, in addition to the above methods, if there are many objects below, the call is also a relatively troublesome process. We can directly new an object, or implement deep copy, or through deserialization.

 

reflex

  1. What is the principle of reflection?
  2. How to implement a reflection? How many calling methods of reflection? What's the difference?

Reflection principle:

Reflection is a skill that Java programmers must master. It is similar to opening a back door for Java programmers. We can obtain the information of any class, including the properties and methods of this class, and obtain private information at runtime, which destroys the object-oriented encapsulation to a certain extent. So what is the principle of java reflection? The principle of reflection is basically divided into: loading classes into jvm - "querying class information according to requirements". This involves the class loading process in the jvm, which is also a common interview question type in the interview. Let's look at the principle of reflection through forName.

public static Class<?> forName(String className)  
                throws ClassNotFoundException {  
       //Getting the caller class is mainly to get the class loader
        Class<?> caller = Reflection.getCallerClass();  
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);  
    }  

forName0 is a native method, which will load classes. Class loading is the code that calls back the parent loading model of java.

protected Class<?> loadClass(String name, boolean resolve)  
        throws ClassNotFoundException  
    {  
        synchronized (getClassLoadingLock(name)) {//Lock
            //Check whether the class has been loaded
            Class<?> c = findLoadedClass(name);  
             //Parental delegation loading model
            if (c == null) {  
                long t0 = System.nanoTime();  
                try {  
                    if (parent != null) {  
                        c = parent.loadClass(name, false);//Load using parent class
                    } else {  
                        c = findBootstrapClassOrNull(name);//Try using the Java boot loader
                    }  
                } catch (ClassNotFoundException e) {  
                    // ClassNotFoundException thrown if class not found  
                    // from the non-null parent class loader  
                }  
                  //Parent loading failed, self loader loading failed
                if (c == null) {  
                    // If still not found, then invoke findClass in order  
                    // to find the class.  
                    long t1 = System.nanoTime();  
                    c = findClass(name);//Use self classloader
  
                    // this is the defining class loader; record the stats  
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);  
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);  
                    sun.misc.PerfCounter.getFindClasses().increment();  
                }  
            }  
            if (resolve) {//If it is linkable, link the specified class
                resolveClass(c);  
            }  
            return c;  
        }  
    }  

Use of reflection:

In java, we can dynamically obtain the information of a class in the following ways:

  1. Class.forName()
  2. Object.class
  3. Instance.getClass()
Class c1 =  Class.forName("com.java.base.learn.reflect.ReflectTest");  
//If you know the name of the class
Class c2=  ReflectTest.class;  
//If the object exists
ReflectTest reflectTest = new ReflectTest();  
Class c3  =reflectTest.getClass();  

The difference between the three is:

Class.forName will load the class and initialize the static code block by default. Of course, you can also set parameters to not initialize the static code block.

Object.Class only returns class information and does not do any initialization.

Instance.getClass() is the class object corresponding to the returned object.

You can build a with static code blocks, dynamic code blocks, and constructors to experiment. It is worth noting that no matter who calls, once the class is loaded, it will be retrieved from the cache and will not be loaded every time. If we need to obtain the instance of the obtained class, we will call another method class newInstance. Newinstance will initialize the class and call the constructor to initialize an object. This will be described in the following jvm interview questions.

There are so many contents in this article. If you think it is helpful for your study and interview, please praise it. thank you.

 

Want to know more java content (including big factory interview questions and questions) can pay attention to the official account, also can leave messages in official account, help push Ali, Tencent and other Internet factories.

                                                                   

           

Topics: Java Interview