2012-01-03 17 views
3

Javaでは、コンパイル時のコンパイルを強制する一般的な方法はありますか?プログラミング競争では、プログラムの実行中に私たちのロボットが毎回使うことができるバイトコードによって制限されているので、コンパイル時に物事を計算することができれば利点があります。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)}; 

}

ロボットは今9の平方距離内の真北、約90度の円弧ですべての正方形を見ることができることを表して

、私のロボットはすべての基本的な方向で見ることができ、いくつかは他のものよりもさらに を見ることができます。それはむしろ退屈で、一見悪い形でそれぞれコードを手渡すことになります 視力(距離、方向)のペア。したがって、私は機能自動的に場所を計算

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

を書いたので、ロボットによってNORTH変数を使用しようとするとき、私は唯一の問題は今

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

としてSightSensorクラスを再書き込みすることができますgetSensorLocsメソッドを実行するのに、 の時間を費やさなければならないため、手書きのバージョンよりも高価です。 コンパイル時に強制的に計算を実行できますか?つまり、適切な意味で「記号的に置き換えられますか?

+1

私はあなたがコンパイル時のプリプロセッサを探していると思いますが、これはCと同じですか? – Mitch

+0

はい、それは私が望んでいたものです。 – andyInCambridge

答えて

2

バイトコードのサイズが最適化されていることを確認しましたので、次の方法を使用できます。

// 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 

注:符号列の長さは、任意のバイトコードを追加しません!


最初のコードを実行すると、実際には実行時に配列と各要素が作成されます。コンパイル時の最適化はありません。私は、あなたのgetSensorLocsメソッドが遅くならないかどうか、それがどうしてなぜ遅くならないのかを確認することをお勧めします。

+0

問題は、実行速度がバイトコードレベルで厳しく制限されているため、遅延初期化されたものを実際の問題にするという人工環境で動作しているようです。 –

+0

そして、私は彼がその問題を知りませんと思っています。 –

+0

@PeterLawrey、これは単なるチケットのようです!私は今それを調べます。 – andyInCambridge

1

public static MapLocation[] NORTH = getSensorLocs(3, Direction.NORTH);はすでに1回しか評価されていません - なぜ毎回実行されるのですか?あなたはすでに "事前計算"を行っています。

これは本当に評価の問題かどうかはわかりません。コンパイル時にコードを実行したがっているように見えますが、それは一般的な言語ではありません。 Javaにはプリプロセッサがありません。これは、あなたが意味するものに最も近いものかもしれません。ほとんどのJavaは、 "5 + 3"という文字が "8"であることを計算するようなものです。

+0

Sean、実際には私はプリプロセッサコマンドを望んでいるようです。手書きの速度を達成する方法がないことは悲しいことです。私はConstruct-Sensorを呼び出すサイドプログラムを書いて、新しい「ハンドコード」のSightSensorクラスを書きますが、それはちょっと醜いようです。 – andyInCambridge

+1

多くの言語には、コンパイル時にコードを実行する機能があり、LispマクロとC++テンプレートが最も顕著です。 –

+0

C++のテンプレートは基本的にコンパイル時にコードを実行できます。コンパイル時に素数やpiなどを計算するのに使用されていると聞いています。しかし、アフリカ、Javaはそのような楽しいものを行うことはできません。 – yshavit

0

私は、コンパイル時にコードを操作する注釈プロセッサーを書くことが最も近いと考えています。これはProject Lombokで行われています。しかし、それは明らかに非公開APIのjavacを使用しているので、かなりの作業になる可能性があります。

1

これはコンパイル時のコンパイルではなく、コンパイル時の実行です。

あなたが求めているのは、NORTHが何らかの形でコンパイル時に計算されてから、バイトコードに "フリーズ"された値として保存されることです。

これは一般的には可能ではありません。

使用できるバイトコードの量が制限されている場合は、オブジェクトなどではなくフラグの配列として方向などを表現することを検討してください。これは基本的に古いクラスのCコードをJavaで書いているため、一般的なベストプラクティスとしては推奨されませんが、ゲームプログラミング(特にJava ME)ではかなり一般的です。

0

他のJavaプロジェクトでは、 javaファイル。それらのすべての代わりにnew MapLocationのあなたはオブジェクト(static final MapLocation ML_M2_1 = new MapLocation(-2, 1);)を再利用することができます。スピードをさらに速めるための唯一の方法は、ルックアップデータを作成することです。 new MapLocation(-1, 2)0xF2のような数値コードを作成すると、実際に何かが保存されます。

+0

正確に。コードジェネレータは私の唯一の選択肢かもしれません。本質的には、Javaで効率的なルックアップテーブルを構築する方法を尋ねています。私が参照するために見てもいい材料のことを知っていますか? – andyInCambridge

関連する問題