简体   繁体   English

从 Java 类调用时,Kotlin 数据类复制功能不起作用

[英]Kotlin data class copy function not working when called from java class

Maybe I'm misinterpreting how the copy function of a data class works or maybe there's a bug, but the following is an example of the copy function not working as expected:也许我误解了data类的copy功能是如何工作的,或者可能存在错误,但以下是copy功能未按预期工作的示例:

Kotlin:科特林:

data class A {
    public var x: String? = null
    public var y: String? = null
    public var z: B = B.ONE
}

enum class B {
    ONE
    TWO
    THREE
}

Java爪哇

A a1 = new A()
a1.setX("Hello")
a1.setY("World")
a1.setZ(B.TWO)

A a2 = a1.copy()
// a2.x is null
// a2.y is null
// a2.z is B.ONE

It seems that copy is just making a new instance of A and not copying the values.似乎copy只是制作A的新实例而不是复制值。 If I put the variables in the constructor, the values are assigned, but then it's no different than constructing a new instance.如果我将变量放在构造函数中,则会分配值,但这与构造新实例没有什么不同。

Okay, I missed this sentence in the docs:好的,我在文档中遗漏了这句话:

If any of these functions is explicitly defined in the class body or inherited from the base types, it will not be generated.如果这些函数中的任何一个在类主体中显式定义或从基类型继承,则不会生成它。

Which, infact, makes copy no better than a constructor for Java interop.事实上,这使得copy并不比 Java 互操作的构造函数更好。

What you can do to get around the limitations of Kotlin's copy(), is to create your own copy function inside your data class.为了绕过 Kotlin 的 copy() 的限制,您可以做的是在您的数据类中创建您自己的复制函数。 Example below:下面的例子:

data class User(val name : String, val property: String) {

    fun copy() : User {
      //uses the fields name and property defined in the constructor
      return User(name,property)
    }

    //or if you need a copy with a changed field
    fun copy(changedProperty : String) : User {
      return User(name, changedProperty)
    }

}

For interop with java you can make function that use kotlin generated .copy对于与 java 的互操作,您可以创建使用 kotlin 生成的 .copy 的函数

@Entity
data class User(@PrimaryKey var id: Int = 0,
            var firstName: String? = null,
            var lastName: String? = null,
            var phone: String? = null,
            var email: String? = null,
            var phoneCode: String? = null,
            var tokenId: String? = null,
            var provider: SocialProvider? = null) : Serializable {


var countryCodeIso: String? = null
    set(countryCodeIso) {
        if (countryCodeIso != null) {
            field = countryCodeIso.toLowerCase()
        }
    }

fun javaCopy(): User {
    val user = copy()
    user.countryCodeIso = countryCodeIso
    return user
}}

This question is high in search rankings, and potentially confusing for those new to kotlin, since the question's sample code is not typical kotlin code or usage of the copy function.这个问题在搜索排名中很高,对于那些刚接触 kotlin 的人来说可能会造成混淆,因为问题的示例代码不是典型的 kotlin 代码或复制函数的用法。 I added some sample code below to help clarify what's going on, and also show typical usage of a data class.我在下面添加了一些示例代码来帮助阐明发生了什么,并展示了数据类的典型用法。
In short, the copy function is most useful when called from a kotlin class.简而言之, copy函数在从 kotlin 类调用时最有用。 I agree that its behavior isn't obvious when called from java code.我同意从 java 代码调用时它的行为并不明显。

//
// A.kt
//

// this is an idiomatic kotlin data class. note the parens around the properties, not braces.
data class A(
    val x: String? = null,
    val y: String? = null,
    val z: B = B.ONE
) {
    // this javaCopy function is completely unnecessary when being called from kotlin; it's only here to show a fairly simple way to make kotlin-java interop a little easier (like what Nokuap showed).
    fun javaCopy(): A {
        return this.copy()
    }
}

enum class B {
    ONE,
    TWO,
    THREE
}

fun main() {
    val a1 = A("Hello", "World", B.TWO)

    // here's what copy usage looks like for idiomatic kotlin code.
    val a2 = a1.copy()
    assert(a2.x == "Hello")
    assert(a2.y == "World")
    assert(a2.z == B.TWO)

    // more typical is to `copy` the object and modify one or more properties during the copy. e.g.:
    val a3 = a1.copy(y = "Friend")
    assert(a2.x == "Hello")
    assert(a3.y == "Friend")
}
public class App {

    public static void main(String[] args) {
        A a1 = new A("Hello", "World", B.TWO);

        // the kotlin copy function is primarily meant for kotlin <-> kotlin interop
        // copy works when called from java, but it requires all the args.
        // calling the `javaCopy` function gives the expected behavior.
        A a2 = a1.javaCopy();
        assert a2.getX().equals("Hello");
        assert a2.getY().equals("World");
        assert a2.getZ().equals(B.TWO);
    }
}

Official docs on data classes, including the copy function:关于数据类的官方文档,包括copy功能:
https://kotlinlang.org/docs/reference/data-classes.html https://kotlinlang.org/docs/reference/data-classes.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从数据类到Java类调用Kotlin copy()? - How to call Kotlin copy() from data class to java class? 从另一个类调用时,Java PropertyChangeListener不起作用 - Java PropertyChangeListener not working when called from another class 从不同的类调用时,Java repaint()无法正常工作 - Java repaint() not working when called from a different class 数据类Kotlin到Java类 - Data class Kotlin to Java Class Java Class 从 Kotlin 中的适配器访问数据 - Java Class to access data from Adapter in Kotlin 当从另一个 class 调用时 Function 崩溃应用程序,但从 MainActivity.java 调用时不会崩溃 - Function crashing app when called from another class but not when called from MainActivity.java 在Java接口上调用.class时,将.class传递给Clojure函数 - Pass .class to Clojure Function when .class is called on a Java interface Kotlin 暂停 function 从 Java 调用时延迟后未执行 - Kotlin suspend function not executing after delay when called from Java 为什么当我从Kotlin项目程序调用Java类时总是停止工作 - why when I call java class from kotlin project program alway stop working Kotlin ArrayList <HashSet<data class> &gt; .reduce函数不使用ArrayList的子集 - Kotlin ArrayList<HashSet<data class>> .reduce function not working with subset of ArrayList
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM