@JvmOverloads
1 2 3 4 5 | class MyCustomerView constructor( context: Context, attrs: AttributeSet? = null, defStyleRes: Int = 0) : View(context, attrs, defStyleRes) |
Above is the code to create a custom view in Android. Quite familiar, isn’t it?
You will have no problems building. However, the unfortunate thing happens at runtime:
1 2 | Caused by: android.view.InflateException: Binary XML file line #10: Error inflating class com.myapplication.customview.MyCutomerView |
What is this error? The main reason in paragraph: View (context, attrs, defStyleRes)
Remember when creating a customer view class with java, we had to write 4 to 5 different constructors? In particular, the number of parameters in the constructor is different.
That is the cause of this error. Because we are missing the fun constructors needed for the View class.
-> @JvmOverLoads will solve this problem.
A case similar to the following:
1 2 | data class MyObject( val param1: String, val param2: String = "default string") |
With kotlin, it is possible to create an instance of MyObject with only param1 as follows:
1 2 | val obj1 = MyObject("param1") |
param2 will be created with the default value.
But if we initialize the above object in java as follows, the error will be:
1 2 | MyObject obj = new MyObject("param1"); |
We must explicitly pass all parameters of the constructor, including those that already have defaults.
To solve this problem, just fix the following:
1 2 | data class MyObject @JvmOverloads constructor( val param1: String, val param2: String = "default string") |
This is the description of the use of @JvmOverloads :
1 2 3 4 5 | Instructs the Kotlin compiler to generate overloads for this function that substitute default parameter values. If a method has N parameters and M of which have default values, M overloads are generated: the first one takes N-1 parameters (all but the last one that takes a default value), the second takes N-2 parameters, and so on. |
Quite explicit, isn’t it. It will simply help create the number of functions (or constructors) corresponding to the param value with the default value.
@JvmStatic
At first glance, it is possible to know the use of this annotation to create functions or properties in the static form.
In fact, if only pure kotlin code, we will rarely use this anno because there is one type of static definition seems more popular that is Top-level function.
However, the difference will lie in the companion object .
1 2 3 4 5 6 7 8 9 10 11 12 | class A { companion object { fun funNotStatic() { } @JvmStatic fun funStatic() { } } } |
Usually, if we need to call these fun from another kotlin class, we just need to
1 2 3 | A.funNotStatic() hoặc A.funStatic() |
However, what if you want to call them from a java class? Now @JvmStatic will have its role.
1 2 3 | A.Companion.funNotStatic(); funStatic(); |
As you can see, thanks to @JvmStatic , funStatic () is called directly without any need for the class names that contain it. In contrast to funNotStatic, we must explicitly A.Companion
@JvmField
1 2 | data class Test constructor(val x1: String) |
To get the value x1, do the following:
In kotlin:
1 2 3 | val test = Test("") test.x1 |
In java:
1 2 3 | Test test = new Test(""); test.getX1(); |
java will not access variables directly but through getter and setter.
Now, we will add @JvmField as follows:
1 2 | data class Test constructor(@JvmField val x1: String) |
Instructs the Kotlin compiler not to generate getters / setters for this property and expose it as a field.
This anno will cancel the getter, setter of the variable, which can instead allow direct axis access. So in the above java code, it is possible to write test.x1 similar to kotlin.