Java 接口中的静态初始化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19722847/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 19:41:07  来源:igfitidea点击:

static initialization in interface

javainterfacestatic-initialization

提问by Sergey Morozov

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?

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

采纳答案by Peter Lawrey

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.

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

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

关键是您不打算在接口中包含代码(Java 8 之前),但您可以初始化字段。

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

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

回答by Manish Doshi

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.

在接口中声明静态方法从来没有意义。它们不能通过正常调用 MyInterface.staticMethod() 来执行。(编辑:由于最后一句话混淆了一些人,调用 MyClass.staticMethod() 正是在 MyClass 上执行 staticMethod 的实现,如果 MyClass 是接口,则不存在!)如果您通过指定实现类 MyImplementor.staticMethod() 来调用它们那么你必须知道实际的类,所以接口是否包含它无关紧要。

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.

static 的规则说必须执行在 var 声明类型中定义的方法。由于这是一个接口,这是不可能的。

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.

您当然可以始终从方法中删除 static 关键字。一切都会好起来的。如果从实例方法调用它,您可能必须抑制一些警告。

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.

为了回答下面的一些评论,您不能执行“result=MyInterface.staticMethod()”的原因是它必须执行在 MyInterface 中定义的方法的版本。但是不能在 MyInterface 中定义版本,因为它是一个接口。根据定义,它没有代码。

回答by Holger

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

接口不应该有副作用,这甚至适用于静态初始化器。它们将具有高度依赖于 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() {
  }
}

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

你怎么看,什么时候interface Foo initialized印刷?尝试猜测并在之后运行代码。答案可能会让你大吃一惊。

回答by OldCurmudgeon

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. :)

Java 是一种如此聪明的语言 - 它使做愚蠢的事情变得困难但并非不可能。:)

回答by Siddappa Walake

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

}