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

发布于 2024-07-21 17:57:37 字数 1456 浏览 7 评论 0原文

我的同事建议使一些 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

北风几吹夏 2024-07-28 17:57:37

为了帮助人们解决问题,如果您在问题中使用原始类代码和

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 {
}

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$1 x0) {
        this();
    }

    private WeirdInnerClassJavaWarning$InnerClass() {
        super();
    }

    public void doSomething() {
    }
}

/*synthetic*/ class WeirdInnerClassJavaWarning$1 {
}
暗地喜欢 2024-07-28 17:57:37

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

static class InnerClass ...

还值得注意的是,我将光标放在带有警告的代码行上并按 ctrl-1,Eclipse 可能能够修复这会自动为您服务。

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.

猫瑾少女 2024-07-28 17:57:37

您可以按如下方式消除警告:

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 编译器创建的合成方法。 如果您获取代码,对其进行编译,然后使用 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,我链接到一个维基百科页面...托管该程序的域已过期,但维基百科链接到另一个我尚未测试过的页面。 我知道还有其他(可能是更新的)反编译器,但这是我开始使用的。 注意:它在反编译最近的 Java 类文件时抱怨,但它仍然做得很好。

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):

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 complains when decompiling recent Java class files, but it still does a good job.

唠甜嗑 2024-07-28 17:57:37

顺便说一句,关闭警告的设置位于“代码样式”下的“Java 错误/警告”页面中,名为:

访问封闭类型的不可访问成员

By the way, the setting to turn the warning off is in the Java Errors/Warnings page under "Code style" and is called:

Access to a non-accessible member of an enclosing type

囍笑 2024-07-28 17:57:37

您无法从 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.

撑一把青伞 2024-07-28 17:57:37

<块引用>

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

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

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

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

That is not a quirk/bug of Eclipse, just a feature of Java. The Java Language Specification, 8.8.9 says:

... if the class is declared protected, then the default constructor is implicitly given the access modifier protected ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文