我使用静态编程语言反射来检查具有特定注释的属性是否为空。
给出以下示例:
data class DataClass(
@SomeRandomAnnotation
val otherAnnotated: String?,
val inner: InnerClass
)
data class AnotherDataClass(
@SomeRandomAnnotation
val annotatedProperty: String?,
val dataClass: DataClass
) {
fun checkCreditAnalysisConstrain() {
print(checkConstrain(this))
}
}
以及检查它的函数:
fun checkConstrain(parentClass: Any): List<String> {
val filter = parentClass::class.memberProperties.filter {
if (memberIsDataClass(it)) checkConstrain(getMemberPropertyInstance(parentClass, it))
hasAnnotation(it) && propertyIsNull(it, parentClass)
}
return filter.map { formatResult(parentClass, it) }
}
这个想法是,函数将迭代我的类的属性,检查它们是否有注释,并检查值是否为空。如果属性是一个数据类,代码会递归地计算Childs的属性。
之后,我映射结果,将KProperty转换为一个简单的字符串,该字符串可供人阅读,包含类名和属性名。
问题是上面的代码没有按预期工作。返回的属性只是来自第一级类的属性。
如果不进行筛选,而是运行forEach并打印结果,则会得到预期的属性。所以我很确定这和过滤器内部的循环有关。
你认为有没有更实用的方法?我只是担心我不需要一个“临时”列表,向列表中添加值,然后重置它。
您的函数递归地调用自身,但不处理该递归调用的返回列表。这就是为什么你只会得到顶级课程的成绩。
另外,在我看来,你不应该依赖于过滤器
调用产生的副作用。它可能会工作,但函数的文档并不能保证集合中的每个项都会准确调用它一次。因此,应该有一个单独的for循环来执行递归调用,并且应该将结果添加到现有结果中。
fun checkConstrain(parent: Any): List<String> {
val memberProperties = parent::class.memberProperties
var result = memberProperties
.filter { hasAnnotation(it) && propertyIsNull(it, parent) }
.map { formatResult(parent, it) }
memberProperties.filter { memberIsDataClass(it) }
.mapNotNull { getMemberPropertyInstance(parent, it) }
.forEach { result += checkConstrain(it) }
return result
}
您没有为您使用的几个函数提供代码。这是我给他们用的:
val KProperty<*>.returnTypeClass get() = this.returnType.classifier as? KClass<*>
fun <T> memberIsDataClass(member: KProperty<T>) = member.returnTypeClass?.isData == true
fun <T> getMemberPropertyInstance(parent: Any, property: KProperty<T>) = property.getter.call(parent)
fun <T> hasAnnotation(property: KProperty<T>) = property.annotations.firstOrNull { it.annotationClass == SomeRandomAnnotation::class } != null
fun <T> propertyIsNull(property: KProperty<T>, parent: Any) = getMemberPropertyInstance(parent, property) == null
fun formatResult(parent: Any, property: KProperty<*>) = "$parent's property(${property.name}) is annotated with SomeRandomAnnotation and is null."
使用Java8 streams,我希望将列表转换为映射,如Java8 list into map 解决方案中所述。但是,我希望过滤以删除具有某些键的条目(例如,如果键为空),而不需要将值转换为键两次。
如何过滤
我想通过作为字符串的属性名筛选类的集合。假设我有一个名为Person的类,我有它的一个集合,或者是IEnumerable或者是List,我想过滤这个集合,但是我不知道确切的过滤器,我的意思是我不能使用: 让我举一个例子。
我在做一些类似递归获取属性的事情 代码的问题是:它只下降了一级,我想知道如何使用反射自动获取所有属性?我刚刚编写了以下示例容器代码: 在主要方法中: 我希望得到: 我现在得到的结果是: 有人能帮我使用PrintProperties方法吗?非常感谢你。
我对此代码的唯一关注是,它需要一个新表来连接和,我希望避免这种行为(但如果确实不可能的话,就继续执行它)。 使用也是不可行的,因为它需要表中的其他列,而且这个表稍后将被许多其他实体使用。 因此,使用数据示例,如果在我的表中有一个have: 在Java中,我的列表应该有两个条目(可用的两种语言)。 这种行为在JPA中可能吗? 解决方案 现在一切都按预期工作。