关于Java中私有静态嵌套类的合成访问器的Eclipse警告?

我的同事build议让几个Eclipse代码格式和警告设置更加严格。 这些变化大部分是有道理的,但我在Java中得到这个奇怪的警告。 这里有一些testing代码来重现“问题”:

package com.example.bugs; public class WeirdInnerClassJavaWarning { private static class InnerClass { public void doSomething() {} } final private InnerClass anInstance; { this.anInstance = new InnerClass(); // !!! this.anInstance.doSomething(); } } // using "this.anInstance" instead of "anInstance" prevents another warning, // Unqualified access to the field WeirdInnerClassJavaWarning.anInstance 

与行!!! 在Eclipse中给我这个警告与我的新的警告设置:

访问封闭构造函数WeirdInnerClassJavaWarning.InnerClass()是由一个综合访问器方法模拟的。 提高可见度将提高你的performance。

这是什么意思? 当我将“private static class”改为“protected static class”时,这个警告消失了,这对我没有任何意义。


编辑:我终于想出了“正确”的修复。 这里真正的问题似乎是这个嵌套的私有静态类缺less一个公共构造函数。 这一个调整删除了警告:

 package com.example.bugs; public class WeirdInnerClassJavaWarning { private static class InnerClass { public void doSomething() {} public InnerClass() {} } final private InnerClass anInstance; { this.anInstance = new InnerClass(); this.anInstance.doSomething(); } } 

我希望这个类是一个私有嵌套类(所以没有其他类可以访问它,包括封闭类的子类),我希望它是一个静态类。

我仍然不明白为什么使嵌套类保护而不是私有是修复“问题”的另一种方法,但也许这是Eclipse的怪癖/错误。

(道歉,我应该把它叫做NestedClass而不是InnerClass更清楚。)

你可以摆脱这个警告,如下所示:

 package com.example.bugs; public class WeirdInnerClassJavaWarning { private static class InnerClass { protected InnerClass() {} // This constructor makes the warning go away public void doSomething() {} } final private InnerClass anInstance; { this.anInstance = new InnerClass(); this.anInstance.doSomething(); } } 

正如其他人所说,Eclipse正在抱怨,因为没有显式构造函数的私有类不能从外部实例化,除非通过Java编译器创build的合成方法。 如果你把你的代码,编译它,然后用jad (*)反编译,你会得到以下(重新格式化):

 public class Test { private static class InnerClass { public void doSomething() {} // DEFAULT CONSTRUCTOR GENERATED BY COMPILER: private InnerClass() {} // SYNTHETIC METHOD GENERATED BY THE JAVA COMPILER: InnerClass(InnerClass innerclass) { this(); } } public Test() { anInstance.doSomething(); } // Your instance initialization as modified by the compiler: private final InnerClass anInstance = new InnerClass(null); } 

如果添加受保护的构造函数,则不需要合成代码。 综合代码在理论上我认为比使用公共或受保护的构造函数的非合成代码要慢的多。

(*)对于jad,我链接到维基百科页面…托pipe此程序的域已过期,但维基百科链接到另一个我没有testing过自己。 我知道还有其他(可能是更新的)反编译器,但这是我开始使用的。 注意:在反编译最近的Java类文件的时候会抱怨 ,但是它仍然做得很好。

顺便说一下,closures警告的设置位于“代码风格”下的Java错误/警告页面中,名为:

访问封闭types的不可访问成员

你不能从WeirdInnerClassJavaWarning实例化InnerClass。 这是私人的,JVM不会让你,但Java语言(出于某种原因)会。

因此,javac会在InnerClass中创build一个只返回新的InnerClass()的附加方法,因此允许您从WeirdInnerClassJavaWarning创buildInnerClass实例。

我不认为你真的需要摆脱它,因为性能下降将是微不足道的。 不过,如果你真的想要的话。

我仍然不明白为什么使嵌套类保护而不是私有是修复“问题”的另一种方法,但也许这是Eclipse的怪癖/错误

这不是Eclipse的怪癖/错误,只是Java的一个特性。 Java语言规范8.8.9说:

…如果该类被声明为protected,则默认的构造函数被隐式地赋予访问修饰符protected …

为了帮助伙计们,如果您在问题中使用原始类代码,则可以得到以下结果

 javac -XD-printflat WeirdInnerClassJavaWarning.java -d tmp 

原始输出,编译器添加了评论。 请注意添加合成包私有类和构造函数。

 public class WeirdInnerClassJavaWarning { { } public WeirdInnerClassJavaWarning() { super(); } { } private final WeirdInnerClassJavaWarning$InnerClass anInstance; { this.anInstance = new WeirdInnerClassJavaWarning$InnerClass(null); this.anInstance.doSomething(); } } class WeirdInnerClassJavaWarning$InnerClass { /*synthetic*/ WeirdInnerClassJavaWarning$InnerClass(WeirdInnerClassJavaWarning$1 x0) { this(); } private WeirdInnerClassJavaWarning$InnerClass() { super(); } public void doSomething() { } } /*synthetic*/ class WeirdInnerClassJavaWarning$1 { } 

你应该能够摆脱它通过使用默认范围,而不是私人或保护,即

 static class InnerClass ... 

还有一点值得注意的是,我把你的光标放在代码行上,按下ctrl-1,Eclipse可能会自动为你解决这个问题。