gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:28:27 24 4
gpt4 key购买 nike

这是上一个问题的后续:

accepted answer给出了一个解决方法,如果找不到更好的解决方案,将使用该方法。

这个问题将原始问题提炼成一个简单、易于复制的情况,没有专有代码。因此,这提供了原始代码的完整详细信息。

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

对于这篇文章的长度和细节,我们深表歉意。


问题是:

  • 为什么 java 编译器无法识别给定的类是静态的
  • 为什么 java 编译器坚持使用封闭类的实例?

这篇博文试图提供与原博文不同的细节,希望代码能够展示奇怪的行为。

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


问题是:

  1. 3 个public 类,其中一个包含一个static 类。
  2. 这些类之间的继承关系。
  3. 使用 Microsoft JVC 和 Sun javac 的组合构建(至少在 1.4.2_18 和一些 1.5 版本上)。
  4. 最终构建中断,提示 static 类需要一个封闭的实例,这是不正确的。

确切的构建过程已包含在一个批处理文件中,因此它是可复制的。

下面是 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
{
}
}

父类(super class).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();
// }

}

splinter 的 child .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 Bugs 数据库中搜索类似的东西,但找不到任何东西。但这可能意味着这是其他一些错误的另一种表现形式。

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

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


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

  • 更改 BrokenChild 类,这样您就不会导入 那些类。而是通过他们的完全限定名称来引用他们。对 SuperClass 类重复...

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

  • 尝试使用更高版本的 (Oracle/Sun) java 编译器编译单个文件;例如旧的 SuperClass 和较新的 BrokenChild反之亦然

(我怀疑这些是否会揭示任何有趣的东西……但它们可能会。)


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

关于JAVAC 错误 - 无法将类识别为静态(后续),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18098393/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com