与ecj相比,javac生成的行号是否不准确(对于这种特殊情况)?



我使用下面的类,它在equals()方法中具有这种特殊性,即return关键字及其表达式被分成几行(return关键字在自己的行上)。

package jd.core.test;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
public class TimeZoneDisplayKey {
private final TimeZone mTimeZone;
private final int mStyle;
private final Locale mLocale;
public TimeZoneDisplayKey(TimeZone mTimeZone, int mStyle, Locale mLocale) {
this.mTimeZone = mTimeZone;
this.mStyle = mStyle;
this.mLocale = mLocale;
}
@Override
public int hashCode() {
return Objects.hash(mLocale, mStyle, mTimeZone);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
TimeZoneDisplayKey other = (TimeZoneDisplayKey) obj;
return
Objects.equals(mLocale, other.mLocale) &&
mStyle == other.mStyle &&
Objects.equals(mTimeZone, other.mTimeZone);
}
}

我使用javac -g命令(来自JDK 17)和javap -l来获取行号表。下面是javapequals()的简化提取,以说明令人困惑的地方:

31: aload_0
32: getfield      #17                 // Field mLocale:Ljava/util/Locale;
35: aload_2
36: getfield      #17                 // Field mLocale:Ljava/util/Locale;
39: invokestatic  #37                 // Method java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z
42: ifeq          74
45: aload_0
46: getfield      #13                 // Field mStyle:I
49: aload_2
50: getfield      #13                 // Field mStyle:I
53: if_icmpne     74
56: aload_0
57: getfield      #7                  // Field mTimeZone:Ljava/util/TimeZone;
60: aload_2
61: getfield      #7                  // Field mTimeZone:Ljava/util/TimeZone;
64: invokestatic  #37                 // Method java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z
67: ifeq          74
70: iconst_1
71: goto          75
74: iconst_0
75: ireturn
LineNumberTable:
line 26: 0
line 27: 5
line 29: 7
line 30: 11
line 32: 13
line 33: 24
line 35: 26
line 36: 31
line 37: 39
line 39: 64
line 36: 75

它说第36行不止有return,还有return(75: ireturn)和this(31: aload_0),而在源代码中,return关键字在自己的行上。

如果我看看equals()产生ecj的原因,我看不到这个问题:

31: aload_0
32: getfield      #21                 // Field mLocale:Ljava/util/Locale;
35: aload_2
36: getfield      #21                 // Field mLocale:Ljava/util/Locale;
39: invokestatic  #47                 // Method java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z
42: ifeq          72
45: aload_0
46: getfield      #19                 // Field mStyle:I
49: aload_2
50: getfield      #19                 // Field mStyle:I
53: if_icmpne     72
56: aload_0
57: getfield      #17                 // Field mTimeZone:Ljava/util/TimeZone;
60: aload_2
61: getfield      #17                 // Field mTimeZone:Ljava/util/TimeZone;
64: invokestatic  #47                 // Method java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z
67: ifeq          72
70: iconst_1
71: ireturn
72: iconst_0
73: ireturn
LineNumberTable:
line 26: 0
line 27: 5
line 29: 7
line 30: 11
line 32: 13
line 33: 24
line 35: 26
line 37: 31
line 38: 45
line 39: 56
line 36: 70

是的,这是一个javac错误,尽管在本例中您不会注意到它。行号映射仅用于异常堆栈跟踪,因此我没有看到任何问题,除非在mStyle == other.mStyle行上抛出NPE。如果我修改equals方法为破碎:

@Override
public boolean equals(Object obj) {
TimeZoneDisplayKey other = (TimeZoneDisplayKey) obj;
return
Objects.equals(mLocale, mLocale) &&
mStyle == other.mStyle &&
Objects.equals(mTimeZone, other.mTimeZone);
}

然后我用null作为第二个参数调用equals,当试图访问other.mStyle时抛出NullPointerException,但行号错误。它报告上面那行比较(错误地)mLocale字段。

相关内容

  • 没有找到相关文章

最新更新