次のようなものを書き込もうとしたとき:
public interface MyInterface {
static {
System.out.println("Hello!");
}
}
コンパイラはコンパイルできませんでした。
しかし、私はこのような何かを書いたとき:
interface MyInterface {
Integer iconst = Integer.valueOf(1);
}
それを逆コンパイルすると、静的な初期化が見られました:
public interface MyInterface{
public static final Java.lang.Integer i;
static {};
Code:
0: iconst_1
1: invokestatic #1; //Method Java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: putstatic #2; //Field i:Ljava/lang/Integer;
7: return
}
この振る舞いを私に説明してもらえますか?
静的な初期化はできますが、静的なブロックはできません。静的初期化が実装するために静的コードブロックを必要とするという事実は、Java構文を変更します。
重要なのは、インターフェイスにコードを置くつもりはない(Java 8)の前)が、フィールドを初期化することは許可されているということです。
ところで、あなたは好きなだけのコードを持つネストされたクラスまたは列挙を持つことができ、フィールドを初期化しながらこれを呼び出すことができます。 ;)
インターフェイスには副作用がないようにし、静的初期化子にも適用する必要があります。それらは、JVM実装に依存する動作が非常に強いでしょう。次のコードを見てください
public class InterfaceSideEffects {
public static void main(String[] args) {
System.out.println("InterfaceSideEffects.main()");
Impl i=new Impl();
System.out.println("Impl initialized");
i.bla();
System.out.println("Impl instance method invoked");
Foo f=new Impl();
System.out.println("Impl initialized and assigned to Foo");
f.bla();
System.out.println("Foo interface method invoked");
}
}
interface Foo {
int dummy=Bar.haveSideEffect();
void bla();
}
class Bar {
static int haveSideEffect() {
System.out.println("interface Foo initialized");
return 0;
}
}
class Impl implements Foo {
public void bla() {
}
}
interface Foo initialized
印刷されますか?後でコードを推測して実行してください。答えはあなたを驚かせるかもしれません。
同じファイルに2つ目の非パブリッククラスを配置することで、問題を回避できます。
public interface ITest {
public static final String hello = Hello.hello();
}
// You can have non-public classes in the same file.
class Hello {
static {
System.out.println("Static Hello");
}
public static String hello() {
System.out.println("Hello again");
return "Hello";
}
}
これをテストする:
public class Test {
public void test() {
System.out.println("Test Hello");
System.out.println(ITest.hello);
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
プリント:
Test Hello
Static Hello
Hello again
Hello
Javaは非常に賢い言語です。バカなことをするのは難しくなりますが、不可能ではありません。 :)
インターフェイスには初期化ブロックはありません。次のコードスニペットが役立つ場合があります。
public interface MyInterface {
public static final int a;// Compilation error as there is no way for
// explicit initialization
}
public class MyClass {
public static final int a;// Still no error as there is another way to
//initialize variable even though they are final.
static{
a=10;
}
}