JAVAC错误-无法将类识别为静态(后续)

JAVAC错误-无法将类识别为静态(后续),java,compiler-construction,static,javac,Java,Compiler Construction,Static,Javac,这是对上一个问题的补充: 如果找不到更好的解决方案,将使用该解决方案 这个问题将原始内容提炼成一种简单、易于复制的情况,而无需专有代码。因此,这提供了原始版本的完整代码细节 遗憾的是,所使用的java版本无法轻易更改。此问题来自遗留产品支持。一次构建一个文件的奇怪路径模仿了在我们的产品上编写的自定义代码的构建过程,该代码是在遗留api上编写的 为这篇文章的篇幅和细节道歉 问题是: 为什么java编译器无法识别给定的类是静态的 为什么java编译器坚持使用封闭类的实例 这篇文章试图为原

这是对上一个问题的补充:

如果找不到更好的解决方案,将使用该解决方案

这个问题将原始内容提炼成一种简单、易于复制的情况,而无需专有代码。因此,这提供了原始版本的完整代码细节

遗憾的是,所使用的java版本无法轻易更改。此问题来自遗留产品支持。一次构建一个文件的奇怪路径模仿了在我们的产品上编写的自定义代码的构建过程,该代码是在遗留api上编写的

为这篇文章的篇幅和细节道歉


问题是:

  • 为什么java编译器无法识别给定的类是静态的
  • 为什么java编译器坚持使用封闭类的实例
这篇文章试图为原始文章提供不同的细节,希望代码能够演示这种奇怪的行为

,原始帖子被简化为一个简单的3类问题,复制了原始问题。我想知道是否有人能对这一点有更多的了解,并为我们的发现提供一个很好的解释


问题是:

  • 3
    public
    类,其中一个包含
    static
  • 这些类之间的继承关系
  • 使用Microsoft JVC和Sun javac的组合构建(至少在1.4.2_18和一些1.5版本上)
  • 最终构建中断,抱怨
    静态类需要一个封闭的实例,这是不正确的
  • 确切的构建过程包含在批处理文件中,因此它是可复制的

    下面是3个java文件的完整源代码,以及批处理文件。还包括批处理文件的运行时输出


    Outer.java
    超类.java
    BrokenChild.java
    demo.bat
    运行demo.bat的输出

    我相信这一结果使问题不言而喻。我很乐意根据需要提供进一步的详细信息。

    我觉得这像是JDK 1.4.2/1.5中的一个编译器错误。我看不出编译器称之为错误的任何明显解释

    我试图在Java Bugs数据库中搜索类似的东西,但什么也找不到。但这可能意味着这是其他一些bug的另一种表现形式

    人们无法用JDK1.6或1.7重现这一事实很可能意味着这个问题(不管它是什么)已经修复了很长时间

    那么你能做些什么呢?我想,很少。如果您有一份Oracle Java支持合同(涵盖JDK 1.4),那么您可以向他们发出支持请求并要求解释。但是(假设这是一个bug),他们不太可能为您提供修复


    如果您想进一步调查,我建议您做几件事(如果您还没有尝试过):

    • 更改
      BrokenChild
      类,以便不导入这些类。用他们的完全限定名来代替。对
      超类
      类重复此操作

    • 使用
      javap
      检查相关的“.class”文件,看看它们是否有任何意外之处

    • 尝试使用更高版本(Oracle/Sun)的java编译器编译各个文件;e、 g.旧的
      超类
      与新的
      断片
      相反

    (我怀疑其中任何一个都不会透露任何有趣的东西……但它们可能会。)



    我所能说的是,我希望您/您的公司向某人收取大笔费用,因为他们在传统平台上支持此产品。

    对我很有用。您的设置有些奇怪,您可能是地球上最后一个使用Microsoft JSomething编译器的活着的人。如果您尝试使用Ant或Maven编译类,会发生什么情况?在JDK6和JDK7上对我也适用。构建
    BrokenChild.java
    没有问题。我没有尝试过1.4或1.5,因为JDK6问世已经将近七年了。您使用如此旧的版本有什么原因吗?您好,两者都有-不幸的是,这源于一个基于MS JVC 1.1和Sun 1.4的遗留产品。我们相同产品的较新版本基于更真实的JAVAC版本。这个问题并不存在,除非在这个精确的组合中使用JVC和JAVAC,它模仿了我们正在努力解决的现实世界场景。。。同意,这是一个棘手的问题!旧代码FTL…1)不导入类-效果相同。2) 爪哇。。。我会调查的。3) 较新版本不适用于这种情况。4) “很多钱”嗯,我希望如此:)答案不错,但“尝试更新版本”的建议是收集漏洞的证据。。。找不到解决方法。作为错误接受。还在为“很多钱”工作。。。仍然没有找到真正的解决方案,但一些黑客解决了眼前的问题。最终,客户端将不得不升级。
    package demo;
    
    public class Outer
    {
        /** this causes a problem when instantiated in Superclass and in BrokenChild **/
        public static class Static_1
        {
        }
    
        /** this causes no problem as it is not instantiated in SuperClass, only in BrokenChild **/
        public static class Static_2
        {
        }
    }
    
    package demo;
    
    import demo.Outer;
    import demo.Outer.Static_1;
    import demo.Outer.Static_2;
    
    public class SuperClass
    {
        public void breaksBuild()
        {
            // instantiating Static_1 here prevents BrokenChild from instantiating Static_1 in a later build
            Object f = new Static_1();
        }
    
    //  public void breaksBuildIfUncommented()
    //  {
    //      Object f = new Static_2();
    //  }
    
    }
    
    package demo;
    
    import demo.SuperClass;
    
    import demo.Outer;
    import demo.Outer.Static_1;
    import demo.Outer.Static_2;
    
    public class BrokenChild extends SuperClass
    {
        /** method broken because Static_1 is instantiated in SuperClass */
        public void breaksBuild()
        {
            // commenting the below line allows this class to build
            Object f = new Static_1();
        }
    
        /** method works because Static_2 is not instantiated in SuperClass */
        public void buildsProperly()
        {
            // this instance can remain, since it is not instantiated in SuperClass
            Object f = new Static_2();
        }
    
    }
    
    @goto start
    
    Demonstrates both a working build, and a broken build of BrokenChild.
    
    setup for both scenarios:
     - Outer is built with either JVC or JAVAC
    
    scenario #1 - BrokenChild build FAILS:
     - SuperClass is built using JVC
     - BrokenChild does not build using JAVAC
    
    scenario #2 - BrokenChild build works:
     - SuperClass is built using JAVAC
     - BrokenChild does build using JAVAC
    
    
    :start
    
    @prompt $s$s$s$s$g
    
    :: init folders
    @if exist .\build rd .\build /s /q
    @md .\build
    
    @echo ------------------------------------------------------------------------------
    @echo Build Outer using JVC or JAVAC (does not matter)
    jvc.exe /nologo /d .\build .\src\demo\Outer.java
    :: building with JAVAC still breaks the BrokenChild build
    :: javac.exe -d .\build .\src\demo\Outer.java
    @echo.
    
    @echo ------------------------------------------------------------------------------
    @echo Build SuperClass using JVC (building with JAVAC does not break the BrokenChild build)
    jvc.exe /nologo /d .\build -cp:p .\build .\src\demo\SuperClass.java
    :: building with JAVAC does not break the BrokenChild build
    :: javac.exe -d .\build -classpath .\build src\demo\SuperClass.java
    @echo.
    
    @echo ------------------------------------------------------------------------------
    @echo BrokenChild build FAILS using JAVAC
    javac.exe -d .\build -classpath .\build src\demo\BrokenChild.java
    @echo.
    
    @echo.
    @echo Show files
    dir .\build\*.class /s /b
    @echo.
    
    @echo ------------------------------------------------------------------------------
    @echo BrokenChild build WORKS using JVC
    jvc.exe /nologo /d .\build -cp:p .\build .\src\demo\BrokenChild.java
    @echo.
    
    @echo.
    @echo Show files
    dir .\build\*.class /s /b
    @echo.
    @echo ------------------------------------------------------------------------------
    
    @prompt $p$g
    @pause
    
    Build Outer using JVC or JAVAC (does not matter)
    
        >jvc.exe /nologo /d .\build .\src\demo\Outer.java
    
    ------------------------------------------------------------------------------
    Build SuperClass using JVC (building with JAVAC does not break the BrokenChild b
    uild)
    
        >jvc.exe /nologo /d .\build -cp:p .\build .\src\demo\SuperClass.java
    
    ------------------------------------------------------------------------------
    BrokenChild build FAILS using JAVAC
    
        >javac.exe -d .\build -classpath .\build src\demo\BrokenChild.java
    src\demo\BrokenChild.java:15: error: an enclosing instance that contains Outer.S
    tatic_1 is required
                    Object f = new Static_1();
                               ^
    
    
    Show files
    
        >dir .\build\*.class /s /b
    C:\jvc_bug\build\demo\Outer$Static_1.class
    C:\jvc_bug\build\demo\Outer$Static_2.class
    C:\jvc_bug\build\demo\Outer.class
    C:\jvc_bug\build\demo\SuperClass.class
    
    ------------------------------------------------------------------------------
    BrokenChild build WORKS using JVC
    
        >jvc.exe /nologo /d .\build -cp:p .\build .\src\demo\BrokenChild.java
    
    
    Show files
    
        >dir .\build\*.class /s /b
    C:\jvc_bug\build\demo\BrokenChild.class
    C:\jvc_bug\build\demo\Outer$Static_1.class
    C:\jvc_bug\build\demo\Outer$Static_2.class
    C:\jvc_bug\build\demo\Outer.class
    C:\jvc_bug\build\demo\SuperClass.class