月度归档:2015年12月

Int与Integer的拆箱问题

一段程序从java迁移到scala后遇到的,

private val map = new java.util.concurrent.ConcurrentHashMap[String, Int]

val c = map.get(key)

// 下面的if语句在eclipse里提示
// comparing values of types Int and Null using `==' will always yield false
if (c == null) { 
    ...  
}

问题简化后如下:

scala> val m = new java.util.concurrent.ConcurrentHashMap[String, Int]
m: java.util.concurrent.ConcurrentHashMap[String,Int] = {}

scala> m.get("key")
res0: Int = 0

scala> val m = new java.util.concurrent.ConcurrentHashMap[String, java.lang.Integer]
m: java.util.concurrent.ConcurrentHashMap[String,Integer] = {}

scala> m.get("key")
res2: Integer = null

为何value设置为scala里的Int类型得到0而用java里的Integer确是null? 跟以前遇到的null造型为值类型时为何不抛异常 是相似的事

$ scala -Xprint:jvm -e 'val m = new java.util.concurrent.ConcurrentHashMap[String, Int]; val c = m.get("key")'
...
anon$1.this.m = new java.util.concurrent.ConcurrentHashMap();
anon$1.this.c = scala.Int.unbox(anon$1.this.m().get("key"));
...

$ scala -Xprint:jvm -e 'val n:Int = null.asInstanceOf[Int]' ...
anon$1.this.n = scala.Int.unbox(null);
...

scala> val n:Int = null.asInstanceOf[Int]
n: Int = 0

scala> scala.Int.unbox(null)
res3: Int = 0



scala> null.asInstanceOf[java.lang.Integer]
res5: Integer = null

scala> null.asInstanceOf[Int]
res6: Int = 0

scala.Int.unbox 注释里提到运行时是 scala.runtime.BoxesRunTime里的unboxToInt方法

package scala.runtime.BoxesRunTime;

public static int unboxToInt(Object i) {
    return i == null ? 0 : ((java.lang.Integer)i).intValue();
}

还是在对待Int类型时,两种语言设计上的差异,Scala里统一了primitive类型和引用类型。

kafka的advertised.host.name参数

机器有两块网卡,kafka的host.name开始只绑定在了内部IP上,另一块对外网卡无法访问,把值设置为空的话会kafka监听端口在所有的网卡上绑定,但是在外网访问时,客户端又遇到了java.nio.channels.ClosedChannelException异常信息,server端用tcpdump分析的时候发现客户端有传递kafka所在机器的机器名过来。在client里断点跟踪一下发现是findLeader的时候返回的元信息是机器名而不是IP。客户端无法解析这个机器名所以出现了前面的异常。

在server.properties 里还有另一个参数是解决这个问题的, advertised.host.name参数用来配置返回的host.name值,把这个参数配置为外网IP地址即可。

这个参数默认没有启用,默认是返回的java.net.InetAddress.getCanonicalHostName的值,在我的mac上这个值并不等于hostname的值而是返回IP,但在linux上这个值就是hostname的值。