如果一个人在不同目录中编写了两个具有相同的不区分大小写名称的公共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项目。
如果尝试,我myCase
像这样调用两个类:
System.out.println(A.myCase());
System.out.println(a.myCase());
类型检查器成功,但是当我运行直接由上面代码生成的类文件时,我得到:
线程“主”中的异常java.lang.NoClassDefFoundError:testcase / A(错误名称:testcase / a)
在Java中,名称通常区分大小写。某些文件系统(例如Windows)不区分大小写,因此上述行为不会使我感到惊讶,但这似乎是 错误的
。不幸的是,关于哪些类是可见的,Java规范是奇怪的。在Java语言规范(JLS)的Java SE
7版(第6.6.1节,第166页)说:
如果将类或接口类型声明为公共,则只要可以观察到声明了其的编译单元(第7.3节),任何代码都可以访问它。
在7.3节中,JLS用非常模糊的术语定义了编译单元的可观察性:
预定义包java及其子包lang和io的所有编译单元始终是可观察的。对于所有其他软件包, 主机系统确定可观察到哪些编译单元 。
在Java虚拟机规范同样是模糊的(第5.3.1节):
下列步骤用于加载,从而使用引导类加载器创建由[二进制名称] N表示的非数组类或接口C
[…]否则,Java虚拟机将参数N传递给在以下位置调用方法引导类加载器以依赖于平台的方式搜索C的声称表示。
所有这些都导致四个问题的重要性降序:
a
和A
同步?编写自定义类加载器会起作用吗?
- 是否可以保证每个JVM中的引导类加载器可以加载哪些类?
语言的核心组成部分,以及支持的实现类。不保证包括您编写的任何类。(普通的JVM将您的类加载到与引导程序不同的单独的类加载器中,实际上,常规的引导加载程序通常将其类从JAR加载出来,因为这比充满类的大型旧目录结构更有效地进行了部署。)
- 如果有任何保证,那么上面示例中的行为是否违反了保证(即行为是否是错误)?
- 有什么方法可以使“标准” JVM同时加载a和A?编写自定义类加载器会起作用吗?
Java通过将类的全名映射到文件名中来加载类,然后在类路径中进行搜索。因此,testcase.a
去testcase/a.class
和testcase.A
去testcase/A.class
。一些文件系统将这些东西混合在一起,并可能在有人请求时为其他文件系统服务。其他人则正确(特别是JAR文件中使用的ZIP格式的变体完全区分大小写且可移植)。Java对此无能为力(尽管IDE可以通过使.class
文件远离本机FS
来为您处理它,但我不知道是否有实际作用,而且JDK javac
肯定不是那么聪明)。
但这并不是在这里要注意的唯一一点:类文件在内部知道它们在谈论什么类。文件中缺少 预期的
类仅意味着加载失败,导致NoClassDefFoundError
您收到了该文件。您得到的是一个问题(至少在某种意义上是错误部署),该问题已被发现并得到了有效处理。从理论上讲,您可以构建一个可以通过继续搜索来处理此类事情的类加载器,但是
为什么要麻烦呢? 将类文件放在JAR中可以更牢固地解决问题。那些被正确处理。
更一般而言,如果您确实确实遇到了这个问题,请在具有区分大小写的文件系统(建议使用Jenkins等CI系统)的Unix上进行生产构建,并
找出哪些开发人员在命名时区分大小写并 让他们停下来,因为这非常令人困惑!
问题内容: 我正在尝试提出一个要求区分大小写的结果的请求。 例如在我的数据库中 该请求是 但我有3行作为结果,我只想要abcdef 我试图找到一个解决方案 但是我有这个错误: 未知归类:’Latin1_General_CS_AS’{“成功”:false,“错误”:“#1273-未知归类:’Latin1_General_CS_AS’”} 谢谢 问题答案: 感谢您的帮助,我找到了不是latin1 ut
问题内容: 我到处都读到CSS不区分大小写,但是我有这个选择器 当我像这样在HTML中使用时,它会被拾取 如果我这样改变上面的选择器 这样就不会拾取样式。 问题答案: CSS选择器通常不区分大小写;这包括类和ID选择器。 但是HTML类名 _是_区分大小写的(见属性定义),这就是导致你的第二个例子不匹配。HTML5中没有更改。1个 这是因为选择器的区分大小写取决于文档语言的含义: 在ASCII范围
问题内容: 我遇到一个区分大小写的问题,无法解决问题。 这就是我的文件结构。我只输入要使用的目录,但实际上我使用的是完整安装的CI3。 这是类定义语法的样子: /application/core/My_Controller.php /application/core/Public_Controller.php /application/controllers/application_control
问题内容: 我在另一个列名称为的团队的Postgres中有一个db表说。现在,我试图使用PG指令在此列名上查询该表。 它只是返回 错误:列“ first_Name”不存在 不知道我是在做傻事还是对我遗失的问题有解决方法? 问题答案: 所有未加双引号的 标识符 (包括列名)在PostgreSQL中被折叠为小写。用双引号创建的列名并因此保留了大写字母(和/或其他语法违规),必须在余下的时间将双引号引起
我有一个db表说,在Postgres传给另一个团队,有一个列名说,。现在我试图使用PG指挥官来查询这个列名称上的表。 然后它就回来了 错误:列"first_Name"不存在 不确定我是在做一些愚蠢的事情,还是有解决这个问题的方法,我错过了?
问题内容: 我有一个Lucene索引,该索引当前区分大小写。我想添加的 选项 有不区分大小写作为后备的。这意味着与案例匹配的结果将获得更大的权重,并且将首先出现。例如,如果结果数限制为10,并且有10个匹配项符合我的情况,那就足够了。如果仅找到7个结果,则可以从不区分大小写的搜索中再添加3个结果。 我的案子实际上更复杂,因为我有不同重量的物品。理想情况下,匹配“错误”的表壳会增加一些重量。不用说,