有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中的名称空间包相对标识符路径

导言

从C++中移出的一个最大区别是范围的差异:在C++中,每个标识符都与当前的范围(^ {< CD1>}或^ {CD2>})相对应,并且可以在开始时用范围解析操作符{{CD3}}编写绝对路径。p>

然而,在Java中,如果不将标识符导入当前作用域或写入其完整路径,我无法找到从其他包访问标识符的方法

如果我有几个同名的类,那么在C++中,我会把它们定义为模块1::FoO和Meule2::FoO,这是不可能的,只要我想保存我的心智,因为^ {CD4}}太长,我的口味太长了。< /p>

密码

这里是一个例子,用于访问来自java和C++的类^ {CD5>}(没有^ {CD6>}或^ {< CD7>})

Tools/Useless/Foo.hpp

namespace Tools {
namespace Useless {
class Foo {         
};
}
}

Tools/Bar.hpp

namespace Tools {
...
// Use Foo with a relative identifier
Useless::Foo foo;
// Use Foo with an absolute identifier.
::Tools::Useless::Foo bar;
...
} 

这就是它在Java中的外观:

com/company/project/Tools/Useless/Foo.java

package com.company.project.Tools.Useless;

public class Foo { }

com/company/project/Tools/Bar.java

...
// Use Foo with a relative identifier
???
// Use Foo with an absolute identifier.
com.company.project.Tools.Useless.Foo foo;
...

问题

  1. 有没有一种方法可以从包Tools.Useless访问Foo而不指定Tools.Useless完整的包名(并导入它;因为导入它会将它绑定到当前范围)
  2. 我做得对吗?我应该如何使用几个同名的类?我应该避免这样做,还是直接用“package.*”导入它们来绕过它

解决方案

  1. 使用更多的包描述性类名(例如ToolsUselessFoo,而不仅仅是Foo
  2. import path.to.module.*而不是import path.to.module.Foo导入所有内容,然后访问Foo所需的包以解决任何歧义。问题是,有时包名有一个含义(例如Tools.Useless.FooTools.Useful.Foo

共 (1) 个答案

  1. # 1 楼答案

    Java包不是嵌套的。虽然它们的名字可能有共同的前缀,但这在Java编程语言中没有任何意义

    此外,当存储是文件系统时,它们的类文件存储在嵌套目录中,这一事实没有其他意义。当类存储在jar文件中时,它们的条目名与它们的限定名匹配,而实际上根本不形成目录(尽管许多工具喜欢将它们呈现为一个层次结构,以模拟文件系统)

    所以包com.company.project.tools.uselesscom.company.project.tools根本没有关系。虽然我们人类倾向于以这样的方式组织代码,这里可以假设语义关系(这是一件好事),但在技术层面上没有。与其他两个包相比,它们之间没有相对寻址,也没有额外的访问权限。事实上,这两个包可能是两个不同模块(从Java 9开始)的一部分,与其他两个名称不太相似的包相比,访问权限更少

    使用另一个包中的类的标准方法是使用import com.company.project.Tools.Useless.Foo;,然后在类中使用Foo

    目前还不清楚,您看到的问题是什么,即“因为导入它会将其绑定到当前范围”应该是什么意思。仅仅存在import语句对代码没有影响。它告诉编译器的只是,如果范围内没有其他Foo,如何解析简单名称Foo的出现

    换句话说,局部作用域仍然具有优先权,甚至包括继承的成员。此外,在变量和类型可能出现的地方,变量具有优先权。例如,对于Foo.bar()的出现,一个名为Foo的变量将具有优先级,一个局部变量优先于同一类型内的成员变量,一个外部类或继承类。否则,将使用成员类型、外部类型或继承的成员类型。只有当它们都不存在时,import语句才会用于解析Foo

    不用说,您应该避免使用太多相同简单名称的项目,这样您就必须考虑解决过程的细节。这就是为什么命名约定建议变量名以小写字母开头,类名以大写字母开头

    是的,避免给类起相同的简单名称。一旦必须在同一个编译单元中处理这两个类,就无法在整个编译单元中访问其中一个具有其(完整的)限定名的类。(在导入中使用*对这种情况没有任何帮助)


    如前所述,“完全”一词在Java中已经过时,因为限定名总是完整的