关于 Java 中私有静态嵌套类的合成访问器的 Eclipse 警告?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/921025/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Eclipse warning about synthetic accessor for private static nested classes in Java?
提问by Jason S
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":
我的同事建议使一些 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
The line with the !!! gives me this warning in Eclipse with my new warning settings:
同线!!!使用我的新警告设置在 Eclipse 中给我这个警告:
Access to enclosing constructor WeirdInnerClassJavaWarning.InnerClass() is emulated by a synthetic accessor method. Increasing its visibility will improve your performance.
对封闭构造函数 WeirdInnerClassJavaWarning.InnerClass() 的访问由合成访问器方法模拟。提高其可见性将提高您的表现。
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.
我仍然不明白为什么使嵌套类受保护而不是私有是解决“问题”的另一种方法,但这也许是 Eclipse 的一个怪癖/错误。
(apologies, I should have called it NestedClass instead of InnerClass to be more clear.)
(抱歉,为了更清楚,我应该称它为 NestedClass 而不是 InnerClass。)
采纳答案by Eddie
You can get rid of the warning as follows:
您可以通过以下方式消除警告:
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();
}
}
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):
正如其他人所说,Eclipse 抱怨是因为没有显式构造函数的私有类无法从外部实例化,除非通过 Java 编译器创建的合成方法。如果你把你的代码编译,然后用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);
}
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 complainswhen decompiling recent Java class files, but it still does a good job.
(*) 对于 jad,我链接到了一个维基百科页面……托管这个程序的域已经过期,但维基百科链接到另一个我自己没有测试过的页面。我知道还有其他(可能是更新的)反编译器,但这是我开始使用的。注意:它在反编译最近的 Java 类文件时会报错,但它仍然做得很好。
回答by alamar
You can not instantiate InnerClass from WeirdInnerClassJavaWarning. It's private, JVM wouldn't let you to, but the Java language (for some reason) would.
您不能从 WeirdInnerClassJavaWarning 实例化 InnerClass。它是私有的,JVM 不允许您这样做,但 Java 语言(出于某种原因)可以。
Therefore, javac would make an additional method in InnerClass that would just return new InnerClass(), therefore permitting you to create InnerClass instances from WeirdInnerClassJavaWarning.
因此,javac 会在 InnerClass 中创建一个额外的方法,它只会返回 new InnerClass(),从而允许您从 WeirdInnerClassJavaWarning 创建 InnerClass 实例。
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.
我不认为你真的需要摆脱它,因为性能下降将是微乎其微的。但是,如果您真的愿意,也可以。
回答by izb
You should be able to get rid of it by using the default scope instead of private or protected, i.e.
您应该能够通过使用默认范围而不是私有或受保护的范围来摆脱它,即
static class InnerClass ...
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.
还值得注意的是,我将光标放在带有警告的代码行上并按 ctrl-1,Eclipse 可能会自动为您修复此问题。
回答by user85421
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
我仍然不明白为什么使嵌套类受保护而不是私有是解决“问题”的另一种方法,但这也许是 Eclipse 的一个怪癖/错误
That is not a quirk/bug of Eclipse, just a feature of Java. The Java Language Specification, 8.8.9says:
这不是 Eclipse 的怪癖/错误,只是 Java 的一个特性。在Java语言规范,8.8.9说:
... if the class is declared protected, then the default constructor is implicitly given the access modifier protected ...
...如果类声明为protected,则默认构造函数被隐式赋予访问修饰符protected ...
回答by robinst
By the way, the setting to turn the warning off is in the Java Errors/Warnings page under "Code style" and is called:
顺便说一下,关闭警告的设置位于“代码样式”下的 Java 错误/警告页面中,并被调用:
Access to a non-accessible member of an enclosing type
访问封闭类型的不可访问成员
回答by Joseph Lust
To help folks out, here is what you get if you use the original class code in the question with
为了帮助人们,如果您使用问题中的原始类代码,您会得到以下结果
javac -XD-printflat WeirdInnerClassJavaWarning.java -d tmp
Raw output, compiler added the comments. Note the addition of the synthetic package private class and constructor.
原始输出,编译器添加了注释。注意合成包私有类和构造函数的添加。
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 x0) {
this();
}
private WeirdInnerClassJavaWarning$InnerClass() {
super();
}
public void doSomething() {
}
}
/*synthetic*/ class WeirdInnerClassJavaWarning {
}