gpt4 book ai didi

java - Java 类名区分大小写

转载 作者:IT老高 更新时间:2023-10-28 20:35:29 33 4
gpt4 key购买 nike

如果一个人在不同的目录中使用相同的不区分大小写的名称编写两个公共(public) Java 类,那么这两个类在运行时都不能使用。 (我在 Windows、Mac 和 Linux 上使用多个版本的 HotSpot JVM 进行了测试。如果有其他 JVM 可以同时使用它们,我不会感到惊讶。)例如,如果我创建一个名为 a 的类> 和一个像这样命名的 A :

// lowercase/src/testcase/a.java
package testcase;
public class a {
public static String myCase() {
return "lower";
}
}

// uppercase/src/testcase/A.java
package testcase;
public class A {
public static String myCase() {
return "upper";
}
}

包含上述代码的三个 Eclipse 项目是 available from my website .

如果我尝试在两个类上调用 myCase,如下所示:

System.out.println(A.myCase());
System.out.println(a.myCase());

类型检查成功,但是当我运行上面直接生成的代码时,我得到:

Exception in thread "main" java.lang.NoClassDefFoundError: testcase/A (wrong name: testcase/a)

在 Java 中,名称通常区分大小写。一些文件系统(例如 Windows)不区分大小写,所以我对上述行为的发生并不感到惊讶,但它似乎错误。不幸的是,Java 规范对于哪些类是可见的很奇怪。 Java Language Specification (JLS), Java SE 7 Edition (第 6.6.1 节,第 166 页)说:

If a class or interface type is declared public, then it may be accessed by any code, provided that the compilation unit (§7.3) in which it is declared is observable.

在第 7.3 节中,JLS 用极其模糊的术语定义了编译单元的可观察性:

All the compilation units of the predefined package java and its subpackages lang and io are always observable. For all other packages, the host system determines which compilation units are observable.

Java Virtual Machine Specification同样含糊不清(第 5.3.1 节):

The following steps are used to load and thereby create the nonarray class or interface C denoted by [binary name] N using the bootstrap class loader [...] Otherwise, the Java virtual machine passes the argument N to an invocation of a method on the bootstrap class loader to search for a purported representation of C in a platform-dependent manner.

所有这些都导致了四个问题,按重要性降序排列:

  1. 是否可以保证每个 JVM 中的默认类加载器可以加载哪些类?换句话说,我能否实现一个有效但退化的 JVM,它不会加载除 java.lang 和 java.io 中的类之外的任何类?
  2. 如果有任何保证,上面示例中的行为是否违反了保证(即该行为是否存在错误)?
  3. 有没有办法让 HotSpot 同时加载 aA ?编写自定义类加载器有用吗?

最佳答案

  • Are there any guarantees about which classes are loadable by the bootstrap class loader in every JVM?

语言的核心部分,以及支持的实现类。不保证包含您编写的任何类(class)。 (普通的 JVM 将您的类加载到与 Bootstrap 不同的类加载器中,事实上,普通的引导加载器通常从 JAR 中加载其类,因为这比充满类的大型旧目录结构更有效地部署。)

  • If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?
  • Is there any way to make "standard" JVMs load a and A simultaneously? Would writing a custom class loader work?

Java 通过将类的全名映射到文件名来加载类,然后在类路径中搜索该文件名。因此 testcase.a 转到 testcase/a.class 并且 testcase.A 转到 testcase/A.class .一些文件系统将这些东西混合在一起,并且可能会在需要时为其他文件系统提供服务。其他人做对了(特别是 JAR 文件中使用的 ZIP 格式的变体是完全区分大小写和可移植的)。 Java 对此无能为力(尽管 IDE 可以通过将 .class 文件远离 native FS 来为您处理它,但我不知道是否有任何实际操作和 JDK 的 javac 肯定没那么聪明)。

但这并不是这里要注意的唯一一点:类文件在内部知道它们在谈论什么类。文件中缺少 expected 类仅意味着加载失败,导致您收到 NoClassDefFoundError。你得到的是一个问题(至少在某种意义上是错误部署),它被检测到并得到了强有力的处理。从理论上讲,您可以构建一个可以通过不断搜索来处理此类事情的类加载器,但是何必呢?这些都得到了正确的处理。

更一般地说,如果您经常遇到此问题,请在具有区分大小写文件系统的 Unix 上进行生产构建(推荐使用 Jenkins 等 CI 系统)并查找哪些开发人员是仅区分大小写并让它们停止,因为这非常令人困惑!

关于java - Java 类名区分大小写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10890805/

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