Я создал небольшой класс Java и выполнил команду javap
против соответствующего файла .class. Я просто делаю это, чтобы понять, как организован файл класса (да, я тоже проходил спецификации JVM). Я мог ошибаться, но из того, что я понимаю в структуре файла классов. кажется, что статический блок на уровне класса отображается как метод.Являются ли статические блоки на уровне класса представленными как методы в байтовом коде?
Я правильно интерпретирую это (что статический блок представляется как метод)? Если да, то статический блок каким-то образом считается эквивалентным методу в Java?
Исходный файл:
package test;
public class TestClass
{
static {
System.out.println("abcd");
}
public void method(String s)
{
System.out.println("hello world");
}
}
javap
выход:
Classfile /C:/TestClass.class
Last modified Dec 25, 2016; size 477 bytes
MD5 checksum 7571c8f98e814fb8bb53885f073c6048
Compiled from "TestClass.java"
public class test.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #7.#17 // java/lang/Object."<init>":()V
#2 = Fieldref #18.#19 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #20 // hello world
#4 = Methodref #21.#22 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = String #23 // abcd
#6 = Class #24 // test/TestClass
#7 = Class #25 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 method
#13 = Utf8 (Ljava/lang/String;)V
#14 = Utf8 <clinit>
#15 = Utf8 SourceFile
#16 = Utf8 TestClass.java
#17 = NameAndType #8:#9 // "<init>":()V
#18 = Class #26 // java/lang/System
#19 = NameAndType #27:#28 // out:Ljava/io/PrintStream;
#20 = Utf8 hello world
#21 = Class #29 // java/io/PrintStream
#22 = NameAndType #30:#13 // println:(Ljava/lang/String;)V
#23 = Utf8 abcd
#24 = Utf8 test/TestClass
#25 = Utf8 java/lang/Object
#26 = Utf8 java/lang/System
#27 = Utf8 out
#28 = Utf8 Ljava/io/PrintStream;
#29 = Utf8 java/io/PrintStream
#30 = Utf8 println
{
public test.TestClass();
descriptor:()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
public void method(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String hello world
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 11: 0
line 12: 8
static {};
descriptor:()V
flags: ACC_STATIC
Code:
stack=2, locals=0, args_size=0
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #5 // String abcd
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 6: 0
line 7: 8
}
SourceFile: "TestClass.java"
Разборка выглядит убедительно для меня. Почему вы считаете, что это не будет эквивалентно методу? Он ведет себя как метод «static void». Вы пытались скомпилировать блок инициализатора элемента (например, нестатический инициализатор), чтобы узнать, что это делает? Помните, что StackOverflow НЕ является дискуссионным сайтом. –
@JimGarrison это действительный и полезный вопрос – firephil
@firephil Не совсем, ответ - деталь реализации. Важно то, что спецификация языка содержит семантику блока инициализатора. Нигде он не заявляет, что он должен быть реализован как «метод», только то, что код выполняется в определенной точке в создании класса или объекта. Ответ, который говорит «да» для Java 8 сегодня, может быть «нет» в Java 9 или Java 10. Кроме того, знание текущего ответа не предоставляет никакой информации, которую вы могли бы использовать для принятия решения о вашей кодировке. –