我有一个非常难以解决的名称隐藏问题。这是解释问题的简化版本:
有一个类:org.A
package org;
public class A{
public class X{...}
...
protected int net;
}
然后有一个类net.foo.X
package net.foo;
public class X{
public static void doSomething();
}
现在,这是继承自 A
并想调用 net.foo.X.doSomething()
package com.bar;
class B extends A {
public void doSomething(){
net.foo.X.doSomething(); // doesn't work; package net is hidden by inherited field
X.doSomething(); // doesn't work; type net.foo.X is hidden by inherited X
}
}
如您所见,这是不可能的。我不能使用简单的名称 X
因为它被继承的类型隐藏。我不能使用完全限定名称 net.foo.X
,因为 net
被继承的字段隐藏。
只有类 B
在我的代码库中; net.foo.X
和 org.A
类是库类,所以我无法更改它们!
我唯一的解决方案如下所示:
我可以调用另一个类,然后调用 X.doSomething()
;但是这个类只会因为名字冲突而存在,看起来很乱!有没有我可以直接从 B.doSomething()
调用 X.doSomething()
的解决方案?
在允许指定全局命名空间的语言中,例如,C# 中的 global::
或 C++ 中的 ::
,我可以简单地为 net
带有这个全局前缀,但 Java 不允许这样做。
最佳答案
您可以将 null
强制转换为该类型,然后对其调用方法(这将起作用,因为目标对象不参与静态方法的调用)。
((net.foo.X) null).doSomething();
这有以下好处
- 没有副作用(实例化
net.foo.X
的问题), - 不需要重命名任何东西(因此您可以为
B
中的方法指定您想要的名称;这就是为什么import static
在您的确切的情况), - 不需要引入委托(delegate)类(尽管这可能是个好主意……),并且
- 不需要使用反射 API 的开销或复杂性。
缺点是这段代码真的很糟糕!对我来说,它会产生警告,总的来说这是一件好事。但由于它正在解决一个完全不切实际的问题,因此添加一个
@SuppressWarnings("static-access")
在适当的(最小的!)封闭点将关闭编译器。
关于Java 名称隐藏 : The Hard Way,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24572214/