当前位置: 代码迷 >> 综合 >> Kotlin-10-数据类(data+lateinit+by lazy+field)
  详细解决方案

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

热度:30   发布时间:2023-10-09 05:48:48.0

目录

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、getlateinit var sex: Stringval sex1 by lazy {if (age > 20) "男" else "女"}//如果不加lateinit关键字,就必须被初始化赋值var race="种族"//被val初始化的属性,是无法被修改的,也就是无法被setval 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 = 0get() = fieldset(value) {field = value}var height: Int = 0set(value) {field = value + 10}val isMan:Booleanget() {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 = 0get() = fieldset(value) {field = value}

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

 //这样会无限的重复调用自己,导致内存溢出var weight: Int = 0get() = fieldset(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;}@Overridepublic 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;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}@Overridepublic String toString() {return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';}
}
  •    和kotlin类的输出对比
fun main() {val person=Person();person.name = "张三"person.age = 18println(person)val person1=Person1("李四",20)println(person1)}

 

 

  相关解决方案