- create class
class Person3 {
//可变属性
var name: String? = null
//不可变属性
val age: Int = 0
//如果使用private修饰,则不会有getter和setter方法
//外面就无法访问该属性了
private var gender: Int = -1
}
- primary constructor
class Person (val name: String) //只会生成name的getter方法
- secondary constructor
//构造方法和class声明在同一行时,该构造方法被称之为 Primary Constructor
//如果构造方法在类的内部声明,该构造方法被称之为 Secondary Constructor
//Primary Constructor和 Secondary Constructor区别:
//Primary Constructor 构造方法的参数如果有val/var修饰,那么该类会生成和该参数一样的属性,以及与之对应setter和getter(如果是var修饰会有getter和setter,val修饰只有getter)
//Secondary Constructor 构造方法的参数不能用val/var属性
open class Person5(var bool:Boolean){
var name: String? = null
var id: Int = 0
constructor(name: String) : this(false) {
this.name = name
}
constructor(id: Int) : this("AAA") {
this.id = id
}
}
- companion object
伴生对象,可在内部生成静态常量、实现接口、内部对象的函数等
companion object {
//公共常量
const val FEMALE: Int = 0
const val MALE: Int = 1
//私有常量
val GENDER: Int = FEMALE
//静态变量
var username: String = "chiclaim"
//静态方法
fun run() {
println("run...")
}
}
interface IAnimal {
fun eat()
}
class ObjectKeywordTest4 {
companion object : IAnimal {
override fun eat() {
println("eating apple")
}
}
}
companion object Cache {
fun save2DB() {
println("save data to database...")
}
fun save2Memory() {
println("save data to memory...")
}
}
- object class
// 单例
object Singleton
- init block
类在对象初始化时,调用的函数
open class Person7 {
var name: String? = null
var id: Int = 0
constructor(name: String) {
this.name = name
}
constructor(id: Int){
this.id = id
}
//构造对象的时候,init代码块只会被执行一次
init {
System.out.println("init----------")
}
}
执行完 init 函数之后,再执行构造函数里面的逻辑,反编译后可以看到 init 之后才执行 name 的赋值

截屏2025-01-31 17.27.29.png
- inner class
内部类关键字
class OuterClass {
//和Java不同,在Kotlin中内部类默认是静态的,不持有外部类的引用
class InnerStaticClass{
}
//如果要声明非静态的内部类,需要加上inner关键字
inner class InnerClass{
}
}
- sealed class 密封类
https://blog.csdn.net/chuyouyinghe/article/details/144731741
密封类与枚举的比较
密封类和枚举都表示有限的值集合,但它们有不同的用途。
枚举
• 适用于固定常量集合(如一周的天数)。
• 简单且易于使用。
• 可以包括属性和方法。
密封类
• 更灵活。
• 可以保存不同类型的数据。
• 允许每种类型有不同的实现。
enum class Color {
RED, GREEN, BLUE
}
sealed class Shape {
object Circle : Shape()
object Square : Shape()
data class Rectangle(val height: Int, val width: Int) : Shape()
}
反编译后和原始输入的对比
在这个生成的字节码中:
• NetworkResult 是一个抽象类。
• Success 和 Error 是静态嵌套类,具有各自的数据字段(data 和 exception)。
• Loading 是一个表示单例对象的静态嵌套类,具有单个实例(INSTANCE)。
sealed class NetworkResult {
data class Success(val data: String) : NetworkResult()
data class Error(val exception: Throwable) : NetworkResult()
object Loading : NetworkResult()
}
public abstract class NetworkResult {
public static final class Success extends NetworkResult {
private final String data;
public Success(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
public static final class Error extends NetworkResult {
private final Throwable exception;
public Error(Throwable exception) {
this.exception = exception;
}
public Throwable getException() {
return exception;
}
}
public static final class Loading extends NetworkResult {
public static final Loading INSTANCE = new Loading();
private Loading() {}
}
}
- data class
简单理解为常规实体类,无需显式编写 get/set 方法,会自动生成 get/set 方法
data class User(val nickname: String)
- interface
Kotlin 中的接口,可以定义 变量 和 函数(内部可以有逻辑实现),java 不允许在接口中定义 变量/函数
interface InterfaceTest {
var count: Int
fun plus(num: Int) {
count += num
}
}
class Impl : InterfaceTest {
override var count: Int = 0
override fun plus(num: Int) {
super.plus(num)
println("invoke plus")
}
}
/*
Java8之前的接口是不允许有变量和方法的,那么Kotlin是如何实现的呢?
Kotlin 接口中的变量底层只是setter和setter方法
Kotlin 接口中的方法并不是真的有方法体,底层也只有声明。只是在接口的内部新建一个静态内部类
内部类的里静态方法名就是我们在接口里声明有方法体的方法,静态方法有个额外的接口类型的参数,但是对我们开发者是透明的
接口里有方法体的方法在实现类里是不强制我们实现的,不是不需要,而是Kotlin已经替我们做了
public interface InterfaceTest {
int getCount();
void setCount(int var1);
void plus(int var1);
void test();
public static final class DefaultImpls {
public static void plus(InterfaceTest $this, int num) {
$this.setCount($this.getCount() + num);
}
public static void test(InterfaceTest $this) {
String var1 = "";
System.out.print(var1);
}
}
}
public final class Impl implements InterfaceTest {
private int count;
public int getCount() {
return this.count;
}
public void setCount(int var1) {
this.count = var1;
}
public void plus(int num) {
InterfaceTest.DefaultImpls.plus(this, num);
}
public void test() {
InterfaceTest.DefaultImpls.test(this);
}
}
*/