Kotlin中的object理解

一、 object用作对象声明

最简单的对象声明

object Single{

}

转成java,可以看出(1)一个简单的单例模式,(2)构造函数是private

public final class Single {
   @NotNull
   public static final Single INSTANCE;

   private Single() {
   }

   static {
      Single var0 = new Single();
      INSTANCE = var0;
   }

稍复杂的对象声明

object Single{
    var a = 1
    fun execute(){
        
    }
}

转换成java,可以看出(1)a变量是私有静态成员变量(2)声明了两个非静态的函数用来读写a变量(3)execute函数并没有变成静态函数

public final class Single {
   private static int a;
   @NotNull
   public static final Single INSTANCE;

   public final int getA() {
      return a;
   }

   public final void setA(int var1) {
      a = var1;
   }

   public final void execute() {
   }

   private Single() {
   }

   static {
      Single var0 = new Single();
      INSTANCE = var0;
      a = 1;
   }
}

Kotlin中的具体使用

Single.a = 2;
Single.execute()

Java中的具体使用

Single.INSTANCE.setA(2);
Single.INSTANCE.getA();
Single.INSTANCE.execute();

总结

object用作对象声明时

1.自动变为一个饿汉单例模式

2.生成读写变量的函数去读写其中的私有静态变量

@JvmField和@JvmStatic

object用作对象声明,,@JvmField和@JvmStatic可以简化其在Java中的使用

object Single{
    @JvmField
    var abc = 1;
    
    @JvmStatic
    var efg = 3;
    

    @JvmStatic
    fun feelTheWorld(){}
}

转化为Java代码

public final class Single {
   @JvmField
   public static int abc;
   private static int efg;
   @NotNull
   public static final Single INSTANCE;

   /** @deprecated */
   // $FF: synthetic method
   @JvmStatic
   public static void getEfg$annotations() {
   }

   public static final int getEfg() {
      return efg;
   }

   public static final void setEfg(int var0) {
      efg = var0;
   }

   @JvmStatic
   public static final void feelTheWorld() {
   }

   private Single() {
   }

   static {
      Single var0 = new Single();
      INSTANCE = var0;
      abc = 1;
      efg = 3;
   }
}

Java中的使用

Single.abc = 2;
Single.feelTheWorld();

@JvmField将原来的私有静态变量变为公有静态的变量(可以比较一下使用JvmField和不使用的Java代码的区别),另外,它不能修饰本身为私有的变量

@JvmStatic只能用在object和companion object声明内,一般用于修饰方法,使方法变成真正的静态方法;如果修饰变量不会消除变量的getter与setter方法,但会使getter与setter方法和变量都变成静态

最后总结一下其中成员变量的在Java中的体现

object Single1{
        var a = 1;//私有静态变量,公有非静态setter,getter
        val b = 2;//私有静态变量,公有静非态getter,final修饰
        private var c = 3;//私有静态变量,木有setter,getter
        private val d = 4;//私有静态变量,木有setter,getter,final修饰
        @JvmStatic
        var e = 5 //私有静态变量,公有静态setter,getter
        @JvmStatic
        val f = 6 //私有静态变量,公有静态getter,final修饰
        @JvmField
        var g = 7 //公有静态变量,木有setter,getter
        @JvmField
        val h = 8//公有静态变量,木有setter,getter,final修饰

    }

二、 类的内部使用object对象声明

简单比较一下类内部使用object和companion object的区别,发现

1..类内部可以有多个object声明,但是companion object声明只能有一个

2..object一定要取名,但是companion object可以不取名,默认为Companion。对于companion object取不取名,这个在Java使用中会有感觉,而Kotlin使用中无感

下面用kotlin代码实际比较一下,成员变量,成员函数相关

class TestManager3{
    object Single{
        var a1 = 1
        @JvmField
        var b1 = 1
        fun seeTheWorld1(){}
        @JvmStatic
        fun feelTheWorld1(){}
    }

    companion object{
        var a2 = 1
        @JvmField
        var b2 = 1
        fun seeTheWorld2(){}
        @JvmStatic
        fun feelTheWorld2(){}
    }
}

在Java中的体现

public final class TestManager3 {
   private static int a2 = 1;
   @JvmField
   public static int b2 = 1;
   @NotNull
   public static final Companion Companion = new Companion((DefaultConstructorMarker)null);

   @JvmStatic
   public static final void feelTheWorld2() {
      Companion.feelTheWorld2();
   }
  
   public static final class Single {
      private static int a1;
      @JvmField
      public static int b1;
      @NotNull
      public static final Single INSTANCE;

      public final int getA1() {
         return a1;
      }

      public final void setA1(int var1) {
         a1 = var1;
      }

      public final void seeTheWorld1() {
      }

      @JvmStatic
      public static final void feelTheWorld1() {
      }

      private Single() {
      }

      static {
         Single var0 = new Single();
         INSTANCE = var0;
         a1 = 1;
         b1 = 1;
      }
   }
  
   public static final class Companion {
      public final int getA2() {
         return TestManager3.a2;
      }

      public final void setA2(int var1) {
         TestManager3.a2 = var1;
      }

      public final void seeTheWorld2() {
      }

      @JvmStatic
      public final void feelTheWorld2() {
      }

      private Companion() {
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}

Kotlin中的使用

TestManager3.Single.a1=2
TestManager3.Single.b1=2
TestManager3.Single.seeTheWorld1()
TestManager3.Single.feelTheWorld1()
TestManager3.a2 = 2
TestManager3.b2 = 3
TestManager3.seeTheWorld2()
TestManager3.feelTheWorld2()

Java中的使用

TestManager3.Single.INSTANCE.setA1(2);
TestManager3.Single.b1 = 2;
TestManager3.Single.feelTheWorld1();
TestManager3.Single.INSTANCE.seeTheWorld1();
TestManager3.Companion.setA2(2);
TestManager3.b2 = 2;//java转kotlin项目静态变量使用这种
TestManager3.feelTheWorld2();
TestManager3.Companion.seeTheWorld2();

object用作内部类声明,和之前相比并没有变化

companion object用作内部类声明的话,有几点需要注意

1.定义的变量,会变成外部类的私有静态变量

2.定义的变量加上@JvmField修饰,会变成外部类的公有静态变量

3.定义的方法加上@JvmStatic修饰,会变成外部类的公有静态方法

<think>好的,我现在要帮用户了解Kotlin中的companion object,也就是伴生对象。首先,我需要回忆一下相关的知识,并结合提供的引用资料来组织答案。 首先,根据引用3,companion objectobject关键字的三种使用场景之一,其他两种是对象声明和对象表达式。伴生对象主要用于在类中定义与类本身关联而不是与实例关联的成员,类似于Java中的静态成员。但Kotlin没有static关键字,所以用伴生对象来实现类似功能。 接下来,引用4给出了一个例子,companion object中可以包含用@JvmStatic注解的方法,这样在Java中调用时会更方便。这说明伴生对象的方法可以被编译成静态方法,方便与Java互操作。 引用5提到伴生对象可以有名字,也可以没有名字,如果实现接口的话会提供默认实现。这意味着伴生对象可以更灵活地组织代码,甚至实现接口,增强扩展性。 然后,我需要定义伴生对象的基本概念:它是类内部的一个对象,与类本身关联,而不是实例。每个类只能有一个伴生对象,类似于Java的静态成员,但功能更强大,因为伴生对象可以继承类和实现接口。 接下来是使用场景。根据引用3和5,伴生对象适合工厂方法、类级别常量、静态工具方法。比如,在类中定义一个创建实例的工厂方法,或者保存全局配置的常量。 然后需要提到如何定义伴生对象。语法是在类内部使用companion object关键字,可以带名字或者不带。例如: class MyClass { companion object Factory { fun create(): MyClass = MyClass() } } 或者不命名: companion object { ... } 还要提到@JvmStatic和@JvmField注解,用于生成真正的静态成员,方便Java调用。这是实际开发中常见的做法,特别是在混合项目中使用时需要注意。 另外,伴生对象可以实现接口,这样可以在需要接口实现的地方使用伴生对象,增加灵活性。比如: interface Factory<T> { fun create(): T } class MyClass { companion object : Factory<MyClass> { override fun create(): MyClass = MyClass() } } 这样,可以通过MyClass.Companion.create()来调用。 可能还需要对比伴生对象和Java静态成员的区别,强调Kotlin的伴生对象更灵活,可以继承和实现接口,而Java的static方法不能。 最后,根据用户的问题,生成相关问题,比如伴生对象和对象声明的区别,或者如何实现静态常量等。确保问题覆盖常见的疑惑点。 检查引用是否准确,引用3和5提到了伴生对象的命名和接口实现,引用4提到了@JvmStatic的使用,这些都需要在回答中正确引用。例如,在提到伴生对象可以有名字时引用5,提到@JvmStatic时引用4。 需要确保回答结构清晰,分点说明定义、使用场景、语法和注意事项,同时给出示例代码,让用户更容易理解。还要注意使用中文,数学公式用$...$,但这里可能不太涉及数学内容,所以主要关注代码块和引用。</think>### Kotlin伴生对象(companion object)详解 #### 一、核心定义 伴生对象是通过$companion\ object$关键字在类内部声明的特殊对象,与类本身生命周期绑定,每个类只能有一个伴生对象[^3]。其本质是「类的内部单例对象」,用于替代Java的静态成员。 ```kotlin class Logger { companion object Factory { // 可命名伴生对象 fun create(): Logger = Logger() } } ``` #### 二、核心特性 1. **类级别访问**:通过类名直接访问成员 ```kotlin val logger = Logger.create() // 无需实例化Logger类 ``` 2. **命名自由**:支持匿名或显式命名(默认名称$Companion$)[^5] 3. **接口实现**:可继承接口实现多态 ```kotlin interface Factory<T> { fun produce(): T } class Car { companion object : Factory<Car> { override fun produce() = Car() } } ``` #### 三、典型使用场景 | 场景类型 | 示例代码 | 说明 | |-------------------|--------------------------------------------------------------------------|-----------------------------| | 工厂模式 | `Car.produce()` | 创建类实例的统一入口[^3] | | 静态常量 | ```companion object { const val MAX_SIZE = 1024 }``` | 编译时常量声明 | | 工具方法 | ```fun parse(json: String) = ...``` | 与类相关但无需实例的方法 | | 接口适配 | ```companion object : JsonConverter<Data>``` | 实现JSON序列化等通用协议 | #### 四、JVM平台互操作 1. **@JvmStatic注解** 生成真正的静态方法(Java可调用): ```kotlin companion object { @JvmStatic fun check() { ... } } ``` 2. **@JvmField注解** 暴露常量到Java: ```kotlin companion object { @JvmField val VERSION = "1.0" } ``` #### 五、与对象声明的区别 | | 伴生对象 | 对象声明(object) | |------------------|-----------------------------------|------------------------------| | 关联性 | 绑定到宿主类 | 独立单例对象 | | 访问方式 | 通过类名访问 | 通过对象名直接访问 | | 初始化时机 | 首次访问宿主类时初始化[^2] | 首次访问时初始化 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值