使用bufferedInputStream作为scala中的特征时的Stackoverflow

时间:2012-04-16 05:16:34

标签: scala traits

我正在尝试解决“Scala for the Impatient”一书中提出的问题,该书要求将java的BufferedInputStream作为特征实现。这是我的实现,

trait Buffering {           
    this:InputStream =>
        private[this] val bis = {
            new JavaBufferedInputStream(this)
        }
        override def read = bis.read
        override def read(byte:Array[Byte], off:Int, len:Int) = bis.read(byte, off, len)
        override def available = bis.available
        override def close() {
            bis.close
        }
        override def skip(n:Long) = bis.skip(n)
}

def main(args:Array[String]) {
    val bfis = new FileInputStream(new File("foo.txt")) with Buffering
    println(bfis.read)
    bfis.close
}

但是这给了我一个java stackoverflow错误,那么它有什么问题呢?谢谢!

3 个答案:

答案 0 :(得分:4)

看起来你正在获得一个堆栈溢出,你不期望它。解决这些问题的关键是查看堆栈跟踪的重复循环。它通常指向重复分配帧的内容。在这里它将显示类似的东西:

at C.Buffering$class.read(C.scala:12)
at C.C$$anon$1.read(C.scala:23)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at C.Buffering$class.read(C.scala:12)
at C.C$$anon$1.read(C.scala:23)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at C.Buffering$class.read(C.scala:12)

因此,从下到上阅读,看起来read(byte, ...)正在呼叫bis.read(byte, ...)正在呼叫BufferedInputStream.read,然后再次呼叫您的read(byte, ...)

new BufferedInputStream(this)似乎在底层read上调用了InputStream,但由于基础this是您的对象,然后委托bis调用我们有无限的递归。

我猜测作者希望您使用abstract override可堆叠修改模式,您可以使用super来引用正确的read方法。

答案 1 :(得分:0)

也许这就是答案。可能是我理解的。

trait Buffering extends InputStream{
abstract override def read()=
{
    println("Hello");
    super.read()
}
}
val t = new ByteArrayInputStream("hello".getBytes()) with Buffering

答案 2 :(得分:0)

我一直在经历" Scala for the Impatient"。以下是我在第10章中对练习8的解决方案:

import java.io._

object BufferedInputStream extends App {

  trait Buffering {
    this: FileInputStream =>
    val br = new BufferedInputStream(this)
  }

  def bufferedReader(f: String): Unit = {
    val fis = new FileInputStream(f) with Buffering
    var c = 0
    var blen = 8192
    var len = 0
    var b = new Array[Byte](blen)
    while (fis.br.available > 0) {
      if (fis.br.available > blen) len = blen
      else len = fis.br.available
      c = fis.br.read(b, 0, len)
      if (c == -1) return
      print((for (i <- 0 to (c - 1)) yield b(i).toChar).mkString)
    }
    fis.br.close
    fis.close
  }

  bufferedReader("webpagexample")

}