接口中的静态初始化

2022-08-31 22:33:52

当我试图写这样的东西时:

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
}

你能向我解释一下这种行为吗?


答案 1

接口不应该有副作用,这甚至适用于静态增强剂。它们将具有高度依赖于 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

您可以具有静态初始化,但不能具有静态块。静态初始化需要一个静态代码块来实现,这一事实确实改变了Java语法。

关键是你不应该在接口中(在Java 8之前)有代码,但你可以初始化字段。

顺便说一句,你可以有一个嵌套的类或枚举,它包含尽可能多的代码,你可以在初始化字段时调用它。;)