Java中的Class在反射中起到了至关重要的重要。同样,KClass也是kotlin学习中不可或缺的一部分。
1.什么是Kclass
在 Kotlin 中,KClass 是一种特殊的类型,用于表示 Kotlin 类的类引用。KClass 提供了一些有用的函数和属性,以便在运行时对类进行操作和访问。
KClass 是 Kotlin 反射 API 的一部分,可以通过 ::class
来获取一个类的 KClass 实例。
2.获取KClass
2.1 获取java Class对象
java中获取一个Class对象的方法有很多,例如有一个Person.java
public class Person {
private String name;
}
那么获取这个对象的方法可以有:
Class clazzA = Person.class;
Class clazzB = new Person().getClass();
Class clazzC = Class.forName("com.example.entity.Person");
2.2 获取KClass对象
有一个Kotlin类定义:
data class Dog(val name: String, val age: Int) {
fun run() {
println("dog $name is running.")
}
}
获取KClass的方式有:
val kClazzA = Dog::class
val kClazzB = Dog("Eddie", 2)::class
val kClazzC = Dog("Eddie", 2).javaClass.kotlin
3. KClass
KClass是一个接口,有很多定义好的方法:
package kotlin.reflect
public actual interface KClass<T : Any> : KDeclarationContainer, KAnnotatedElement, KClassifier {
public actual val simpleName: String?
public actual val qualifiedName: String?
//当前类及其父类定义的所有属性和方法
override val members: Collection<KCallable<*>>
//所有的构造函数
public val constructors: Collection<KFunction<T>>
//定义的所有嵌套类,包括内部类和静态嵌套类
public val nestedClasses: Collection<KClass<*>>
public val objectInstance: T?
public actual fun isInstance(value: Any?): Boolean
public val typeParameters: List<KTypeParameter>
public val supertypes: List<KType>
public val sealedSubclasses: List<KClass<out T>>
//当前类的可见性,即public、protected等
public val visibility: KVisibility?
public val isFinal: Boolean
public val isOpen: Boolean
public val isAbstract: Boolean
public val isSealed: Boolean
public val isData: Boolean
public val isInner: Boolean
public val isCompanion: Boolean
public val isFun: Boolean
public val isValue: Boolean
actual override fun equals(other: Any?): Boolean
actual override fun hashCode(): Int
}
4. 扩展函数
扩展函数是Kotlin的一大特色,KClass也有很多扩展函数:
@file:JvmName("KClasses")
@file:Suppress("UNCHECKED_CAST")
package kotlin.reflect.full
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.DFS
import kotlin.reflect.*
import kotlin.reflect.jvm.internal.*
//获取主要构造函数
val <T : Any> KClass<T>.primaryConstructor: KFunction<T>?
get() = (this as KClassImpl<T>).constructors.firstOrNull {
((it as KFunctionImpl).descriptor as ConstructorDescriptor).isPrimary
}
//获取伴生对象的KClass对象
@SinceKotlin("1.1")
val KClass<*>.companionObject: KClass<*>?
get() = nestedClasses.firstOrNull {
(it as KClassImpl<*>).descriptor.isCompanionObject
}
//伴生对象的实例
@SinceKotlin("1.1")
val KClass<*>.companionObjectInstance: Any?
get() = companionObject?.objectInstance
//获取当前类的属性和方法,不包括父类
val KClass<*>.declaredMembers: Collection<KCallable<*>>
get() = (this as KClassImpl).data.value.declaredMembers
/**
* Returns all functions declared in this class, including all non-static methods declared in the class
* and the superclasses, as well as static methods declared in the class.
*/
@SinceKotlin("1.1")
val KClass<*>.functions: Collection<KFunction<*>>
get() = members.filterIsInstance<KFunction<*>>()
//获取当前类声明的静态方法
val KClass<*>.staticFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.allStaticMembers.filterIsInstance<KFunction<*>>()
//获取当前类及其父类声明的非静态非拓展方法
val KClass<*>.memberFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.allNonStaticMembers.filter { it.isNotExtension && it is KFunction<*> } as Collection<KFunction<*>>
//获取当前类及其父类的所有拓展方法(非静态)
val KClass<*>.memberExtensionFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.allNonStaticMembers.filter { it.isExtension && it is KFunction<*> } as Collection<KFunction<*>>
/**
* Returns all functions declared in this class.
* If this is a Java class, it includes all non-static methods (both extensions and non-extensions)
* declared in the class and the superclasses, as well as static methods declared in the class.
*/
@SinceKotlin("1.1")
val KClass<*>.declaredFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.declaredMembers.filterIsInstance<KFunction<*>>()
//获取当前类非静态、非扩展方法
val KClass<*>.declaredMemberFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.declaredNonStaticMembers.filter { it.isNotExtension && it is KFunction<*> } as Collection<KFunction<*>>
//获取当前类的扩展方法
val KClass<*>.declaredMemberExtensionFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.declaredNonStaticMembers.filter { it.isExtension && it is KFunction<*> } as Collection<KFunction<*>>
//获取这个类的所有静态字段(只有Java类中的静态字段才会被返回)
val KClass<*>.staticProperties: Collection<KProperty0<*>>
get() = (this as KClassImpl).data.value.allStaticMembers.filter { it.isNotExtension && it is KProperty0<*> } as Collection<KProperty0<*>>
//当前类及其父类的非拓展属性
val <T : Any> KClass<T>.memberProperties: Collection<KProperty1<T, *>>
get() = (this as KClassImpl<T>).data.value.allNonStaticMembers.filter { it.isNotExtension && it is KProperty1<*, *> } as Collection<KProperty1<T, *>>
//返回当前类及其父类定义的拓展属性
val <T : Any> KClass<T>.memberExtensionProperties: Collection<KProperty2<T, *, *>>
get() = (this as KClassImpl<T>).data.value.allNonStaticMembers.filter { it.isExtension && it is KProperty2<*, *, *> } as Collection<KProperty2<T, *, *>>
//返回当前类非拓展的属性
val <T : Any> KClass<T>.declaredMemberProperties: Collection<KProperty1<T, *>>
get() = (this as KClassImpl<T>).data.value.declaredNonStaticMembers.filter { it.isNotExtension && it is KProperty1<*, *> } as Collection<KProperty1<T, *>>
//当前类中定义的拓展属性
val <T : Any> KClass<T>.declaredMemberExtensionProperties: Collection<KProperty2<T, *, *>>
get() = (this as KClassImpl<T>).data.value.declaredNonStaticMembers.filter { it.isExtension && it is KProperty2<*, *, *> } as Collection<KProperty2<T, *, *>>
private val KCallableImpl<*>.isExtension: Boolean
get() = descriptor.extensionReceiverParameter != null
private val KCallableImpl<*>.isNotExtension: Boolean
get() = !isExtension
//不包含自己本身的所有直接父类,包括接口
val KClass<*>.superclasses: List<KClass<*>>
get() = supertypes.mapNotNull { it.classifier as? KClass<*> }
//返回父类类型
val KClass<*>.allSupertypes: Collection<KType>
get() = DFS.dfs(
supertypes,
{ current ->
val klass = current.classifier as? KClass<*> ?: throw KotlinReflectionInternalError("Supertype not a class: $current")
val supertypes = klass.supertypes
val typeArguments = current.arguments
if (typeArguments.isEmpty()) supertypes
else TypeSubstitutor.create((current as KTypeImpl).type).let { substitutor ->
supertypes.map { supertype ->
val substituted = substitutor.substitute((supertype as KTypeImpl).type, Variance.INVARIANT)
?: throw KotlinReflectionInternalError("Type substitution failed: $supertype ($current)")
KTypeImpl(substituted)
}
}
},
DFS.VisitedWithSet(),
object : DFS.NodeHandlerWithListResult<KType, KType>() {
override fun beforeChildren(current: KType): Boolean {
result.add(current)
return true
}
}
)
//返回当前类的所有父类,不包含其本身
val KClass<*>.allSuperclasses: Collection<KClass<*>>
get() = allSupertypes.map { supertype ->
supertype.classifier as? KClass<*> ?: throw KotlinReflectionInternalError("Supertype not a class: $supertype")
}
//这里要注意,是当前类型本身也是返回true
fun KClass<*>.isSubclassOf(base: KClass<*>): Boolean =
this == base ||
DFS.ifAny(listOf(this), KClass<*>::superclasses) { it == base }
fun KClass<*>.isSuperclassOf(derived: KClass<*>): Boolean =
derived.isSubclassOf(this)
fun <T : Any> KClass<T>.cast(value: Any?): T {
if (!isInstance(value)) throw TypeCastException("Value cannot be cast to $qualifiedName")
return value as T
}
fun <T : Any> KClass<T>.safeCast(value: Any?): T? {
return if (isInstance(value)) value as T else null
}
fun <T : Any> KClass<T>.createInstance(): T {
// TODO: throw a meaningful exception
val noArgsConstructor = constructors.singleOrNull { it.parameters.all(KParameter::isOptional) }
?: throw IllegalArgumentException("Class should have a single no-arg constructor: $this")
return noArgsConstructor.callBy(emptyMap())
}
这里咋一看方法很多,又是当前类定义的方法,又是父类定义的,又有拓展方法等等,但是有规律:
比如方法分为是该类的还是包含其父类的,仅该类的可以用declared来命名其函数名,比如方法是否是扩展的,是扩展的话用extensions来命名其函数名,还有就是函数用Function,而属性用Properties来进行区分。
- members包含方法和字段。
- declared只是当前类定义的。
- extension是扩展的。
如declaredMemberExtensionFunctions表示当前类定义的扩展方法。