Unsafe Creating an instance

There are basically three ways to create an object in Java

    1. This is the most common one created with the new keyword
    1. It is also common to create objects through reflection constructors. It’s used in many frameworks.
    1. The Unsafe class creates an instance, which is very rare.

Here’s how Unsafe creates an instance.

Let’s start by creating a Pserson class

public class Person { public Person() { System.out.println("Person cons"); }}Copy the code

Create another User class

public class User extends Person { public String getName() { return name; } public void setName(String name) { this.name = name; } private String name; public User() { System.out.println("User cons"); }}Copy the code

Note that both classes are characterized by parameterless constructors

Then, how to manipulate an object that is User using Unsafe

try { Class klass = Unsafe.class; Field field = null; field = klass.getDeclaredField("theUnsafe"); field.setAccessible(true); Unsafe unsafe = (Unsafe) field.get(null); User user=(User) unsafe.allocateInstance(User.class); System.out.println(user.getName()); user.setName("wuyue"); System.out.println(user.getName()); System.out.println(" split line "); User user1=new User(); } catch (NoSuchFieldException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); }Copy the code

Then let’s look at the results:

Objects derived from Unsafe are used in the same way as objects derived from the new keyword. UnSafe, however, creates objects that don’t use constructors, meaning the constructor doesn’t walk.

You can take a look at the log:

Objects created using the Unsafe method before splitting have no constructor logs. (Many Java boys can’t believe this? The Unsafe class has many methods that are just as unprincipled.)

We’re not going to get into the underlying theory here (which I don’t know), but just keep that in mind

Kotlin’s non-null and non-null

Take a look at these two functions:

fun one(msg:String){

}

fun two(msg:String?){

}
Copy the code

The only difference is that function parameters here one is nullable and one is not nullable. Let’s decompile:

So you can see it’s pretty dangerous here. If your one function is called by a Java person, and he happens to pass in a null, then you’re going to throw an exception if you walk into one.

For example, if we call the one function in Java code with the user.getName() argument in the first section, it will definitely throw an error exception

Kotlin’s constructor

This is actually a very frustrating point. Everyone knows that in pure Java code if you don’t write any constructors, the compiler will generate one for you.

But in Kotlin, this feature is erased

For example:

Let’s start by defining a common class for Kotlin

class KUser(var name:String)
Copy the code

Then try calling it in Java code

You will find that this is not going to work, because this way of defining a class will not help you generate the default no-argument constructor.

Let’s try data Class again and see if we can do that

data class KUser2(var name: String)

Copy the code

Neither class nor data class in Kotlin will automatically generate a constructor with no arguments.

Is there a way to avoid this. Of course you can.

For example, we manually assign a default value to a defined attribute

class KUser(var name:String="")

data class KUser2(var name: String="")

Copy the code

Or manually specify a constructor that takes no parameters

data class KUser2(var name:String ,var age:Int){
    constructor():this("123",0)
}
Copy the code

As long as you specify that all attributes have default values, there will always be parameterless constructors

When Kotlin hits serialization

With that in mind, let’s look at the following example and make it much clearer.

Take a look at kotlin’s original post:

For Kotlin to work well with some serialization or deserialization frameworks, it is best to provide a no-argument constructor

Let’s take Gson for example:

The main logic gson follows when serializing a JSON string into a Javabean is as follows:

  1. Does this class have a no-argument constructor, and if it does use that no-argument constructor to construct the object if it doesn’t go to step 2
  2. The second step is actually to use unsafe to construct an object.

Let’s look at the first example:

data class KUser(var name:String,var age:Int)

fun main(){
    val gson= Gson()
    val person=gson.fromJson<KUser>(""" {"age":"12"} """,KUser::class.java)

    println(person.name)
}
Copy the code

Take a look at the output:

The json string contains no information about name, and the data class defines name as non-null

What if the output is null instead?

Let’s modify the code:

data class KUser(var name:String="123",var age:Int)

Copy the code

Run again and see the result:

I’ve already set it to 123 by default. Why is it null?

This time I will add the default value of age as well:

data class KUser(var name:String="123",var age:Int)

Copy the code

This is finally normal.

Let me explain why this is the case

In Kotlin, if you have n attributes, you must set the default values of each of these attributes to the default values to generate the default no-parameter constructor. Any less will not generate the no-parameter constructor

Therefore, the first and second results in the preceding example are easily interpreted. Since there is no safe-looking constructor, gson’s deserialization directly constructs the object, bypasing kotlin’s non-empty declaration, and therefore outputs null instead of an error

The last result is that I set both the name and age properties to default values, so I have a no-argument constructor and everything works fine.

Points to note when Kotlin calls Java functions

Null println(person) val gson= gson () val person= gson.fromjson ("",KUser::class.java Person2 :KUser?= gson.fromjson ("",KUser::class.java) // println(person2) // will crash because it is not null, Val person3:KUser= gson.fromjson ("",KUser::class.java) println(person3)Copy the code

To see why an error was reported, take a look at decompilation: