kotlin--还不懂伴随对象和内联函数?

伴生对象

kotlin的伴生对象用companion关键字来指定,可以省略伴生对象的名称,伴生对象的成员可通过只使用类名作为限定符来调用,伴生对象的成员看起来像其他语言的静态成员,在运行时他们仍然是真实对象的实例成员。为什么有着静态成员的特性却是真实对象的实例成员呢?

class User {
    companion object {
        const val tag = "companion"
        private val property = "user_companion"
		val property2 = "user_companion2"

        fun newInstance(): User {
            return User()
        }
    }
}
复制代码

这段代码对应如下java代码

public final class User {
	   public static final String tag = "companion";
	   private static final String property = "user_companion";
	   private static final String property2 = "user_companion2";
	   public static final User.Companion Companion = new User.Companion((DefaultConstructorMarker)null);
	
	   public static final class Companion {
	      private final String getProperty() {
	         return User.property;
	      }

		  @NotNull
	      public final String getProperty2() {
	         return User.property2;
	      }
	
	      @NotNull
	      public final User newInstance() {
	         return new User();
	      }
	
	      private Companion() {
	      }
	
	      // $FF: synthetic method
	      public Companion(DefaultConstructorMarker $constructor_marker) {
	         this();
	      }
	 }
}
复制代码

再类里面生成了一个静态的User.Companion对象,这个Companion是在不指定伴生对象类名的情况下的默认名字,用const修饰的常量直接是编译生成public static final对应的常量;其他常量就对应生成private static final对应的常量,并生成其他相应的get方法。

看一下通过类名调用代码以及生成代码

fun main(args: Array<String>) {
    println(User.tag)
    println(User.property2)
    println(User.newInstance())
}

public static final void main(@NotNull String[] args) {
  Intrinsics.checkParameterIsNotNull(args, "args");
  String var1 = "companion";
  System.out.println(var1);
  var1 = User.Companion.getProperty2();
  System.out.println(var1);
  User var2 = User.Companion.newInstance();
  System.out.println(var2);
复制代码

}

一目了然,伴随对象就是生成了一个静态的对象,生成对应的方法,在调用的时候,通过生成的静态对象去代理

内联函数

为什么要内联函数?

调用一个方法是一个压栈和出栈的过程,调用方法时将栈针压入方法栈,然后执行方法体,方法结束时将栈针出栈,这个压栈和出栈的过程会耗费资源,这个过程中传递形参也会耗费资源。

什么是内联函数?

当一个函数被声明为inline时,它的函数体是内联的——换句话说,函数体会被直接替换到函数调用的地方,而不是被正常调用。

我们先写一个函数被正常调用的代码

fun main(args: Array<String>) {
    val a = 1
    val b = 2
    a.calculate(b) { x, y ->
        val c = x + y
        println(c)
        c
    }
}

fun Int.calculate(b: Int, calculator: (Int, Int) -> Int): Int {
    return calculator(this, b)
}

------------------------

public final class DemoKt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      int a = 1;
      int b = 2;
      calculate(a, b, (Function2)null.INSTANCE);
   }

   public static final int calculate(int $receiver, int b, @NotNull Function2 calculator) {
      Intrinsics.checkParameterIsNotNull(calculator, "calculator");
      return ((Number)calculator.invoke(Integer.valueOf($receiver), Integer.valueOf(b))).intValue();
   }
}
复制代码

可以看到calculate(a, b, (Function2)null.INSTANCE)其实也就是一个常规方法的调用,我们把calculate函数加上inline

fun main(args: Array<String>) {
    val a = 1
    val b = 2
    a.calculate(b) { x, y ->
        val c = x + y
        println(c)
        c
    }
}

inline fun Int.calculate(b: Int, calculator: (Int, Int) -> Int): Int {
    return calculator(this, b)
}

----------------------

public final class DemoKt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      int a = 1;
      int b = 2;
      int c = a + b;
      System.out.println(c);
   }

   public static final int calculate(int $receiver, int b, @NotNull Function2 calculator) {
      Intrinsics.checkParameterIsNotNull(calculator, "calculator");
      return ((Number)calculator.invoke(Integer.valueOf($receiver), Integer.valueOf(b))).intValue();
   }
}
复制代码

可以看到main方法中好像就直接把calculate方法中的语句拷贝进去了一样,并没有做函数的调用。这就是内联函数与普通函数的区别。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值