java编译与运行时计算

时间:2012-01-02 21:29:31

标签: java enums runtime

我正在尝试理解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)};

没有成本开销。我不明白其中的区别。编译器是否做了一些 奇怪的即时计算?

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()

这样就可以避免枚举枚举的所有成员。