ARTS - 15

138 阅读2分钟

A


92. 反转链表 II

描述: 反转从位置 mn 的链表。请使用一趟扫描完成反转。

思路: 从 m 到 n 阶段的反转的实现和反转整个链表的思路是一样的。但是需要保存起始时m-1和m位置的结点,用来在最后将链表连接为1个整体。

R


Safe Parsing Kotlin Data-classes with Gson

问题

如下的数据类:

data class SomeData(
    val intValue: Int,
    val strValue: String = "default value"
)

默认值将会被忽略,如 {"intValue":2} 的 json 会生成对象 {intValue=2,srtValue=null} 而不是 {intValue=2,srtValue="default"}

解决方法

解决方法是为所有属性都添加上默认值,如:

data class SomeData(
    val intValue: Int = 0,
    val strValue: String = "default value"
)

原因

1. Kotlin 数据类的字节码不同

两个类的字节码如下:

public final class WithoutDefaultConstructor {
   private final int intValue;
   @NotNull
   private final String strValue;

   public WithoutDefaultConstructor(int intValue, @NotNull String strValue) {
      super();
      this.intValue = intValue;
      this.strValue = strValue;
   }

   public WithoutDefaultConstructor(int intValue, String strValue, int defaultParametersFlags, DefaultConstructorMarker defaultConstructorMarker) {
      if ((defaultParametersFlags & 2) != 0) {
         strValue = "default";
      }

      this(intValue, strValue);
   }
   //... other methods
}


public final class WithDefaultConstructor {
   private final int intValue;
   @NotNull
   private final String strValue;

   public WithDefaultConstructor(int intValue, @NotNull String strValue) {
      super();
      this.intValue = intValue;
      this.strValue = strValue;
   }

   public WithDefaultConstructor(int intValue, String strValue, int defaultParametersFlags, DefaultConstructorMarker defaultConstructorMarker) {
      if ((defaultParametersFlags & 1) != 0) { // checking binary flag for the first parameter presence `01`
         intValue = 1;
      }

      if ((defaultParametersFlags & 2) != 0) { // checking binary flag for the second parameter presence `10`
         strValue = "default";
      }

      this(intValue, strValue);
   }

   public WithDefaultConstructor() {
      this(0, (String)null, 3, (DefaultConstructorMarker)null);
   }
   //... other methods 
}

当所有参数都有默认值时,编译器会自动为其生成默认无参的构造函数。

2. Java 在 Gson 中的不安全调用

默认构造函数在 Gson 中很重要。其工作方式大致如下:

  • 尝试通过基于 type-token 的 InstanceCreator 来创建对象。
  • 尝试调用默认构造函数。
  • 尝试为 maps,sets,queues 等调用已知的构造函数。
  • 如果都不起效,则会使用 unsafe allocation

这意味着,如果没有 instance creator ,并且类没有默认构造函数,会在不调用构造函数的情况下创建对象。而 Kotlin 将所有非空检查和默认值的分配都放在构造函数中,在这种情况下,它们将都会被跳过。

T


Python 浮点数的一个冷知识

  • 包含 float('nan') 的两个元组,当作整体比较时相等,但其对位的元素可能不相等。
  • float('nan') 表示一个“不是数”的东西,本身是个不确定值,两个对象做比较时不相等,但其哈希值是固定的,作比较值时相等。用作字典的键值时是不冲突的。
  • float('inf') 表示无穷大的浮点数,可看作是确定值,两个对象作比较时相等,哈希结果也相等。但用作字典值时冲突。
  • float('nan') 的哈希结果为 0 ,float('inf') 的哈希结果为 314159

S