Kotlin学习day7——注解以及实战

2020.7.20

学习目的:了解什么是注解,以及注解的作用,并掌握其使用

①注解的作用:通过注解Annotation来实现标识一个类或一个属性、一个方法、一个参数
②Kotlin的注解完全继承与java
③注解只是一个标识,不会影响类的任何运行
④Kotlin中的注解结构与类很相似
注意:注解类里面定义参数时,只能使用val

               Target注解

  • 语法结构:
    @Target(AnnotationTarget.类型)
    annotation class 自定义标签(注解)的名字
  • 常用的几种标签类型
    AnnotationTarget CLASS: 标识一个类
    AnnotationTarget CONSTRUCTOR: 标识构造函数
    AnnotationTarget PROPERTY: 标识属性
    AnnotationTarget FUNCTION: 标识函数
    AnnotationTarget VALUE_PARAMETER: 标识函数的参数
//标识类
@Target(AnnotationTarget.CLASS)
annotation class TableName(val name:String)
//标识构造函数
@Target(AnnotationTarget.CONSTRUCTOR)
annotation class MYCons
//标识属性
@Target(AnnotationTarget.PROPERTY)
annotation class Mypram(val colum_name:String)
//标识函数
@Target(AnnotationTarget.FUNCTION)
annotation class MyFunc
//标识函数参数
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class MyFuncPram
@TableName(name = "PeopleTable") class People @MYCons constructor(@Mypram(colum_name = "age") var age:Int){
    @Mypram(colum_name = "firstName") val name:String="jack"
    @MYCons constructor(name:String):this(12){}
    @MyFunc fun show(@MyFuncPram score:Int){

    }
}
  • 注解类使用参数(属性)可以与标识的对象形成映射关系,如代码中的"jack"对应的是firstName,对号入座
               Retention——标签的生命周期
  • 三种标签->主要区别是作用域(生命周期)不同,用来修饰Target标签
    AnnotationRetention.SOURCE
    AnnotationRetention.BINARY

    AnnotationRetention.RUNTIME
    作用域.png

通常都会使用AnnotationRetention.RUNTIME

注解实战:从数据库中读取数据模型,并返回对象

import kotlin.reflect.KClass
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.primaryConstructor
//模型数据
@Entity class User(
    @ColumnInfo var id:Int,
    @ColumnInfo var name:String,
    @ColumnInfo var icon:String
) {
    override fun toString(): String {
        return "User(id=$id, name='$name', icon='$icon')"
    }
}

class Student
//Table -- 类名
//类注解 属性注解
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class Entity

//属性注解
@Retention//默认是RUNTIME
@Target(AnnotationTarget.PROPERTY)
annotation class ColumnInfo
//模拟数据的查询
fun selectData():Map<String,Map<String,Any>>{
    //模拟有两个表User Student
    //使用Map封装数据 k-v
    val userData = mapOf(
        Pair("id",1),
        Pair("name","rose"),
        Pair("icon","www.baidu.com")
    )
    val studentData = mapOf(
        Pair("sId",1),
        Pair("name","小王"),
        Pair("address","西南大学")
    )
    val data = mapOf(
        Pair("User",userData),
        Pair("Student",studentData)
    )
    return data
}
fun atuoParseFromTable(clz:KClass<out Any>):Any?{
    //先从数据库中读取表对应的数据
    val datas=selectData()
    //判断传递过来的KClass对象有没有Entity表示
    val entity=clz.findAnnotation<Entity>()
    if(entity==null){
        //传递过来的类没有Entity注解
        //不能自动转换
        return null
    }else{
        //可以自动转换
        //获取类名 ----表名
        val tableName =clz.simpleName
        //使用这个表名去数据库中获取这个表对应的数据
        val info=datas[tableName]
        //创建对象,再将info的数据对应地填充到对象的属性中
        //使用默认的主构造函数创建
        val con=clz.primaryConstructor
        //创建一个数组,保存解析的属性的值
        val params= arrayOfNulls<Any>(con?.parameters?.size!!)
        //遍历构造函数的参数
        con.parameters.forEach {
            //获取参数名
           val value =info?.get(it.name)
            //将这个值保存到数组中
            params[it.index]=value

        }
        //使用构造函数创建对象
        return con?.call(*params)

    }
}
fun main() {
    val obj=atuoParseFromTable(User::class) as User
    println(obj.name)
    //打印rose
}
demo介绍.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容