Java类名称的区分大小写 [英] Case sensitivity of Java class names

查看:301
本文介绍了Java类名称的区分大小写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果在不同的目录中将两个具有相同的不区分大小写的公共Java类写入,那么这两个类在运行时都不可用。 (我在Windows,Mac和Linux上使用多个版本的HotSpot JVM对此进行了测试。如果其他JVM可以同时使用,我也不会感到惊讶。)例如,如果我创建一个名为的类, 和一个名为 A 的人如下:

If one writes two public Java classes with the same case-insensitive name in different directories then both classes are not usable at runtime. (I tested this on Windows, Mac and Linux with several versions of the HotSpot JVM. I would not be surprised if there other JVMs where they are usable simultaneously.) For example, if I create a class named a and one named A like so:

// 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项目是可从我的网站获取

Three eclipse projects containing the code above are available from my website.

如果我尝试在这两个类上调用 myCase ,那么:

If try I calling myCase on both classes like so:

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

typechecker成功,但是当我运行由上面的代码生成的类文件时,我得到:

The typechecker succeeds, but when I run the class file generate by the code directly above I get:


线程main中的异常java.lang.NoClassDefFoundError:testcase / A(错误名称:testcase / a)

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

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

In Java, names are in general case sensitive. Some file systems (e.g. Windows) are case insensitive, so I'm not surprised the above behavior happens, but it seems wrong. Unfortunately the Java specifications are oddly non-commital about which classes are visible. The Java Language Specification (JLS), Java SE 7 Edition (Section 6.6.1, page 166) says:


如果类或接口类型被声明为public,则可以通过$访问它b $ b任何代码,只要声明它的编译单元(第7.3节)是
observable。

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以极其模糊的术语定义了编译单元的可观察性:

In Section 7.3, the JLS defines observability of a compilation unit in extremely vague terms:


预定义包java及其所有的编译单元subpackages lang
和io总是可以观察到的。对于所有其他包,主机系统确定哪些编译单元是可观察的

Java虚拟机规范同样模糊(第5.3.1节):

The Java Virtual Machine Specification is similarly vague (Section 5.3.1):


以下步骤用于加载,从而使用引导程序创建由[二进制名称] N表示的非阵列类或
接口C class loader [...]
否则,Java虚拟机将参数N传递给bootstrap类加载器上
方法的调用,以搜索一个声称的C
表示形式。依赖于平台的方式。

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.

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

All of this leads to four questions in descending order of importance:


  1. 是否可以保证每个JVM中的默认类加载器可以加载哪些类?换句话说,我可以实现一个有效但退化的JVM,它不会加载除java.lang和java.io中的类之外的任何类吗?

  2. 如果有任何保证,上述示例中的行为是否违反保证(即行为是否为错误)?

  3. 有没有如何使HotSpot同时加载 a A ?编写自定义类加载器会起作用吗?

  1. Are there any guarantees about which classes are loadable by the default class loader(s) in every JVM? In other words, can I implement a valid, but degenerate JVM, that won't load any classes except those in java.lang and java.io?
  2. If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?
  3. Is there any way to make HotSpot load a and A simultaneously? Would writing a custom class loader work?


推荐答案



  • 是否可以保证每个JVM中的引导类加载器可以加载哪些类?

语言的核心部分,以及支持实现类。不保证包括您编写的任何课程。 (普通的JVM在一个单独的类加载器中将类加载到引导程序中,实际上正常的引导程序加载程序通常会从JAR中加载它的类,因为这比一个充满类的大型旧目录结构更有效。)

The core bits and pieces of the language, plus supporting implementation classes. Not guaranteed to include any class that you write. (The normal JVM loads your classes in a separate classloader from the bootstrap one, and in fact the normal bootstrap loader loads its classes out of a JAR normally, as this makes for more efficient deployment than a big old directory structure full of classes.)



  • 如果有任何保证,上述示例中的行为是否违反了保证(即行为)一个错误)?

  • 有没有办法让标准JVM同时加载a和A?编写自定义类加载器是否有效?

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

Java loads classes by mapping the full name of the class into a filename that is then searched for on the classpath. Thus testcase.a goes to testcase/a.class and testcase.A goes to testcase/A.class. Some filesystems mix these things up, and may serve the other up when one is asked for. Others get it right (in particular, the variant of the ZIP format used in JAR files is fully case-sensitive and portable). There is nothing that Java can do about this (though an IDE could handle it for you by keeping the .class files away from the native FS, I don't know if any actually do and the JDK's javac most certainly isn't that smart).

然而,这不是唯一的指向请注意:类文件在内部知道他们在谈论什么类。文件中缺少期望的类只意味着加载失败,导致您收到的 NoClassDefFoundError 。你得到的是一个问题(至少在某种意义上的错误部署),这个问题被强有力地检测和处理。从理论上讲,你可以构建一个可以通过保持搜索来处理这类事情的类加载器,但为什么要这么麻烦?将类文件放在JAR中可以更加强大地解决问题。这些都是正确处理的。

However that's not the only point to note here: class files know internally what class they are talking about. The absence of the expected class from the file just means that the load fails, leading to the NoClassDefFoundError you received. What you got was a problem (a mis-deployment in at least some sense) that was detected and dealt with robustly. Theoretically, you could build a classloader that could handle such things by keeping searching, but why bother? Putting the class files inside a JAR will fix things far more robustly; those are handled correctly.

更一般地说,如果你真的遇到这个问题很多,那么在带有区分大小写的文件系统的Unix上进行生产构建(建议像Jenkins这样的CI系统)并且找出哪些开发人员只是在案例差异的情况下命名类,并且让它们停止,因为它非常混乱!

More generally, if you're running into this problem for real a lot, take to doing production builds on a Unix with a case-sensitive filesystem (a CI system like Jenkins is recommended) and find which developers are naming classes with just case differences and make them stop as it is very confusing!

这篇关于Java类名称的区分大小写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆