ARTS - 2020.07.27 ~ 2020.08.02

ARTS打卡 - 9

1. Algorithm

3Sum Closest

这应该是上周做的三数之和的衍生题,是计算数组中最接近目标值的三个数字之和,这道题感觉要比那道题简单一些,可能是因为刚做过类似的题,所以知道大概的解法,步骤还是一样:

  1. 边界条件判断
  2. 快速排序
  3. 判断差值:一头一尾指针,与一个顺序指针,计算三个数字大小并保存与目标值的差值,如果小于之前的,则保存差值,并向左移动右指针,如果大于之前的差值,则向右移动左指针。

2. Review

  • Reification of the Erased

    • 这是一篇将关于 reified 的使用方法与原理的文章

    • reified 是Kotlin中为解决类型擦除而提供的一个关键字,可以在编译时访问泛型类型信息。

    • 如果不使用 reified ,那如果想要在一个泛型方法内部访问泛型类型信息的话,只能传递一个类型参数,提供访问,例如:

      1
      2
      3
      fun <T> printType(classType: Class<T>) {
      print(classType::class.java)
      }

      而如果使用refied的话,就可以直接在泛型函数内部访问泛型类型信息:

      1
      2
      3
      4
      5
      6
      7
      8
      inline fun <reified T> printType() {
      print(T::class.java)
      }

      fun printStringType(){
      //calling the reified generic function with String type
      printType<String>()
      }

      那么 reified 是怎么实现的呢?实际上是通过内联函数,reified关键字只能作用于内联函数,对于内联函数,其优势之一就是编译器可以在复制函数体时对其进行修改,而 reified 正是利用了这个特性来实现的编译时访问泛型类型信息的:当使用了reified 时,编译器在复制函数体时会将泛型类型替代为实际声明类型,因此也就可以访问到泛型类型信息了

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      // Inline function converted to Java from byte code
      public static final void printType() {
      int $i$f$printType = 0;
      Intrinsics.reifiedOperationMarker(4, "T");
      Class var1 = Object.class;
      boolean var2 = false;
      System.out.print(var1);
      }

      // Caller converted to Java from byte code
      public static final void printStringType() {
      int $i$f$printType = false;
      Class var1 = String.class;
      boolean var2 = false;
      System.out.print(var1);
      }

      由于只能作用与内联函数,所以它与内联函数有一样的特性,例如不能使用被Java访问。

      此外,reified 也允许返回一个泛型类型,例如:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      inline fun <reified T> calculate(value: Float): T {
      return when (T::class) {
      Float::class -> value as T
      Int::class -> value.toInt() as T
      else -> throw IllegalStateException("Only works with Float and Int")
      }
      }

      val intCall: Int = calculate(123643)
      val floatCall: Float = calculate(123643)
    • reified 允许使用泛型做一些之前由于在运行时缺少类型信息而无法完成的事情,然而使用 reified 就以为这需要使用内联函数,reified 不会有任何性能上的消耗,但是使用内联需要考虑函数体的规模,应当尽可能使用简单的短函数才是最好的实践。

3. Tip

  • Jenkins 执行 Execute shell 时,无法对xctestwd签名,因为对该应用签名的证书在keychain login下,因此没有权限,所以需要将证书移动到System中,就可以不用登录就可以访问了。

  • shell中单双括号的区别:

    • 单中括号:
      • []两个符号左右都需要用空格分离
      • 内部操作符与变量之间需要有空格
      • 字符串比较中, < > 都需要进行 ‘\<’ 转义
      • [] 中可以使用 -a(与) 和 -o(或) 进行逻辑运算
    • 双中括号
      • [[]] 左右都需要有空格
      • 内部操作符与操作变量之间需要空格
      • 字符串比较中,无需转义
      • 内部可以使用 && || 进行逻辑运算

4. Share

Javascript 的继承与多态