java-中的静态初始化
当我试图写这样的东西:
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
}
您能否向我解释这种行为?
5个解决方案
21 votes
接口不应有副作用,甚至应适用于静态初始化器。 他们将具有高度依赖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? 然后尝试猜测并运行代码。 答案可能会让您感到惊讶。
Holger answered 2020-08-03T00:49:43Z
15 votes
您可以具有静态初始化,但不能具有静态块。 静态初始化需要静态代码块来实现的事实确实改变了Java语法。
关键是您不打算在接口中包含代码(在Java 8之前),但是可以初始化字段。
顺便说一句,您可以有一个嵌套的类或枚举,其中包含所需的代码,您可以在初始化字段时调用它。 ;)
Peter Lawrey answered 2020-08-03T00:49:18Z
6 votes
您可以通过在同一文件中放置第二个非公共类来解决该问题(如果您将其视为问题)。
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是一种聪明的语言-它使很难做愚蠢的事情,但并非不可能。 :)
OldCurmudgeon answered 2020-08-03T00:50:16Z
0 votes
接口没有任何初始化块。 遵循以下代码段可能会有所帮助。
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;
}
}
Siddappa Walake answered 2020-08-03T00:50:36Z
-1 votes
在接口中声明静态方法永远没有意义。 它们不能通过常规调用MyInterface.staticMethod()执行。 (编辑:由于最后一句话使某些人感到困惑,因此,调用MyClass.staticMethod()会在MyClass上精确执行staticMethod的实现,如果MyClass是接口,则该方法将不存在!)如果通过指定实现类MyImplementor.staticMethod()来调用它们 那么您必须知道实际的类,因此该接口是否包含它是无关紧要的。
更重要的是,静态方法永远不会被覆盖,如果您尝试这样做:
MyInterface var = new MyImplementingClass();
var.staticMethod();
静态规则说必须执行声明的var类型中定义的方法。 由于这是一个接口,因此这是不可能的。
当然,您总是可以从方法中删除static关键字。 一切都会正常。 如果从实例方法中调用它,则可能不得不禁止某些警告。
为了回答下面的一些评论,不能执行“ result = MyInterface.staticMethod()”的原因是它必须执行MyInterface中定义的方法的版本。 但是在MyInterface中无法定义一个版本,因为它是一个接口。 根据定义,它没有代码。
Manish Doshi answered 2020-08-03T00:51:15Z