When I first began writing Kotlin, one of my favorite benefits was default arguments. This is a way for you to create a function (or constructor) that would accept default values for something. This way, the user of that method would only have to give you what you need. However, that ability to overload functions with default values doesn't interrop 1-1 to Java, and if you are going to be using both languages in your app, you'll need to be sure to include the @JvmOverloads
annotation. This post explains the interrop problem and how that annotation solves it.
Overloaded Constructors In Java
在展示它们在Kotlin中的工作方式之前,这是通常如何用Java编写重载的构造函数:
public class Task {
private String description;
private Date date;
private boolean isCompleted;
public Task() {
this("");
}
public Task(String description) {
this(description, new Date());
}
public Task(String description, Date date) {
this(description, date, false);
}
public Task(String description, Date date, boolean isCompleted) {
this.description = description;
this.date = date;
this.isCompleted = isCompleted;
}
}
Default Parameters In Kotlin
这是在Kotlin中定义类的方式,或者我想:
// In Task.kt
data class Task(var description: String? = "", var date: Date? = Date(), var isCompleted: Boolean = false)
// In MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
// All of these statements are valid
val task1 = Task()
val task2 = Task("Test")
val task3 = Task("Test", Date())
val task4 = Task("Test", Date(), false)
}
在不失去任何灵活性的情况下,很快就会意识到使用默认参数节省了多少时间和代码。 还是我们?
The Java Interrop Snag
在使用默认参数编写了上面的Kotlin类之后,我想在Java中使用相同的想法,但是不幸的是它不起作用:
Task task1 = new Task(); // Valid - Java allows default constructor
Task task2 = new Task("Test"); // Compiler error - no constructor
Task task3 = new Task("Test", new Date()); // Compiler error - no constructor
Task task4 = new Task("Test", new Date(), false); // Valid
我立即感到困惑。 它可以在Kotlin上运行,但不能在Java上运行,而且我知道有100%的插入,因此我开始研究它们之间的区别。 它非常简单-Kotlin具有自己的构造函数,可以根据需要处理诸如默认参数之类的规则-与Java分开。 但是,如果我们确实希望完整的Java插入,则需要创建所有必要的重载。
JvmOverloads Annotation
Thankfully, the solution is just a simple annotation. @JvmOverloads tells the Kotlin compiler to generate an overload for the constructor or function for however many default arguments are supplied. Adding it, our data class would look like this:
data class Task @JvmOverloads constructor(var description: String? = "", var date: Date? = Date(), var isCompleted: Boolean = false)
现在,只要我们在Java中使用此类,就可以使用我们认为必要的重载版本的构造函数,并且仍然只需要一行Kotlin代码即可定义该对象。