Eclipse 关于 Java 中私有静态嵌套类的合成访问器的警告?
我的同事建议使一些 Eclipse 代码格式和警告设置更加严格。 大多数这些更改都是有意义的,但我在 Java 中收到了一个奇怪的警告。 这是一些重现“问题”的测试代码:
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() 由合成访问器模拟 方法。 提高其知名度将 提高你的表现。
这是什么意思? 当我将“私有静态类”更改为“受保护的静态类”时,警告消失了,这对我来说没有意义。
编辑:我终于找到了“正确”的修复方法。 这里真正的问题似乎是这个嵌套的私有静态类缺少公共构造函数。 这一调整删除了警告:
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。)
My coworker suggested making several of the Eclipse code-formatting and warning settings to be more rigorous. The majority of these changes make sense, but I get this one weird warning in Java. Here's some test code to reproduce the "problem":
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
The line with the !!! gives me this warning in Eclipse with my new warning settings:
Access to enclosing constructor
WeirdInnerClassJavaWarning.InnerClass()
is emulated by a synthetic accessor
method. Increasing its visibility will
improve your performance.
What does this mean? The warning goes away when I change "private static class" to "protected static class", which makes no sense to me.
edit: I finally figured out the "correct" fix. The real problem here seems to be that this nested private static class is missing a public constructor. That one tweak removed the warning:
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();
}
}
I want the class to be a private nested class (so no other class can have access to it, including subclasses of the enclosing class) and I want it to be a static class.
I still don't understand why making the nested class protected rather than private is another method of fixing the "problem", but maybe that is a quirk/bug of Eclipse.
(apologies, I should have called it NestedClass instead of InnerClass to be more clear.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
为了帮助人们解决问题,如果您在问题中使用原始类代码和
原始输出,您会得到以下结果,编译器添加了注释。 请注意添加了合成包私有类和构造函数。
To help folks out, here is what you get if you use the original class code in the question with
Raw output, compiler added the comments. Note the addition of the synthetic package private class and constructor.
您应该能够通过使用默认范围而不是私有或受保护来摆脱它,即,
还值得注意的是,我将光标放在带有警告的代码行上并按 ctrl-1,Eclipse 可能能够修复这会自动为您服务。
You should be able to get rid of it by using the default scope instead of private or protected, i.e.
It's also worth noting that my placing your cursor on the line of code with the warning and pressing ctrl-1, Eclipse may be able to fix this automatically for you.
您可以按如下方式消除警告:
正如其他人所说,Eclipse 会抱怨,因为没有显式构造函数的私有类无法从外部实例化,除非通过 Java 编译器创建的合成方法。 如果您获取代码,对其进行编译,然后使用 jad 反编译它 (*) ,您将得到以下内容(重新格式化):
如果添加受保护的构造函数,则不需要合成代码。 我认为,理论上,合成代码比使用公共或受保护构造函数的非合成代码慢一点点。
(*) 对于 jad,我链接到一个维基百科页面...托管该程序的域已过期,但维基百科链接到另一个我尚未测试过的页面。 我知道还有其他(可能是更新的)反编译器,但这是我开始使用的。 注意:它在反编译最近的 Java 类文件时抱怨,但它仍然做得很好。
You can get rid of the warning as follows:
As others have said, Eclipse is complaining because a private class with no explicit constructor cannot be instantiated from outside, except via the synthetic method that the Java compiler creates. If you take your code, compile it, and then decompile it with jad (*), you get the following (reformatted):
If you add a protected constructor, the synthetic code is unnecessary. The synthetic code is theoretically, I suppose, slower by a minescule amount than non-synthetic code using a public or protected constructor.
(*) For jad, I linked to a Wikipedia page ... the domain that hosted this program has expired, but Wikipedia links to another that I have not tested myself. I know there are other (possibly more recent) decompilers, but this is the one I started using. Note: It complains when decompiling recent Java class files, but it still does a good job.
顺便说一句,关闭警告的设置位于“代码样式”下的“Java 错误/警告”页面中,名为:
By the way, the setting to turn the warning off is in the Java Errors/Warnings page under "Code style" and is called:
您无法从 WeirdInnerClassJavaWarning 实例化 InnerClass。 它是私有的,JVM 不会让你这么做,但 Java 语言(出于某种原因)会。
因此,javac 将在 InnerClass 中添加一个仅返回 new InnerClass() 的方法,从而允许您从 WeirdInnerClassJavaWarning 创建 InnerClass 实例。
我不认为你真的需要摆脱它,因为性能下降会非常小。 但是,如果您确实愿意,也可以。
You can not instantiate InnerClass from WeirdInnerClassJavaWarning. It's private, JVM wouldn't let you to, but the Java language (for some reason) would.
Therefore, javac would make an additional method in InnerClass that would just return new InnerClass(), therefore permitting you to create InnerClass instances from WeirdInnerClassJavaWarning.
i don't think you really need to get rid of it because the perfomance drop would be inmeasureably tiny. However, you can if you really want to.
这不是 Eclipse 的怪癖/错误,只是 Java 的一个功能。 Java 语言规范,8.8.9 说:
That is not a quirk/bug of Eclipse, just a feature of Java. The Java Language Specification, 8.8.9 says: