我正在尝试理解java中的编译与运行时计算。我有以下内容 枚举
public enum SightSensor{
NORTH (new MapLocation[]{new MapLocation(0,1),
new MapLocation(0,2),
new MapLocation(0,3)}),
SOUTH (new MapLocation[]{new MapLocation(0,-1),
new MapLocation(0,-2),
new MapLocation(0,-3)});
private final MapLocation[] locs;
SightSensor(MapLocation[] locs){
this.locs = locs;
}
public static MapLocation[] getLocs(Direction dir){
if (dir == Direction.NORTH)
return NORTH.locs;
if (dir == Direction.SOUTH)
return SOUTH.locs;
}
};
总之,我想在Direction和数组之间定义一个常量映射 MapLocations。 (也许这是错误的方法吗?我是Java的新手。)现在,如果我 写
MapLocation[] locs = SightSensor.getLocs(Direction.SOUTH_WEST);
在代码中的循环内部,我发现第一次代码时会有成本开销 被称为,暗示我在某种程度上是在运行时计算/实例化。如果相反 我只是直接编码
MapLocation[] locs = new MapLocation[]{new MapLocation(0,1),
new MapLocation(0,2),
new MapLocation(0,3)};
没有成本开销。我不明白其中的区别。编译器是否做了一些 奇怪的即时计算?
答案 0 :(得分:3)
您看到的成本似乎是类加载成本:代码第一次访问类时,类加载器将其二进制(.class文件)加载到内存中。这是一次性成本,对于大多数实际目的而言可以忽略不计。
此外:
现在,如果我在代码中的循环中编写...,我发现第一次调用代码时会产生成本开销,
你是如何衡量这笔费用的?几乎不可能测量单个操作的时间成本。您可以通过循环测量执行xM传递所需的时间,然后可以除以获得摊销成本。但是,测量单个操作很困难:您可能正在获得垃圾收集周期,与线程相关的上下文切换等。此外,JIT(即时)编译器在第一次执行语句时不会启动,因此测量一次操作通常会比N次操作的摊销成本高得多。
FWIW,我会写getLocs()
如下:
public static MapLocation[] getLocs(Direction dir) {
return valueOf(dir.name()).locs;
}
或者,您可以使用将类型为EnumMap的变量替换为SightSensor枚举:
EnumMap<Direction, MapLocation[]> map = new EnumMap(Direction.class);
map.put(Direction.NORTH, new MapLocation[] { new MapLocation(0, 1),
new MapLocation(0, 2),
new MapLocation(0, 3) });
map.put(Direction.NORTH, new MapLocation[] { new MapLocation(0, -1),
new MapLocation(0, -2),
new MapLocation(0, -3) });
然后,getLocs()
来电变为map.get(dir)
答案 1 :(得分:2)
编译器是否进行了一些奇怪的即时计算?
是的,Java运行时确实使用统计信息来优化运行时的代码:
http://docs.oracle.com/javase/6/docs/technotes/tools/share/jstat.html
没什么好奇的。
这也可能是相关的:
Real differences between "java -server" and "java -client"?
就个人而言,我认为您应该编写尽可能易于阅读的代码,而不必担心优化。加速可能并不重要。
答案 2 :(得分:0)
这不是一个真正的答案,而是一个提示:让getLocs
非静态,只返回当前枚举的locs
:
public MapLocation[] getLocs(){
return locs;
}
而不是SightSensor.getLocs(someDir)
,而是拨打someDir.getLocs()
。
这样就可以避免枚举枚举的所有成员。