当简单名称和完全限定名称发生冲突时如何引用 class
How to refer to a class when both simple and fully-qualified names clash
考虑以下病态示例:
class Ideone {
static class ArrayList<T> {
ArrayList() {
System.out.println("!!");
}
}
static class java {
static class util {
static class ArrayList<T> {
ArrayList() {
System.out.println("Here");
}
}
}
}
public static void main(String[] args) {
new ArrayList<>();
new java.util.ArrayList<>();
// Can I refer to the "usual" java.util.ArrayList?
}
}
构造函数中创建的两个实例是嵌套的classes.
但是我怎么能在同一个 class 中提到我们都知道和喜爱的 java.util.ArrayList
?我们不能导入它,也不能使用完全限定名称,因为会使用嵌套的 class 符号。
在这种情况下我们能做什么? (除了明显的 - 停止为嵌套的 classes 使用这种肆意邪恶的名称)。
你试过了吗
Class cls = ClassLoader.getSystemClassLoader().loadClass("java.util.ArrayList");
List arrayList = cls.newInstance();
很久没考虑类加载器了,不过IIRC.loadClass()
会优先尝试从最基础的类加载器加载,真正的java.util
包应该由bootstrap 类加载器,其优先级高于您在应用程序中定义的任何内容。
我要冒昧地说,不可能从 Ideone
内部引用它。我看到的唯一解决方案是创建另一个 class Idetwo
(它是 Ideone
的 nestmate(即它驻留在同一个文件中))和 return a java.util.ArrayList
从那里用于 Ideone
:
import java.util.ArrayList;
class Ideone {
...
}
class Idetwo {
static ArrayList<Integer> getList() {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
return list;
}
}
您只需将 Ideone
的主要方法更改为类似以下内容:
public static void main(String[] args) throws Exception {
new Ideone.ArrayList<>();
new Ideone.java.util.ArrayList<>();
Idetwo.getList().forEach(System.out::println);
}
输出:
!!
Here
1
2
3
注意:使用这种方法,导入java.util.ArrayList
就可以了。但是,如果您要在 Ideone
的主要方法中调用 List<Integer> list = Idetwo.getList();
,则需要导入 java.util.*
,因为单个导入将不起作用(有趣的是)。
这就是为什么包以小写字母开头,类型以大写字母开头的原因,因为 very first edition of the official code conventions for java。我认为我从未见过 java 代码违反此约定。
但是您可以使用它的完全限定名称从外部引用内部类型:
com.whatever.bad.project.SomeClass.java.util.ArrayList
当您必须从内部引用外部类型时,您可以更改该源文件以符合 Java 命名准则。
如果您已完成以下两件事,您将无法再直接引用 java.util.ArrayList
:
- 在作用域中用静态嵌套 class 隐藏简单名称
ArrayList
。
- 隐藏完全限定名称
java.util.ArrayList
与 class ArrayList
嵌套在 class util
中,嵌套在嵌套 class java
.
您甚至无法 "split" 尝试使用 "partially qualified" 导入。
import java.*;
...
// This doesn't work!
new util.ArrayList<>();
你可以import java.*;
,但那是没有价值的;没有 class 直接在 java
包中定义。
但是,您可以间接引用 class java.util.ArrayList
,因为它不是 final
。在 class Ideone
的范围之外,声明一个具有不同名称的子class。
class AnArrayList<T> extends java.util.ArrayList<T> {}
那你可以参考那个class编程到接口:
List<Integer> al = new AnArrayList<>(); // won't print !! or Here
考虑以下病态示例:
class Ideone {
static class ArrayList<T> {
ArrayList() {
System.out.println("!!");
}
}
static class java {
static class util {
static class ArrayList<T> {
ArrayList() {
System.out.println("Here");
}
}
}
}
public static void main(String[] args) {
new ArrayList<>();
new java.util.ArrayList<>();
// Can I refer to the "usual" java.util.ArrayList?
}
}
构造函数中创建的两个实例是嵌套的classes.
但是我怎么能在同一个 class 中提到我们都知道和喜爱的 java.util.ArrayList
?我们不能导入它,也不能使用完全限定名称,因为会使用嵌套的 class 符号。
在这种情况下我们能做什么? (除了明显的 - 停止为嵌套的 classes 使用这种肆意邪恶的名称)。
你试过了吗
Class cls = ClassLoader.getSystemClassLoader().loadClass("java.util.ArrayList");
List arrayList = cls.newInstance();
很久没考虑类加载器了,不过IIRC.loadClass()
会优先尝试从最基础的类加载器加载,真正的java.util
包应该由bootstrap 类加载器,其优先级高于您在应用程序中定义的任何内容。
我要冒昧地说,不可能从 Ideone
内部引用它。我看到的唯一解决方案是创建另一个 class Idetwo
(它是 Ideone
的 nestmate(即它驻留在同一个文件中))和 return a java.util.ArrayList
从那里用于 Ideone
:
import java.util.ArrayList;
class Ideone {
...
}
class Idetwo {
static ArrayList<Integer> getList() {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
return list;
}
}
您只需将 Ideone
的主要方法更改为类似以下内容:
public static void main(String[] args) throws Exception {
new Ideone.ArrayList<>();
new Ideone.java.util.ArrayList<>();
Idetwo.getList().forEach(System.out::println);
}
输出:
!!
Here
1
2
3
注意:使用这种方法,导入java.util.ArrayList
就可以了。但是,如果您要在 Ideone
的主要方法中调用 List<Integer> list = Idetwo.getList();
,则需要导入 java.util.*
,因为单个导入将不起作用(有趣的是)。
这就是为什么包以小写字母开头,类型以大写字母开头的原因,因为 very first edition of the official code conventions for java。我认为我从未见过 java 代码违反此约定。
但是您可以使用它的完全限定名称从外部引用内部类型:
com.whatever.bad.project.SomeClass.java.util.ArrayList
当您必须从内部引用外部类型时,您可以更改该源文件以符合 Java 命名准则。
如果您已完成以下两件事,您将无法再直接引用 java.util.ArrayList
:
- 在作用域中用静态嵌套 class 隐藏简单名称
ArrayList
。 - 隐藏完全限定名称
java.util.ArrayList
与 classArrayList
嵌套在 classutil
中,嵌套在嵌套 classjava
.
您甚至无法 "split" 尝试使用 "partially qualified" 导入。
import java.*;
...
// This doesn't work!
new util.ArrayList<>();
你可以import java.*;
,但那是没有价值的;没有 class 直接在 java
包中定义。
但是,您可以间接引用 class java.util.ArrayList
,因为它不是 final
。在 class Ideone
的范围之外,声明一个具有不同名称的子class。
class AnArrayList<T> extends java.util.ArrayList<T> {}
那你可以参考那个class编程到接口:
List<Integer> al = new AnArrayList<>(); // won't print !! or Here