How do you write something like this in Java in Kotlin? A memorandum of code comparison.
[Kotlin] [Java] Kotlin Java comparison memo This article specializes in the Null safety function part of.
I want to know the basics of Kotlin by comparing it with Java! Please see the above article for those who say.
--Can read and write Java to some extent --I can read Kotlin's basic grammar somehow ――I don't understand the meaning of Kotlin? -I want to know how to get rid of the type with?
It refers to a mechanism that does not allow nulls in principle.
For example, the following code
test.kt
val a: String = null
This will result in a compilation error. That's because Kotlin doesn't allow nulls by default. If you want to allow null, add? After the type.
test.kt
val a: String? = null //This is OK
A Null check is always required when accessing variables defined with options. Let's compare it with Java.
test.java
String a = null;
a.contains("hoge"); //Naturally it is null, so it falls with a nullpo
test.kt
var a: String? = null
a.contains("hoge") //It doesn't compile in the first place
This Kotlin source is played at compile time. This is because non-null is not guaranteed. To access Nullable types:
test.kt
val a: String? = null
a?.contains("hoge")
For a Nullable type function call, just do something like ?. If a is Null, contains will not be executed and Null will be returned.
When I try to achieve this with Java,
First of all, the familiar Null check.
test.java
String a = null;
if (a != null) {
a.contains("hoge"); //If null, it won't pass here
}
With Java 8, you can use the equivalent function called Optional.
test.java
Optional<String> a = Optional.of(null);
a.ifPresent(notNull -> notNull.contains("hoge")) //contains is executed only when the content of a is not null
You can see that it can be written very concisely compared to Java, Java is just a run-time check, so even if you use Java 8 Optional In the first place, it is not a fundamental solution when you forget to use Optional. Kotlin is checked at compile time, so Null check is not missed.
But Kotlin's Null safety features aren't perfect either. For example, when calling a Java method from Kotlin as follows
test.kt
var str = System.getProperty("hoge") //str is String!Mold
Java does not have a null safety feature, so Kotlin will force it to be assigned as a non-null type. If you force the Java value to be non-null, the type will be followed by a!
This is a bit tricky and behaves as non-null, but it could be null.
test.kt
var str = System.getProperty("hoge")
var strLength = str.length //Because it's not a Nullable type?.I don't need
But of course getProperty ("hoge ")
can be returned as null, so strLength can drop with a nullpo.
This cannot be said to have ensured absolute Null safety.
If you explicitly declare it as Nullable type when receiving the return value of Java method, it will be Nullable type.
test.kt
var str: String? = System.getProperty("hoge")
var strLength = str?.length //Because it is a Nullable type?.Is necessary
It is very difficult to handle this. .. If you want to completely eradicate Null, you need to explicitly make it Nullable.
Let's look at the previous example again
test.kt
var str: String? = System.getProperty("hoge")
var strLength = str?.length
In this case, the type of the variable str is String?
, So the strLength to which the value of str length is assigned is ʻInt?`.
In other words, if the type of the assignment source is Nullable, the variable of the assignment destination will also be Nullable.
With this, only variables that Nullable is premised on are created, and the benefits of the Null safety function cannot be fully received.
If you want to make the type that was once Nullable non-null, there are the following two methods
test.kt
var str: String? = System.getProperty("hoge")
var foo = str!!.length // !!You can force str to be of type String by
//foo becomes Int type
If the type that is once Nullable is !!
,? Will be removed.
test.kt
var str: String? = System.getProperty("hoge")
str = str!! //str becomes a String type
var foo = str.length // non-Because it's null?.Or!!.No operator needed
Naturally, if str is Null, it will fall with a slimy po. There is no point in making it a Nullable type.
test.kt
var str = System.getProperty("hoge") ?: "Unknown Property"
var foo = str.length //str becomes a String type
This ?:
Is called the Elvis operator, and evaluates the right expression when the result of the left expression of?: Is Null.
test.java
String str = System.getProperty("hoge") != null ? System.getProperty("hoge") : "Unknown Property";
Synonymous with.
Even if Systrem.getProperty ("hoge") is Null, a dedicated value is returned at that time, so
str becomes String type
and foo becomes ʻInt type`.
The Nullable type is gone and you can handle variables safely.
If you do not want to return a dedicated value, that is, if it is Null, you do not want to continue the subsequent processing.
test.kt
var str = System.getProperty("hoge") ?: return //str becomes a String type
Then, if System.getProperty ("hoge ")
is Null, you can exit the processing of that block.
test.kt
var str = System.getProperty("hoge") ?: return //str becomes a String type
By unwrapping like this, it no longer falls off with a slimy po, but However, it is not possible to detect an error just by returning and exiting the process without failing. In the first place, this code should assume that System.getProperty ("hoge") is not null.
If you want to detect an unexpected return without generating a nullpo
test.kt
var str = System.getProperty("hoge") ?: run {
println("Property was not found!!!")
return
}
It is necessary to make some kind of log spit out like this.
The explanation of run
is omitted because it is out of this scope.
Like Android View, it cannot be initialized at the time of instantiation, There are also cases where it has to be initialized within a specific method such as ʻonCreate`.
test.kt
class HogeActivity: AppCompatActivity(){
private var textView: TextView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.hoge_layout)
textView = findViewById(R.id.textView) as TextView
}
}
Since textView cannot be obtained unless it is inflated with onCreate, The initial value must be null. In that case, the type will be Nullable like TextView ?.
There are two approaches to making this TextView non-null type.
lateinit
is an operator for lazy evaluation of initialization, and compilation can be performed without setting the initial value when defining variables.
test.kt
class HogeActivity: AppCompatActivity(){
private lateinit var textView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.hoge_layout)
textView = findViewById(R.id.textView) as TextView
}
}
It is no longer necessary to set the initial value at the same time as the variable declaration because the? Is removed from the textView type. The value is entered in textView for the first time with findViewById.
However, what you have to be careful about with lateinit is that it can only be used for variables (var). If the getter is called before the setter is called, it will crash.
The explanation of by
is a little complicated by this alone, so I will not explain it in detail,
A qualifier that allows you to delegate property settings to another class.
lazy
is a function that is executed the first time you access a property that defines lazy.
By combining the two, you can initialize variables with any function in another class.
test.kt
class HogeActivity: AppCompatActivity(){
private val textView: TextView by lazy { findViewById(R.id.textView) as TextView }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.hoge_layout)
}
}
This way, when the textView getter is called for the first time, before the getter
findViewById(R.id.textView) as TextView
Is executed and the initial value is entered.
By lazy, on the contrary, can only be used for constants (val). Instead, you don't have to worry about crashing like lateinit.
If you can use by lazy, I think it's better to use this. Is the use of lateinit such as the case defined by another class like DI dagger?
Null safety is a powerful feature, but it's not a silver bullet that solves everything. On the contrary, it can be said that it prevents the spread of defects to other sources because it falls off with a slimy po.
When using the Null safety function, I want to understand the danger behind it before using it.
Recommended Posts