java编译时与运行时计算

java编译时与运行时计算,java,enums,runtime,Java,Enums,Runtime,我试图理解java中编译计算与运行时计算的区别。我有以下几点 枚举 换句话说,我想在一个方向和一个数组之间定义一个常量映射 地图位置。(也许这是一种错误的方法?我是Java新手。)现在,如果我 写 在代码中的一个循环中,我发现在第一次编写代码时存在开销 调用,这对我来说意味着它在运行时以某种方式被计算/实例化。如果相反 我只是直接编码 MapLocation[] locs = new MapLocation[]{new MapLocation(0,1),

我试图理解java中编译计算与运行时计算的区别。我有以下几点 枚举

换句话说,我想在一个方向和一个数组之间定义一个常量映射 地图位置。(也许这是一种错误的方法?我是Java新手。)现在,如果我 写

在代码中的一个循环中,我发现在第一次编写代码时存在开销 调用,这对我来说意味着它在运行时以某种方式被计算/实例化。如果相反 我只是直接编码

MapLocation[] locs = new MapLocation[]{new MapLocation(0,1),
                           new MapLocation(0,2),
                           new MapLocation(0,3)};
没有开销。我不明白有什么区别。编译器做了些什么 奇怪的即时计算

编译器会做一些奇怪的即时计算吗

是的,Java运行时确实在运行时使用统计信息来优化代码:

没什么奇怪的

这也可能是相关的:

就个人而言,我认为您应该编写尽可能容易阅读的代码,而不必担心优化。加速可能并不显著

编译器会做一些奇怪的即时计算吗

是的,Java运行时确实在运行时使用统计信息来优化代码:

没什么奇怪的

这也可能是相关的:


就个人而言,我认为您应该编写尽可能容易阅读的代码,而不必担心优化。加速可能并不显著。

您看到的成本似乎是类加载成本:代码第一次访问类时,类加载程序将其二进制(.class文件)加载到内存中。这是一个一次性成本,在大多数实际情况下可以忽略不计

此外:

现在,如果我写。。。在代码中的一个循环中,我发现在第一次调用代码时存在开销

你是如何衡量这一成本的?要衡量一次操作的时间成本几乎是不可能的。您可以通过一个循环测量执行xM过程所需的时间,然后可以进行分割以获得摊余成本。然而,度量单个操作是困难的:您可能会得到垃圾收集周期、与线程相关的上下文切换等。此外,JIT(实时)编译器不会在第一次执行语句时启动,因此度量单个操作通常会给您带来比N个操作的摊余成本高得多的成本

FWIW,我将写
getLocs()
,如下所示:

public static MapLocation[] getLocs(Direction dir) {
  return valueOf(dir.name()).locs;
}
或者,您可以使用EnumMap类型的变量替换SightSensor enum:

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) });
EnumMap map=新的EnumMap(Direction.class);
地图放置(方向北,新地图位置[]{新地图位置(0,1),
新地图位置(0,2),
新映射位置(0,3)};
地图放置(方向北,新地图位置[]{新地图位置(0,-1),
新映射位置(0,-2),
新映射位置(0,-3)};

然后,
getLocs()
调用就变成了
map.get(dir)

您看到的成本似乎是类加载成本:代码第一次访问类时,类加载程序将其二进制(.class文件)加载到内存中。这是一个一次性成本,在大多数实际情况下可以忽略不计

此外:

现在,如果我写。。。在代码中的一个循环中,我发现在第一次调用代码时存在开销

你是如何衡量这一成本的?要衡量一次操作的时间成本几乎是不可能的。您可以通过一个循环测量执行xM过程所需的时间,然后可以进行分割以获得摊余成本。然而,度量单个操作是困难的:您可能会得到垃圾收集周期、与线程相关的上下文切换等。此外,JIT(实时)编译器不会在第一次执行语句时启动,因此度量单个操作通常会给您带来比N个操作的摊余成本高得多的成本

FWIW,我将写
getLocs()
,如下所示:

public static MapLocation[] getLocs(Direction dir) {
  return valueOf(dir.name()).locs;
}
或者,您可以使用EnumMap类型的变量替换SightSensor enum:

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) });
EnumMap map=新的EnumMap(Direction.class);
地图放置(方向北,新地图位置[]{新地图位置(0,1),
新地图位置(0,2),
新映射位置(0,3)};
地图放置(方向北,新地图位置[]{新地图位置(0,-1),
新映射位置(0,-2),
新映射位置(0,-3)};

然后,
getLocs()
调用就变成了
map.get(dir)

这不是一个真正的答案,而是一个提示:使
getLocs
非静态,只需返回当前枚举的
locs

public MapLocation[] getLocs(){
    return locs;
}
然后调用
someDir.getLocs()
,而不是
SightSensor.getLocs(someDir)


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

这不是一个真正的答案,而是一个提示:使
getLocs
非静态,只返回当前枚举的
locs

public MapLocation[] getLocs(){
    return locs;
}
然后调用
someDir.getLocs()
,而不是
SightSensor.getLocs(someDir)


这样,您就不必枚举枚举的所有成员。

您能解释一下您是如何衡量成本开销的吗?此外,您的示例也无法编译;您需要在
getLocs
中使用某种else语句,因为现在存在没有返回值的路径(当
dir
既不是北也不是南时),对此表示抱歉,我们尝试简化代码。用字节码测量。但是……我认为开销是时间,而不是空间?:-)你是如何将字节码大小与第一次/第二次运行联系起来的?你能解释一下你是如何测量字节码大小的吗