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

问题描述 投票:0回答:1

这是上一个问题的后续:

“已接受的答案”给出了“解决方法”,如果找不到更好的解决方案,将使用该解决方法。 这个问题将原始问题提炼成一个简单、易于复制的情况,无需专有代码。因此,这提供了原始代码的完整代码详细信息。 遗憾的是,所使用的 java 版本不能轻易更改。此问题来自旧产品支持。一次构建每个文件的奇怪路径模仿了在我们的产品之上编写的自定义代码的构建过程,在遗留 API 之上编写。

对这篇文章的长度和细节表示歉意。

问题是:


为什么java编译器无法识别给定的类是静态的

为什么 java 编译器坚持使用封闭类的实例?
  • 这篇文章试图提供与原始文章不同的细节,并希望代码能够演示奇怪的行为。
使用这些步骤

,原来的帖子被简化为一个简单的 3 类问题,复制了原来的问题。我想知道是否有人可以进一步阐明这一点,并为我们的发现提供一个很好的解释。

问题是:


3 个 public

类,其中一个包含
    static
  1. 类。
    这些类之间的继承关系。
    使用 Microsoft JVC 和 Sun javac 的组合构建(至少在 1.4.2_18 和某些 1.5 版本上)。
  2. 最终的构建失败了,抱怨
  3. static
  4. 类需要一个封闭的实例,这是不正确的。
  5. 确切的构建过程已包含在批处理文件中,因此它是可复制的。 
  6. 下面是 3 个 java 文件和批处理文件的完整源代码。还有批处理文件的运行时输出。

外部.java

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

SuperClass.java

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(); // } }

BrokenChild.java

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(); } }

演示.bat

@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

运行 demo.bat 的输出

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

我相信输出使问题变得不言而喻。我很乐意根据需要提供更多详细信息。
    

对我来说,这看起来像是 JDK 1.4.2 / 1.5 中的编译器错误。 对于编译器称其为错误的情况,我看不到任何明显的解释。

java static javac
1个回答
2
投票

人们无法使用 JDK 1.6 或 1.7 重现此问题这一事实很可能意味着该问题(无论它是什么)已经修复很长时间了。

那么你能做些什么呢? 我怀疑,很少。 如果您有 Oracle Java 支持合同(涵盖 JDK 1.4),那么您可以向他们发出支持请求并要求解释。 但是(假设这

一个错误)他们不太可能为您提供修复。

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


更改

BrokenChild
    类,这样您就不会
  • import

    这些类。 请改用其完全限定名称来引用它们。 重复

    SuperClass
    课程 ...
    
    
    使用

    javap
  • 检查相关的“.class”文件,看看是否有什么意外的地方。
  • 尝试使用更高版本的(Oracle/Sun)java编译器编译各个文件;例如旧的 

    SuperClass
  • 与新的
  • BrokenChild

    反之亦然
    
    
    
    (我怀疑其中任何一个都会揭示任何有趣的东西......但他们可能会。)

我只能说,我希望您/您的公司向某人收取大量费用以在旧平台上支持此产品。


© www.soinside.com 2019 - 2024. All rights reserved.