Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java强制编译时评估_Java_Bytecode_Compile Time - Fatal编程技术网

java强制编译时评估

java强制编译时评估,java,bytecode,compile-time,Java,Bytecode,Compile Time,在java中,是否有强制编译时编译的一般方法?在我参加的一个编程竞赛中,我们的机器人在程序运行时每一轮都能使用字节码,因此如果我能在编译时计算东西,我就有优势 作为一个具体的例子,假设我想定义一个变量NORTH,它将是一个数组 地图位置表示机器人朝北时可以看到的正方形。如果我手工编码, 我可以写: public class SightSensor{ public static MapLocation[] NORTH = {new MapLocation(-2,2),

在java中,是否有强制编译时编译的一般方法?在我参加的一个编程竞赛中,我们的机器人在程序运行时每一轮都能使用字节码,因此如果我能在编译时计算东西,我就有优势

作为一个具体的例子,假设我想定义一个变量NORTH,它将是一个数组 地图位置表示机器人朝北时可以看到的正方形。如果我手工编码, 我可以写:

public class SightSensor{
  public static MapLocation[] NORTH = {new MapLocation(-2,2),
                    new MapLocation(-1,1),
                        new MapLocation(-1,2),
                        new MapLocation(0,1),
                        new MapLocation(0,2),
                        new MapLocation(0,3),
                        new MapLocation(1,1),                       
                        new MapLocation(1,2),
                        new MapLocation(2,2)};
}

这表示机器人可以看到90度弧中的所有方格,大约正北,距离平方为9。现在,我的机器人可以看到所有的基本方向,有些可以看得更远 比别人好。每种可能的手工编码方式都相当乏味,而且看起来很糟糕 视线(距离、方向)对。因此,我编写了一个函数

public static MapLocation[] getSensorLocs(int r, Direction dir){ ... bla ... }
这会自动计算位置,因此我可以将SightSensor类重新编写为

public class SightSensor{
  public static MapLocation[] NORTH = getSensorLocs(3, Direction.NORTH);
}
唯一的问题是,当by robot尝试使用NORTH变量时,它必须花费 运行getSensorLocs方法所需的时间,因此它比手写版本更昂贵。
我是否可以强制该计算在编译时运行,即在适当的意义上被“符号替换”?

公共静态映射位置[]北=getSensorLocs(3,Direction.NORTH)
已经只计算了一次——为什么每次都要运行?您已经完成了“预计算”


我不确定这是否真的是一个评估问题。您似乎希望在编译时运行代码,而这通常不是任何语言都能做到的。Java没有预处理器,这可能是最接近您的意思的东西。Java所做的最多的事情是计算,文字“5+3”是“8”。

现在我知道您正在优化字节码大小,您可以使用以下方法

// 8 bytes per field.
public static MapLocation[] NORTH = locations("\u006a\u0079\u007a\u0089\u008a\u008b\u0099\u009a\u009b\u00aa");

// 57 bytes.
public static MapLocation[] locations(String s) {
    final int len = s.length();
    MapLocation[] locations = new MapLocation[len];
    for (int i = 0; i < len; i++) {
        char ch = s.charAt(i);
        locations[i] = new MapLocation((ch >> 4) - 8, (ch & 0xf) - 8);
    }
    return locations;
}

static class MapLocation {
    public MapLocation(int x, int y) {
        System.out.println("x=" + x + ", y=" + y);
    }
}
注意:编码字符串的长度不添加任何字节码



当您运行第一个代码时,它实际上会在运行时创建数组和每个元素。没有编译时优化。我建议您检查一下您的
getSensorLocs
方法是否以及为什么会变慢,因为它不应该明显变慢。

我认为最接近您的方法是编写一个注释处理器,在编译过程中处理代码,就像它在中所做的那样。但这可能需要做大量的工作,因为它显然使用了非公共API,即
javac

,这不是您要求的编译时编译,而是编译时执行

您要求的是在编译时以某种方式计算NORTH,然后将其保存为字节码中的“冻结”值

这通常是不可能或不可取的


如果你可以使用字节码的限制,那么考虑方向等不是作为对象,而是作为标志的数组。这基本上是用Java编写老式的C代码,因此不推荐作为一般最佳实践,但在游戏编程(尤其是在Java ME上)中仍然非常常见。

您可以在另一个Java项目中编写生成.Java文件的代码生成器。您可以重用对象(静态最终MapLocation ML_M2_1=新MapLocation(-2,1);),而不是所有这些
新MapLocation
,这将更有帮助。另一种方法是加快你的速度,考虑到你正在创建查找数据。如果你成功地为
新映射位置(-1,2)
创建了一个像
0xF2
这样的数字编码,你真的会保存一些东西。

我想你正在寻找一个编译时预处理器,类似于C中的预处理器?是的,这正是我所希望的。肖恩,实际上我似乎想要一个预处理器命令。似乎很遗憾,没有办法实现手动编码的速度。我可以编写一个调用结构传感器的边程序,然后为我写一个新的“手编码”的视察类,但是看起来很难看。很多语言都有在编译时运行代码的特性,LISP宏和C++模板是最突出的。C++的模板可以在编译时基本上运行代码。我听说它们被用来计算(在编译时)素数或π之类的。不过,Java不能做那种有趣的事情。@yshavit和Michael,确切地说。我是C++程序员,所以我希望能有类似的东西。当你比较性能时,你能告诉我们这在你的测试中有多大的不同吗?问题似乎是他运行在一个人工环境中,执行速度在字节码级别上受到严格限制,使得延迟初始化的东西成为一个真正的问题。我怀疑他不知道这是一个问题,这只是他习惯做的事情。@PeterLawrey,这看起来就像是一张罚单!我现在就来研究它。@andyin字符串文字是常量,不像数组是以字节码一次生成一个元素。;)精确地代码生成器可能是我唯一的选择。本质上,我是在问如何用Java构建一个高效的查找表。你知道我可以参考哪些资料吗?
x=-2, y=2
x=-1, y=1
x=-1, y=2
x=0, y=1
x=0, y=2
x=0, y=3
x=1, y=1
x=1, y=2
x=1, y=3
x=2, y=2