java 包 和 物理目录 解惑
今天做 JUnit 实验, 发现在物理实际不同的目录(src, testsrc)下可以使用相同的包名, 并且在这两个目录下, 都有个子目录 coolUnit (这个子目录是配合 package 使用的) 问题:
1. 那么包名和实际物理路径有什么关系?
答: 包名必须出现在实际路径中的一部分, 只是一段, 不可能是绝对路径. 而这个段的起点, 就是包含了classpath目录的一个.
可以看到如下代码, 是eclipse 自动生成的 .classpath文件, 其中classpath就包含了testsrc, src, 而这两个目录下都有个子目录 coolUnit, 这个就是包名的开始.
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="testsrc"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>
2. 相同包名 如果可以存储在不同物理路径下, java 编译器如何找到对应的类 ?
答: 当然可以存储在不同的物理路径下, 只不过这两个路径中, 有一部分必须相同, 即包名包括的部分. 置于java编译器如何找到, 简单, 就是把从包名的起点的上层目录添加到classpath中了, 这样就可以找到对应了类了. 类似上边的testsrc, src, 这两个目录都被添加进了classpath(当然这个工作是eclipse替我们完成的, 如果是我们自己编译, 不借助eclipse, 就需要指定 javac –classpath 把这两个目录加进去)
3. 这里肯定跟classpath 有关, 不可能你随便写个java类, java 编译器都能找到, 那么如何引入自己写的类呢?
如何引用自己的类的, 就是将自己的类的包名的起点的上层目录作为 javac –classpath参数传入, 这样的目的是让java编译器找到你的类所在的位置.
综上: 包名是抽象出来的类的空间, 虽然在物理上存储需要文件夹配合层次, 但是关键, 这个层次不是绝对路径, 只是路径中的一部分, 所以, 我们完全可以将代码放在不同路径下, 只要路径中对应包名的部分相同就可以了.
包
为了更好地组织类,Java提供了包机制。包是类的容器,用于分隔类名空间。如果没有指定包名,所有的示例都属于一个默认的无名包.
Java中的包一般均包含相关的类,例如,所有关于交通工具的类都可以放到名为Transportation的包中.
包语句格式:
package pkg1[.pkg2[.pkg3…]];
程序中如果有package语句,该语句一定是源文件中的第一条可执行语句,它的前面只能有注释或空行。另外,一个文件中最多只能有一条package语句.
包的名字有层次关系,各层之间以点分隔。包层次必须与Java开发系统的文件系统结构相同(并非绝对路径)。通常包名中全部用小写字母,这与类名以大写字母开头,且各字的首字母亦大写的命名约定有所不同。
当使用包说明时,程序中无需再引用(import)同一个包或该包的任何元素。import语句只用来将其他包中的类引入当前名字空间中。而当前包总是处于当前名字空间中.
如果文件声明如下:
package java.awt.image
则此文件必须存放在Windows的java\awt\image目录下或unix的java/awt/image目录下。
问题出现了: 因为路径不可能是绝对的, 即从根目录开始一直向下, 所以目录的开始位置, 只需要是classpath包含的位置就可以了.
这才是问题解决的关键. 从这点说, 包名是抽象的.
java 包 和 物理目录 解惑的更多相关文章
- idea中的java web项目(添加jar包介绍)和java maven web项目目录结构
java web项目 web项目下web根目录名称是可以更改的 idea中新建java web项目,默认src为Sources Root,当然也可以手动改,在Sources Root下右键只能新建Pa ...
- android工程gen目录中R.java包名是怎么确定
新建一个工程,包名用的com.mythroad.adskiller, 后来觉得不好,又改成com.mythroad.adsinscepter,但是我发现gen下的R.java文件的包名还是原来的com ...
- 转:java两个jre目录和三个lib目录
lib目录下放置着jar包.程序中的import语句找的就是这些文件!例如:import javax.servlet.RequestDispatcher; 问题在于,在cmd模式下编译,系统会提 ...
- java包和jar包
1.包 package pack; /*定义包,放在程序的第一行,包名所以字母小写*/ class PackageDemo{ publi ...
- Android 虚拟机Dalvik、Android各种java包功能、Android相关文件类型、应用程序结构分析、ADB
Android虚拟机Dalvik Dalvik冲击 随着Google 的AndroidSDK 的发布,关于它的API 以及在移动电话领域所带来的预期影响这些方面的讨论不胜枚举.不过,其中的一个话题在J ...
- 在Eclipse工具里创建maven的web工程,在建立src/main/java包出现The folder is already a source folder.解决
1. 与创建普通java工程一样,点击右键找到New菜单,在弹出的界面输入maven ---->>点击maven Project------>>点击next 2 进入下一个界 ...
- JavaSE复习日记 : java包机制
这里是第一个文件,命名为JavaSE_01.java,我在这个文件里面声明了一个m1()方法,通过包机制,我将在另外一个文件夹里访问这个文件里的东西,确切的说是访问这个文件生成的一个class文件; ...
- 理解Java包
本质上,包是一个唯一命名的类的集合,将类集合到包里面的主要原因,是为了当在应用程序中使用预先编写的类时避免与类自身可能引起的明明冲突.用于包中的类名不会妨碍另一个包或程序中的类名,因为此时,包中的类名 ...
- Android数据库框架——ORMLite轻量级的对象关系映射(ORM)Java包
Android数据库框架--ORMLite轻量级的对象关系映射(ORM)Java包 事实上,我想写数据库的念头已经很久了,在之前写了一个答题系统的小项目那只是初步的带了一下数据库,数据库是比较强大的, ...
随机推荐
- Intent的用法总结(不进你会后悔的)
下面列出几种Intent的用法 下面的代码片段通过谷歌搜索 Intent intent = new Intent(); intent.setAction(Intent.ACTION_WEB_SEARC ...
- IOS8 Playground介绍
一.Playground介绍 Playground是Xcode6中自带的Swift代码开发环境.俗话说"功欲善其事,必先利其器".曾经在Xcode5中编写脚本代码,比如编写JS,其 ...
- ScriptableObject 对象化的运用
http://www.cnblogs.com/oldman/articles/2409554.html using UnityEngine; using UnityEditor; using Syst ...
- Vagrant up Warning: Authentication failure. Retrying...
Vagrant up Warning: Authentication failure. Retrying... Vagrant up Warning: Authentication failure. ...
- mybatis常用标签
1. 定义sql语句 1.1 select 标签 属性介绍: id :唯一的标识符. parameterType:传给此语句的参数的全路径名或别名 例:com.test.poso.User或user ...
- c#:无法将 NULL 转换成“System.DateTime”,因为它是一种值类型(转)
摘自:http://www.blogjava.net/parable-myth/archive/2010/09/30/333454.html 在C# 2.0里面的数据类型中,分为值类型和引用类型,引用 ...
- PHP权限控制(转)
PHP: 我这里说到的权限管理办法是一个普遍采用的方法,主要是使用到"位运行符"操作,& 位与运算符.| 位或运行符.参与运算的如果是10进制数,则会被转换至2进制数参与运 ...
- TCP的发送缓冲区和接收缓冲区
TCP协议是作用是用来进行端对端数据传送的,那么就会有发送端和接收端,在操作系统有两个空间即user space和kernal space. 每个Tcp socket连接在内核中都有一个发送缓冲区和接 ...
- Timer Schedule参数说明
Timer是一种定时器工具,用来在一个后台线程计划执行指定任务.它可以计划执行一个任务一次或反复多次. TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务. schedule的意 ...
- Node Redis 小试
Redis 是一个高性能的 key-value 数据库,为了保证效率,数据都是缓存在内存中,在执行频繁而又复杂的数据库查询条件时,可以使用 Redis 缓存一份查询结果,以提升应用性能. 背景 如果一 ...