簡體   English   中英

java強制編譯時評估

[英]java forcing compile-time evaluation

在java中,是否有一種強制編譯時編譯的通用方法? 在編程競賽中,我所處的是我們的機器人在程序運行時可以使用的字節碼,所以如果我能夠在編譯時計算東西,我就有優勢。

舉一個具體的例子,假設我想定義一個變量NORTH,它將是一個MapLocations數組,表示機器人面向北方時可以看到的方塊。 如果我手動編碼,我可以寫:

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)};

}

這表示機器人可以在距離為9的距離內看到90度弧內的所有正方形。現在,我的機器人可以看到所有基本方向,有些可以看得比其他方向更遠。 手動編碼每個可能的視線(距離,方向)對將是相當繁瑣和看似不好的形式。 因此,我寫了一個函數

public static MapLocation[] getSensorLocs(int r, Direction dir){ ... bla ... }

這會自動計算位置,所以我可以重新編寫SightSensor類

public class SightSensor{
  public static MapLocation[] NORTH = getSensorLocs(3, Direction.NORTH);
}

唯一的問題是現在當機器人試圖使用NORTH變量時,它必須花時間運行getSensorLocs方法,因此它比手寫版本更昂貴。 我可以強制計算在編譯時運行,即在適當的意義上“符號替換”嗎?

現在我了解到您正在優化字節碼大小,您可以使用以下方法。

// 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);
    }
}

版畫

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

注意:編碼String的長度不會添加任何字節代碼!


當您運行第一個代碼時,它實際上在運行時創建數組和每個元素。 沒有編譯時優化。 我建議你檢查你的getSensorLocs方法是否以及為什么速度較慢,因為它不應該慢得多。

public static MapLocation[] NORTH = getSensorLocs(3, Direction.NORTH); 已經只評估過一次 - 為什么每次都會運行? 你已經完成了“預計算”。

我不確定這是否真的是一個評估問題。 您似乎想在編譯時運行代碼,而這通常不是任何語言所做的。 Java沒有預處理器,這可能是你所說的最接近的東西。 大多數Java都是像計算這樣的文字“5 + 3”是“8”。

這不是你要求的編譯時編譯 - 它是編譯時執行。

您要求的是,在編譯時以某種方式計算NORTH,然后將其保存為字節碼中的“凍結”值。

這通常不可能或不可取。

如果您受到可以使用的字節碼數量的限制,那么請考慮將方向等表示為對象,而不是作為標志數組。 這基本上是用Java編寫老式的C代碼,因此不建議作為一般的最佳實踐,但在游戲編程中仍然很常見(特別是在Java ME上)

我相信你能得到的最接近的是編寫一個在編譯過程中操作代碼的注釋處理器,就像它在Project Lombok中完成的那樣。 但這可能是相當多的工作,因為它顯然使用javac非公共API。

您可以在另一個java項目中編寫生成.java文件的代碼生成器。 您可以重用對象( static final MapLocation ML_M2_1 = new MapLocation(-2, 1); ),而不是所有new MapLocation ,這將有助於更多。 唯一能夠提高速度的方法是考慮創建查找數據。 如果你成功為new MapLocation(-1, 2)創建像0xF2這樣的數字編碼new MapLocation(-1, 2)你真的會保存一些東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM