Java Kotlin-为非数据类生成toString()

Java Kotlin-为非数据类生成toString(),java,kotlin,tostring,Java,Kotlin,Tostring,情况: 我有一个带有lateinit字段的类,因此它们不在构造函数中: class ConfirmRequest() { lateinit var playerId: String } 我希望有一个包含所有字段的toString()方法,并且不希望手动编写,以避免打印。在Java中,我会使用Lombok@ToString注释来解决这个问题 问题: 有什么方法可以在Kotlin中实现它吗?推荐的方法是手动编写toString(或通过IDE生成),希望不要有太多这样的类 数据类的目的是适应

情况:

我有一个带有
lateinit
字段的类,因此它们不在构造函数中:

class ConfirmRequest() {
    lateinit var playerId: String
}
我希望有一个包含所有字段的
toString()
方法,并且不希望手动编写,以避免打印。在Java中,我会使用Lombok
@ToString
注释来解决这个问题

问题:


有什么方法可以在Kotlin中实现它吗?

推荐的方法是手动编写
toString
(或通过IDE生成),希望不要有太多这样的类


数据类
的目的是适应85%的最常见情况,剩下15%留给其他解决方案。

像你一样,我习惯于在Java中使用lombok来表示
toString()
equals()
,所以对于Kotlin中的非数据类需要所有标准样板文件,我有点失望

因此,我创建了一个开源库,它允许您实现
toString()
equals()
,而无需任何样板文件-只需提供属性列表,您就完成了

e、 g


我发现Apache Commons Lang的带有反射的
ToStringBuilder
很有用,但它调用
hashCode()
和其他我不需要的方法(从第三方库调用
hashCode()
的方法会生成NPE)

所以我只想说:

// class myClass
    override fun toString() = MiscUtils.reflectionToString(this)

// class MiscUTils
fun reflectionToString(obj: Any): String {
    val s = LinkedList<String>()
    var clazz: Class<in Any>? = obj.javaClass
    while (clazz != null) {
        for (prop in clazz.declaredFields.filterNot { Modifier.isStatic(it.modifiers) }) {
            prop.isAccessible = true
            s += "${prop.name}=" + prop.get(obj)?.toString()?.trim()
        }
        clazz = clazz.superclass
    }
    return "${obj.javaClass.simpleName}=[${s.joinToString(", ")}]"
}
//类myClass
override fun toString()=MiscUtils.ReflectionString(此)
//类杂项
字符串(对象:任意):字符串{
val s=LinkedList()
var clazz:Class?=obj.javaClass
while(clazz!=null){
for(clazz.declaredFields.filterNot{Modifier.isStatic(it.modifiers)}中的prop){
prop.isAccessible=true
s+=“${prop.name}=“+prop.get(obj)?.toString()?.trim()
}
clazz=clazz.superclass
}
返回“${obj.javaClass.simpleName}=[${s.joinToString(“,”)}”
}

您可以定义一个包含要使用的数据的数据类,并通过委托给该类来实现方法


使用Kotlin反射怎么样?我对Kotlin有几天的兴趣,所以若我误解了这个问题,或者写了“Kotlin低效”的例子,我向你们道歉


这也可以在新创建的接口中实现,例如ToString 2接口作为fun ToString 2。那么所有实现ToString 2接口的类都必须是ToString 2()

这就是我最后要做的

任何
类上创建扩展函数

fun Any.toStringByReflection(排除:List=listOf(),掩码:List=listOf()):字符串{
val propsString=this::class.memberProperties
.filter{exclude.isEmpty()| |!exclude.contains(it.name)}
.joinToString(“,”){
val value=if(!mask.isEmpty()&&mask.contains(it.name))“***”else it.getter.call(this.toString())
“${it.name}=${value}”
};
返回“${this::class.simpleName}[${propssString}]”
}
然后可以从单个类型调用此方法

override fun to字符串():字符串{
返回此.toStringByReflection()
}
它在下面生成字符串

Table [colums=[], name=pg_aggregate_fnoid_index, schema=pg_catalog, type=SYSTEM INDEX]
已屏蔽名称字段:

override fun toString(): String {
    return this.toStringByReflection(mask= listOf("name"))
}
它产生

Table [colums=[], name=****, schema=pg_catalog, type=SYSTEM INDEX]

Lombok可能仍然有效,不?Lombok注释不起作用,解释:我建议在同一个类中挑战对
lateinint var
和“data”
toString()
的需求。如果不进一步了解如何使用
ConfirmRequest
,就很难提出建议,但是
数据类ConfirmRequest(var playerId:String?=null)
对我来说似乎工作得很好。如果您知道它在
playerId==null
时永远不会被使用,那么您可以将数据成员设置为私有,并公开一个公共的非null属性以方便使用。该类是从JSON反序列化的,需要具有空constructor根据所使用的JSON库,实际上并不总是需要默认构造函数,例如,Jackson不需要它。好的,必须用IDE生成它。最后决定使用允许使用参数构造函数的
Jackson模块kotlin
,因此数据类现在适合我的需要:
data class ConfirmRequest(var playerId:String)
@awfun,
jackson模块kotlin
是否支持
数据类确认请求(val-playerId:String)
?关于lombok for java的好提示,希望我能早点知道:(是的,当时我关注的是性能。回过头来看,我可能会为了方便而添加它。简单的解决方案,但当人们不能使用数据类时,直觉就足够了,除了--您将得到字符串表示形式为
Bean=[property1$delegate={},property2$delegate={},property3$delegate={}]
。无论这有多酷,都不鼓励使用反射。正如Kotlin文档中所述:“这称为反射,性能不高,除非您真的需要,否则请避免使用它”()@TranseHead大体上同意反射是缓慢的。如果这不是用例的约束,那么这种方法是添加到字符串的快速方法。
override fun toString(): String {
    return this.toStringByReflection(mask= listOf("name"))
}
Table [colums=[], name=****, schema=pg_catalog, type=SYSTEM INDEX]