Kotlin-10-数据类(data+lateinit+by lazy+field)

目录

1、定义

2、kotlin数据类的优势

3、kotlin数据类的限制

4、数据类的属性

5、by lazy

6、field关键字

7、传统JavaBean


 

1、定义

对应于Java中的数据类(JavaBean),kotlin的数据类是需要被data关键字所修饰的

  • 普通的数据类(进阶版在第四小节)
data class Person1(var name: String, var age: Int) 

2、kotlin数据类的优势

kotlin帮我们自动添加和重写了JavaBean中以下方法,让我们代码更加的简洁

      setter()
      getter()      
      hashCode()
      equals()
      toString()
      copy()
      componentN()

3、kotlin数据类的限制

  •  被data关键字修饰的kotlin数据类默认是public final的,所以无法被继承,也不能用open关键字(变成可继承)修饰
  • 必须声明主构造函数
  • 主构造函数必须要至少有一个参数
  • 主构造函数中的所有参数必须被标记为val或者var
  • 数据类不能有以下修饰符:abstract,inner,open,sealed

4、数据类的属性

上面我们说过kotlin的数据类必须声明主构造函数,并且至少得有一个参数,那么我们不需要写在构造函数参数里的属性应该怎么写呢?

注意:没有写在主构造函数的属性,必须被lateinit关键字修饰或者初始化赋值

注意:没初始化赋值的属性,也可以通过by lazy语法来延迟赋值

data class Person1(var name: String, var age: Int) {

    //用lateinit关键字修饰的属性,可以没有初始值,可以后期set、get
    lateinit var sex: String

    val sex1 by lazy {
        if (age > 20) "男" else "女"
    }

    //如果不加lateinit关键字,就必须被初始化赋值
    var race="种族"

    //被val初始化的属性,是无法被修改的,也就是无法被set
    val race1="汉族"

    /**
     * 1、上面的属性,name、age、sex、race都是对set、get方法进行了省略,让编译器来自动添加set、get方法的
     * 2、当然我们也可以重写set、get方法。来对set的值进行一定的封装处理
     * 3、field相当于Java中的this.weight的含义,注意我们set方法中绝不不能调用自己this.weight
     * 否者就会出现无限的重复调用自己的死循环
     */

    var weight: Int = 0
        get() = field
        set(value) {
            field = value
        }

    var height: Int = 0
        set(value) {
            field = value + 10
        }

    val isMan:Boolean
        get() {
            return this.sex=="男"
        }

}

5、by lazy

被by lazy 修饰的变量有以下特点:

  • 必须用val修饰,不能使用var修饰
  • 在被首次调用的时候才会被赋值,一旦被赋值,后续就不能修改。
 val sex1 by lazy {
        if (age > 20) "男" else "女"
    }

fun main() {
    val person=Person1("张三",18)
    println("person.sex1=${person.sex1}")
    person.age=21   //------------------------只在第一次被调用的时候赋值,后续赋值也不会改变sex1的值
    println("person.sex2=${person.sex1}")

    val person1=Person1("张三",22)
    println("person.sex3=${person1.sex1}")
    //person.sex1="s" ------------------------------报错,无法二次赋值
}
//输出结果
person.sex1=女
person.sex2=女
person.sex3=男

6、field关键字

 field类似于java里的this.属性名

   var weight: Int = 0
        get() = field
        set(value) {
            field = value
        }

但是不能直接使用this.name会造成递归调用内存溢出的,  因为在set和get中是不允许有本身的局部变量的(例如如果你属性名是name, 在set/get里是不能有这个变量的), 因为属性的调用也涉及到了set/get会造成递归调用, 所以要解决引用自身的问题, kotlin发明了field来解决这个问题

 //这样会无限的重复调用自己,导致内存溢出
    var weight: Int = 0
        get() = field
        set(value) {
            this.weight=value
        }

7、传统JavaBean

  • 首先看一下我们传统的Java数据类(JavaBean)
public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (!(o instanceof Person))
            return false;

        Person person = (Person) o;

        if (age != person.age)
            return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}
  •    和kotlin类的输出对比
fun main() {

    val person=Person();
    person.name = "张三"
    person.age = 18
    println(person)

    val person1=Person1("李四",20)
    println(person1)

}
发布了82 篇原创文章 · 获赞 16 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/qq_34589749/article/details/103541852