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))
}
}
}
}