嵌套 class 类型参数的注释方法有什么区别?
What is the difference between the approachs of annotation on nested class type parameter?
org.jetbrains.annotations.NotNull
public static void func(Foo.Bar.@NotNull Baz arg0) {
}
public static void func(@NotNull Foo.Bar.Baz arg0) {
}
public static void func(@NotNull Foo.Bar.@NotNull Baz arg0) {
}
嵌套 class 类型参数的注释方法有什么区别?
推荐哪一个?
这些只是语法上的不同。从语义上讲,它们都表示“此参数不应为 null”,实际上,所有三个都编译为对参数进行相同的 null 检查。
三个都起作用的原因是因为NotNull
有TYPE_USE
的ElementType
,所以你可以用NotNull
注释任何“类型使用”。好吧,Foo.Bar
中的 Bar
是对类型 Bar
的使用,因此您可以通过 Foo.@NotNull Bar
.
来注释它
这提出了为什么 NotNull
首先有 ElementType.TYPE_USE
的问题。这当然不是让你有 3 种方式说完全相同的事情。更可能的原因是允许您这样做:
List<@NotNull String> listWithNotNullElements;
无论如何,所有这三个都编译为相同的字节码,因为在所有 3 种情况下,NotNull
注释 参数 。
以下所有三个:
package io.github.sweeper777;
import org.jetbrains.annotations.NotNull;
public class Main {
public static void main(String[] args) {
}
public void f( Foo.@NotNull Bar x) {
}
}
class Foo {
static class Bar {
}
}
package io.github.sweeper777;
import org.jetbrains.annotations.NotNull;
public class Main {
public static void main(String[] args) {
}
public void f(@NotNull Foo.@NotNull Bar x) {
}
}
class Foo {
static class Bar {
}
}
package io.github.sweeper777;
import org.jetbrains.annotations.NotNull;
public class Main {
public static void main(String[] args) {
}
public void f(@NotNull Foo.Bar x) {
}
}
class Foo {
static class Bar {
}
}
编译为:
Compiled from "Main.java"
public class io.github.sweeper777.Main {
public io.github.sweeper777.Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
public void f(io.github.sweeper777.Foo$Bar);
Code:
0: aload_1
1: ifnonnull 8
4: iconst_0
5: invokestatic #36 // Method $$$reportNull$$[=14=]:(I)V
8: return
private static void $$$reportNull$$[=14=](int);
Code:
0: ldc #38 // String Argument for @NotNull parameter \'%s\' of %s.%s must not be null
2: iconst_3
3: anewarray #2 // class java/lang/Object
6: dup
7: iconst_0
8: ldc #39 // String x
10: aastore
11: dup
12: iconst_1
13: ldc #40 // String io/github/sweeper777/Main
15: aastore
16: dup
17: iconst_2
18: ldc #41 // String f
20: aastore
21: invokestatic #47 // Method java/lang/String.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
24: new #49 // class java/lang/IllegalArgumentException
27: dup_x1
28: swap
29: invokespecial #52 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
32: athrow
}
org.jetbrains.annotations.NotNull
public static void func(Foo.Bar.@NotNull Baz arg0) {
}
public static void func(@NotNull Foo.Bar.Baz arg0) {
}
public static void func(@NotNull Foo.Bar.@NotNull Baz arg0) {
}
嵌套 class 类型参数的注释方法有什么区别?
推荐哪一个?
这些只是语法上的不同。从语义上讲,它们都表示“此参数不应为 null”,实际上,所有三个都编译为对参数进行相同的 null 检查。
三个都起作用的原因是因为NotNull
有TYPE_USE
的ElementType
,所以你可以用NotNull
注释任何“类型使用”。好吧,Foo.Bar
中的 Bar
是对类型 Bar
的使用,因此您可以通过 Foo.@NotNull Bar
.
这提出了为什么 NotNull
首先有 ElementType.TYPE_USE
的问题。这当然不是让你有 3 种方式说完全相同的事情。更可能的原因是允许您这样做:
List<@NotNull String> listWithNotNullElements;
无论如何,所有这三个都编译为相同的字节码,因为在所有 3 种情况下,NotNull
注释 参数 。
以下所有三个:
package io.github.sweeper777;
import org.jetbrains.annotations.NotNull;
public class Main {
public static void main(String[] args) {
}
public void f( Foo.@NotNull Bar x) {
}
}
class Foo {
static class Bar {
}
}
package io.github.sweeper777;
import org.jetbrains.annotations.NotNull;
public class Main {
public static void main(String[] args) {
}
public void f(@NotNull Foo.@NotNull Bar x) {
}
}
class Foo {
static class Bar {
}
}
package io.github.sweeper777;
import org.jetbrains.annotations.NotNull;
public class Main {
public static void main(String[] args) {
}
public void f(@NotNull Foo.Bar x) {
}
}
class Foo {
static class Bar {
}
}
编译为:
Compiled from "Main.java"
public class io.github.sweeper777.Main {
public io.github.sweeper777.Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
public void f(io.github.sweeper777.Foo$Bar);
Code:
0: aload_1
1: ifnonnull 8
4: iconst_0
5: invokestatic #36 // Method $$$reportNull$$[=14=]:(I)V
8: return
private static void $$$reportNull$$[=14=](int);
Code:
0: ldc #38 // String Argument for @NotNull parameter \'%s\' of %s.%s must not be null
2: iconst_3
3: anewarray #2 // class java/lang/Object
6: dup
7: iconst_0
8: ldc #39 // String x
10: aastore
11: dup
12: iconst_1
13: ldc #40 // String io/github/sweeper777/Main
15: aastore
16: dup
17: iconst_2
18: ldc #41 // String f
20: aastore
21: invokestatic #47 // Method java/lang/String.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
24: new #49 // class java/lang/IllegalArgumentException
27: dup_x1
28: swap
29: invokespecial #52 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
32: athrow
}