代码之家  ›  专栏  ›  技术社区  ›  Mitch Blevins

意外的scala默认值行为

  •  3
  • Mitch Blevins  · 技术社区  · 15 年前

    为什么这里的默认值在显式分配给VAL时表现不同,而不是直接打印?

    package blevins.example
    
    class SimpleWrap[T] {
      var t: T = _
      def get = t
    }
    
    object App extends Application {
      val swb = new SimpleWrap[Boolean]
      val b = swb.get
      println("b: " + b)  // b: false
      println("swb.get: " + swb.get) // swb.get: null
    
      val swi = new SimpleWrap[Int]
      val i = swi.get
      println("i: " + i) // i: 0
      println("swi.get: " + swi.get) // swi.get: null
    }
    

    我用的是2.8R19890。


    编辑 -当“get”被称为“expecting any”时,似乎会发生奇怪的事情。

      val any1: Any = swb.get
      val any2: Any = b
      println("any1: " + any1) // any1: null
      println("any2: " + any2) // any2: false
    
    1 回复  |  直到 15 年前
        1
  •  4
  •   Flaviu Cipcigan    15 年前

    我很确定这与原始人的拳击/拆箱有关。如果编写处理基元的通用代码,则必须对基元进行装箱,然后在用作基元的位置将其取消装箱。我不确定使用的是什么拆箱算法,但我想它是沿着以下几行:

    if(box == null) 
      default value
    else
      box.unbox
    

    因此, 非常 奇怪的是,我可能会加上,字段的默认值 t 在简单的包装类中 null ,因为字段总是一个装箱的原语,因为泛型是通过类型擦除在JVM级别实现的。因此,JVM看到的只是 T 属于类型 Object ,值为 无效的 . 方法 get 因此将始终返回 无效的 ,但当泛型方法 得到 应该返回一个基元类型, 无效的 未绑定到默认值。

    另外,稍微用反射波拨弄一下确实表明了磁场确实是 无效的 .

    val sw = new SimpleWrap[Boolean]
    sw.getClass.getDeclaredFields.map {
      f => f.setAccessible(true)
      f.get(sw) 
      }
    

    哦,乐趣 无效的 S.解决这个问题的一个方法是使用2.8 @specialised 注释,如果在您使用的夜间构建中实现了注释。

    或者,更好的是,scala编译器可以将这些字段默认为所用原语的实际默认值的装箱默认值。例如,在 SimpleWrap[Boolean] , T 会有那种类型的 对象 价值 java.lang.Boolean(false) 在运行时。

    编辑: 缺陷报告 submitted .

    另一件奇怪的事:

    val x: Int = null.asInstanceOf[Int] // 0
    val y: Boolean = null.asInstanceOf[Boolean] // false
    

    为了使泛型真正成为泛型,并且具有一致的行为,这是应该解决的问题!现在你的 得到 方法的行为不一致。

    --弗拉维厄·西皮根