KClass初探


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表示当前类定义的扩展方法。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值