static initialization in interface

2019-01-13 19:45发布

When I tried to write something like this:

public interface MyInterface {
    static {
        System.out.println("Hello!");
    }
}

the compiler could not compile it.

But when I wrote something like this:

interface MyInterface {
    Integer iconst = Integer.valueOf(1);
}

and decompiled it, I saw static initialization:

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
}

Could you please explain this behavior to me?

5条回答
做自己的国王
2楼-- · 2019-01-13 20:25

Intefaces does not have any initialization blocks. Following code snippet may be helpful..

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

}
查看更多
Summer. ? 凉城
3楼-- · 2019-01-13 20:27

Interfaces should not have side-effects and that even applies to static intializers. They would have highly JVM-implementation dependent behavior. Look at the following code

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() {
  }
}

What do you think, when will interface Foo initialized be printed? Try to guess and run code afterwards. The answer might surprise you.

查看更多
Melony?
4楼-- · 2019-01-13 20:30

You can have static initialisation, but you cannot have a static block. The fact the static initialisation needs a static code block to implement does change the Java syntax.

The point is you are not meant to have code in an interface (before Java 8) but you are allowed to initialise fields.

BTW you can have a nested class or enum which has as much code as you like and you can call this while initialising a field. ;)

查看更多
Root(大扎)
5楼-- · 2019-01-13 20:31

You can get around the problem - if you see it as a problem - by putting a second non-public class in the same file.

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

Testing this with:

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

}

prints:

Test Hello
Static Hello
Hello again
Hello

Java is such a clever language - it makes it difficult to do stupid things but not impossible. :)

查看更多
对你真心纯属浪费
6楼-- · 2019-01-13 20:40

There is never a point to declaring a static method in an interface. They cannot be executed by the normal call MyInterface.staticMethod(). (EDIT:Since that last sentence confused some people, calling MyClass.staticMethod() executes precisely the implementation of staticMethod on MyClass, which if MyClass is an interface cannot exist!) If you call them by specifying the implementing class MyImplementor.staticMethod() then you must know the actual class, so it is irrelevant whether the interface contains it or not.

More importantly, static methods are never overridden, and if you try to do:

MyInterface var = new MyImplementingClass();
var.staticMethod();

the rules for static say that the method defined in the declared type of var must be executed. Since this is an interface, this is impossible.

You can of course always remove the static keyword from the method. Everything will work fine. You may have to suppress some warnings if it is called from an instance method.

To answer some of the comments below, the reason you can't execute "result=MyInterface.staticMethod()" is that it would have to execute the version of the method defined in MyInterface. But there can't be a version defined in MyInterface, because it's an interface. It doesn't have code by definition.

查看更多
登录 后发表回答