修改:我可以通过在MessageParser类中将val
更改为lazy val
来解决此问题。我忘记了我之前使用def
而不是val.
对其进行了测试。有人能说清楚为什么这个更改会修复它吗?
所以,我目前正在编写一个IRC服务器。我决定使用Scala的Combinator Parser库来帮助我解析消息。我已经能够通过测试程序正确地解析消息了,但是当我尝试将我的解析器合并到我已经写过的echo服务器时,我在连接到服务器时收到以下错误消息:
Connected to the target VM, address: '127.0.0.1:55567', transport: 'socket'
Exception in thread "main" java.lang.ExceptionInInitializerError
at IRCServer.main(IRCServer.scala)
Caused by: java.lang.NullPointerException
at messages.MessageParser.<init>(MessageParser.scala:11)
at net.Connection.<init>(Connection.scala:14)
at net.Server.start(Server.scala:14)
at IRCServer$.<init>(IRCServer.scala:12)
at IRCServer$.<clinit>(IRCServer.scala)
... 1 more
Disconnected from the target VM, address: '127.0.0.1:55567', transport: 'socket'
Connection类处理从ServerSocket
创建的侦听器Socketclass Connection(socket: Socket) extends Thread {
private val out = new PrintStream(socket.getOutputStream)
private val in = new BufferedReader(new InputStreamReader(socket.getInputStream))
private val parser = new MessageParser
override def run(): Unit = {
var line = ""
while({(line = in.readLine); line != null}) {
Console.println("received: " + line)
parser.parseLine(line.trim)
out.println("out: " + line)
}
}
}
以下是我的MessageParser:
class MessageParser extends JavaTokenParsers {
def parseLine(line :CharSequence) = {
parseAll(message, line)
}
val message: Parser[Any] = opt(":"~prefix)~command~opt(params) ^^ (x=> {println("message: "+x)})
val prefix: Parser[Any] = nick~"!"~user~"@"~host | servername ^^ (x=> {println("prefix: " +x)})
val nick: Parser[Any] = letter~rep(letter | wholeNumber | special) ^^ (x=> {println("nick: " +x)})
val special: Parser[Any] = "-" | "[" | "]" | "\\" | "`" | "^" | "{" | "}" ^^ (x=> {println("special: " +x)})
val user: Parser[Any] = """[^\s@]+""".r ^^ (x=> {println("user: " +x)})
val host: Parser[Any] = """[\w\.]+\w+""".r ^^ (x=> {println("host: " +x)})
val servername: Parser[Any] = host ^^ (x=> {println("servername: " +x)})
val command: Parser[Any] = """([A-Za-z]+)|([0-9]{3})""".r ^^ (x=> {println("command: " +x)})
val params: Parser[Any] = rep(param)~opt(":"~tail) ^^ (x=> {println("params: " +x)})
val param: Parser[Any] = """[^:][\S]*""".r
val tail: Parser[Any] = """.*$""".r ^^ (x=> {println("tail: " +x)})
val letter: Parser[Any] = """[A-Za-z]""".r ^^ (x=> {println("letter: " +x)})
}
我不太确定是什么原因引起的。希望我只是对一些小事视而不见。
答案 0 :(得分:3)
lazy val
个值; val
值将按您指定的顺序填充。使用解析器,较早的条目引用后来尚不存在的条目。所以他们最好是lazy val
或def
(哪一个取决于解析器; packrat解析器喜欢lazy val
,而其他人通常假设def
,但我是不确定他们是否需要它。)
答案 1 :(得分:0)
使用以下代码捕获异常:
try {
//your code here
} catch {
case err: ExceptionInInitializerError => err.getCause.printStackTrace
}
这将帮助您找到异常的原因。