08kotlin之反射

kotlin之反射

1.函数方法引用

package day7refelect

/**
 * 在包中引用 ::multiplyBy表示函数类型(int)->int
 * 支持重载
 */
fun multiplyBy(x: Int): Int {
    return x
}

fun multiplyBy(s: String): Int {
    return 2
}

fun main(args: Array<String>) {
    val values = listOf(1, 2, 3)
    values.map(::multiplyBy)

    val values2 = listOf("A", "b", "c")
    values2.map(::multiplyBy) //支持重载,自动识别,kotlin中

    var strs = "abcdef"
    strs.myReference3(3)

}

var myReference: (Int) -> Int = ::multiplyBy
var myReference2: (String) -> Int = ::multiplyBy

//接收者类型
var myReference3: String.(Int) -> Char = String::get // 默认还有一个this, String就是这个this,
// 几乎等价于扩展函数,但最大区别就是这个接收者函数,是调用类中方法,扩展函数是扩展函

fun String.sub(a: Int) = this[a] //扩展函数

var myReference4: String.(Int) -> Char = String::sub //扩展函数调用

fun String.leng2(): Boolean = this.length > 3

2.函数组合

函数调用,只是确定了类型

package day7refelect

/**
 * 多个函数,最后还是返回一个函数
 * 与其他语言差异性很大,可以组合出一个新的表达式,其他语言也可以,但是函数组合出来地
 * koltin中,函数之间也可以调用
 */
fun <A, B, C> myCompose(f: (B) -> C, g: (A) -> B): (A) -> C {
    return { x -> f(g(x)) } //返回一个函数类型
}

/**
 * 尽量组合出函数新的函数使用
 */
fun <A, B> myCompose2(f: (B) -> Int, g: (A) -> Int): (A, B) -> Int {
    return { x, y -> f(y) + g(x) }
}

fun isEven(x: Int) = 0 == x % 2

fun length(s: String) = s.length

fun main(args: Array<String>) {
    val eventLenth = myCompose(::isEven, ::length)
    val str = listOf("a", "b", "c")
    println(str.filter(eventLenth))
}

3.属性引用

package day7refelect

/**
 * 属性引用 KProperty<Int>
 * ::a 表示一个属性对象, val a: kotlin.Int
 * ::a.get() 获取值
 * ::a.name 表示属性名称
 */
const val a = 3
var b = 5
fun main(args: Array<String>) {
    println(::a)
    println(::a.get())
    println(::a.name)

    println(::b)
    println(::b.set(2))
    println(b)
    println(::b.get())
}

4.访问一个类的成员属性

属性引用,是一个对象

package day7refelect

import kotlin.reflect.KProperty1

/**
 * 访问一个类地成员属性,需要使用全限定名称
 * transform: (T) -> R
 * 当使用类成员作为方法时,隐含String会当作this使用
 * 也就是 (T) -> R  String::length
 */
fun main(args: Array<String>) {
    val values = listOf("a", "b", "c")
    values.map(String::length) // 隐含的持有this,String.() -> Int
    //二者等价
    values.map {
        it.length
    }
    values.map(mapValue)

    //属性引用,属性引用是一个对象
    var length: KProperty1<String, Int> = String::length
    println(length.get("xyx"))

    println(String::length.get("xyz"))
}

/**
 * 函数表达式
 */
var mapValue: (String) -> Int = { x -> x.length }

5.扩展属性引用

package day7refelect

val String.firstChar: Char
    get() = this[0]

fun main(args: Array<String>) {
    print(String::firstChar.get("xuz"))
}

String::firstChar 属性引用。

6.成员属性反射

.javaClass 是使用java中类型,.javaClass.kotlin是kotlin中的类型,二者只在系统提供的库上有所差异

package day7refelect

import kotlin.reflect.jvm.javaField

class T2(val x: Int) {
    companion object
}

/**
 * .javaClass 是使用java中类型,.javaClass.kotlin是kotlin中的类型,二者只在系统提供的库上有所差异
 * .kotlin,是KClass
 */
fun main(args: Array<String>) {
    println(T2::x.javaClass)
    println(T2::x.javaField)

    println("——————————————")
    println(T2.javaClass) //默认是companion的属性
    println(T2.Companion.javaClass)
    println(T2(10).javaClass)//class day7refelect.T2
    println(T2(10).javaClass.kotlin)//class day7refelect.T2

    //
    println("——————————————")
    println(String.Companion.javaClass)
    println(String.javaClass.kotlin)
    println("x".javaClass)//class java.lang.String
    println("x".javaClass.kotlin)//class kotlin.String
}

7.构造方法引用

构造方法也是函数,只是返回一个对象
package day7refelect

/**
 * 在kotlin中,构造方法也是函数,Function类型
 * 1.参数必须保持一致
 * 2.函数对象返回值
 */
class B(val x: Int)

fun method(factory: (Int) -> B) {
    val b: B = factory(3)
    println(b.x)
}

fun main(args: Array<String>) {
   method(::B)
}

8.属性引用

package day7refelect

import kotlin.reflect.KProperty1

/**
 * 实例对象上引用函数或者属性
 *
 */
fun main(args: Array<String>) {
    val str: String = "abc"
    val getReference = str::get
    println(getReference(1))

    var length = "xyz"::length
    println(length.get())

    val prop: KProperty1<String, Int> = String::length
    println(prop.get("xya"))
}

9.获取类所有属性

package day7refelect

import kotlin.reflect.full.memberProperties

/**
 * 反射所有属性
 */
class Person(val name: String, var age: Int)

fun main(args: Array<String>) {
    val p = Person::class
    println(p.memberProperties)
}

10.获取类所有方法

package day7refelect

import kotlin.reflect.full.functions
import kotlin.reflect.full.memberFunctions

class Person2(val name: String, var age: Int) {
    fun printSomething1() {

    }

    fun printSomething2() {

    }
}

fun main(args: Array<String>) {
    var p = Person2::class // KClass
    println(p.memberFunctions) //二者一致
    println(p.functions)
}

11.获取类所有构造方法

package day7refelect

class Person3(var name: String) {

    constructor(name: String, age: Int) : this(name) {

    }

    constructor(name: String, age: Int, height: Int) : this(name, age) {

    }
}

fun main(args: Array<String>) {
    val p3 = Person3::class
    val constructs = p3.constructors
    println(constructs)
}

12.反射调用类特定方法

package day7refelect

import kotlin.reflect.full.functions

class Person4 {
    fun somethings() {
        println("something")
    }

    fun somethings2(name: String) {
        println("something:$name")
    }
}

fun main(args: Array<String>) {
    var p4 = Person4::class
    val p4Object = Person4()

    var functionsInvoke = p4.functions.find { it.name == "somethings" }//先找到方法
    functionsInvoke?.call(p4Object) //调用特定对象

    //传递参数
    var functionsInvoke2 = p4.functions.find { it.name == "somethings2" }
    functionsInvoke2?.call(p4Object, "hello world")//参数添加,这也是为什么会说隐藏了this
}

13.反射属性修改

与方法基本一致。

package day7refelect

import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.memberProperties

class Person5 {
    var name: String = "我的"
    val age: Int = 0
}

fun main(args: Array<String>) {
    var p5 = Person5::class
    val p5Object = Person5()
    var members = p5.memberProperties.find { it.name == "name" }//找到属性
    println(members?.get(p5Object))//特定对象调用
    
    //由于默认是KProperty1继承KProperty,不可修改,但var属性是可以修改的,强制转换为KMutableProperty
    //针对val属性无效
    if (members is KMutableProperty<*>) {
        members.setter.call(p5Object, "welcome")
    }
    //不判断,强制转换
    (members as KMutableProperty<*>).setter.call(p5Object, "nihao")
}

14.反射半生对象

package day7refelect

import kotlin.reflect.full.companionObject

class Person6 {
    companion object {
        fun method() {
            println("hello world")
        }
    }
}

fun main(args: Array<String>) {
    var p6 = Person6::class
    var comp = p6.companionObject //半生对象,本质是一个静态类对象,所以可以这样拿,这样调用
    println(comp)

    println(Person6.method())
    var com2 = Person6.Companion // 直接获取
}

15.反射创建对象

package day7refelect

import kotlin.reflect.full.createInstance

class Person7(var name: String) {
    var price = 0.0

    constructor() : this("未找到商品") {
        this.price = 0.0
    }

    constructor(name: String, price: Double) : this(name) {
        this.price = price
    }
}

fun main(args: Array<String>) {
    var clazz = Person7::class
    val instance = clazz.createInstance()
    println(instance.name)
    println(instance.price)

    var cons = clazz.constructors
    cons.forEach {
        if (it.parameters.size == 2) { // 构造方法,默认没有this参数
            val instance2 = it.call("zhangSan", 20)
            println(instance2.price)
            println(instance2.name)
        }
    }
}

16.重载方法反射调用

package day7refelect

import kotlin.reflect.full.createInstance
import kotlin.reflect.full.declaredFunctions

class Person8 constructor() { //默认是有一个空的
    fun method(message: String) {
        println(message)
    }

   private fun method(message: String, price: Double) {
        println(price)
        println(message)
    }
}

fun main(args: Array<String>) {
    var clazz = Person8::class
    var instance = clazz.createInstance()

    val funs = clazz.declaredFunctions //猜测是与java一致,打破分装,但是与java对比缺少了一步

    for (f in funs) {
        if (f.parameters.size == 2) { //默认还有this
            f.call(instance, "你好")
        }
        if (f.parameters.size == 3) { //默认含有this参数,都是隐含持有
                        f.isAccessible = true // 添加,才能打破私有函数封装,属性不需要
            f.call(instance, "你好",3.0) //调用报错
        }
    }
}

17.属性打破封装获取

package day7refelect

import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.createInstance
import kotlin.reflect.full.declaredMemberProperties

class Person9 {
    var name: String = "lisi"
    val age: Int = 20
}

/**
 * declared 针对的是private,用来打破封装
 */
fun main(args: Array<String>) {
    var clazz = Person9::class
    var instance = clazz.createInstance()

    var props = clazz.declaredMemberProperties
    props.forEach {
        when (it.name) {
            "name" -> {
                val kmp = it as KMutableProperty1<Person9, Any>
                kmp.set(instance, "wangwu")
                println(it.get(instance))
            }
            "age" -> {
                println(it.get(instance))
            }
        }
    }
}

ain(args: Array) {
var clazz = Person9::class
var instance = clazz.createInstance()

var props = clazz.declaredMemberProperties
props.forEach {
    when (it.name) {
        "name" -> {
            val kmp = it as KMutableProperty1<Person9, Any>
            kmp.set(instance, "wangwu")
            println(it.get(instance))
        }
        "age" -> {
            println(it.get(instance))
        }
    }
}

}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值