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

Jas*_*n S 47 java eclipse nested-class java-synthetic-methods

我的同事建议将几个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    
Run Code Online (Sandbox Code Playgroud)

与!!!线!使用我的新警告设置在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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Edd*_*die 43

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

正如其他人所说,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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 除非这是一个J2ME项目,否则最佳解决方案是禁用Eclipse中的警告并编写代码以符合您的意图.在JIT之后,性能损失可以忽略不计或为零. (5认同)

rob*_*nst 21

顺便说一下,关闭警告的设置是在"代码样式"下的Java错误/警告页面中,并被调用:

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


ala*_*mar 9

您无法从WeirdInnerClassJavaWarning实例化InnerClass.它是私有的,JVM不会让你,但Java语言(出于某种原因)会.

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

我不认为你真的需要摆脱它,因为性能下降将是非常小的.但是,如果你真的想,你可以.

  • +1现代JVM上的性能提升应该是完全不重要的.Eclipse在这里过于热情,我完全拒绝了这个警告. (2认同)