首页 > 代码库 > 10. 内部类、源文件规则和包

10. 内部类、源文件规则和包

 

<style>html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { margin: 0; padding: 0; border: 0 } body { font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 1.6; color: #333; background-color: #fff; padding: 20px; max-width: 960px; margin: 0 auto } body>*:first-child { margin-top: 0 !important } body>*:last-child { margin-bottom: 0 !important } p,blockquote,ul,ol,dl,table,pre { margin: 15px 0 } h1,h2,h3,h4,h5,h6 { margin: 20px 0 10px; padding: 0; font-weight: bold } h1 tt,h1 code,h2 tt,h2 code,h3 tt,h3 code,h4 tt,h4 code,h5 tt,h5 code,h6 tt,h6 code { font-size: inherit } h1 { font-size: 28px; color: #000 } h2 { font-size: 24px; border-bottom: 1px solid #ccc; color: #000 } h3 { font-size: 18px } h4 { font-size: 16px } h5 { font-size: 14px } h6 { color: #777; font-size: 14px } body>h2:first-child,body>h1:first-child,body>h1:first-child+h2,body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child { margin-top: 0; padding-top: 0 } a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6 { margin-top: 0; padding-top: 0 } h1+p,h2+p,h3+p,h4+p,h5+p,h6+p { margin-top: 10px } a { color: #4183C4; text-decoration: none } a:hover { text-decoration: underline } ul,ol { padding-left: 30px } ul li>:first-child,ol li>:first-child,ul li ul:first-of-type,ol li ol:first-of-type,ul li ol:first-of-type,ol li ul:first-of-type { margin-top: 0px } ul ul,ul ol,ol ol,ol ul { margin-bottom: 0 } dl { padding: 0 } dl dt { font-size: 14px; font-weight: bold; font-style: italic; padding: 0; margin: 15px 0 5px } dl dt:first-child { padding: 0 } dl dt>:first-child { margin-top: 0px } dl dt>:last-child { margin-bottom: 0px } dl dd { margin: 0 0 15px; padding: 0 15px } dl dd>:first-child { margin-top: 0px } dl dd>:last-child { margin-bottom: 0px } pre,code,tt { font-size: 12px; font-family: Consolas, "Liberation Mono", Courier, monospace } code,tt { margin: 0 0px; padding: 0px 0px; white-space: nowrap; border: 1px solid #eaeaea; background-color: #f8f8f8 } pre>code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent } pre { background-color: #f8f8f8; border: 1px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px } pre code,pre tt { background-color: transparent; border: none } kbd { background-color: #DDDDDD; background-image: linear-gradient(#F1F1F1, #DDDDDD); background-repeat: repeat-x; border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD; border-style: solid; border-width: 1px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 10px; padding: 1px 4px } blockquote { border-left: 4px solid #DDD; padding: 0 15px; color: #777 } blockquote>:first-child { margin-top: 0px } blockquote>:last-child { margin-bottom: 0px } hr { clear: both; margin: 15px 0; height: 0px; overflow: hidden; border: none; background: transparent; border-bottom: 4px solid #ddd; padding: 0 } table th { font-weight: bold } table th,table td { border: 1px solid #ccc; padding: 6px 13px } table tr { border-top: 1px solid #ccc; background-color: #fff } table tr:nth-child(2n) { background-color: #f8f8f8 } img { max-width: 100% }</style>

1. 内部类

阅读什么是java内部类和Java中为什么要使用内部类

内部类的两个作用:

  1. 一般类,是不允许访问另一个类的 private 权限的,但内部类可以。
  2. 可实现多重继承。

    静态内部类可以直接创建对象new B.C();
    如果内部类不是静态的,那就得这样
    B b = new B();  
    B.C c = b.new C();
    

2. 源文件规则

  • 一个源文件中只能有一个public类
  • 一个源文件可以有多个非public类
  • 源文件的名称应该和public类的类名保持一致。

    例如:源文件中public类的类名是Employee,那么源文件应该命名为Employee.java。

  • 如果一个类定义在某个包中,那么package语句应该在源文件的首行。
  • 如果源文件包含import语句,那么应该放在package语句和类定义之间。
  • 如果没有package语句,那么import语句应该在源文件中最前面。
  • import语句和package语句对源文件中定义的所有类都有效。
  • 在同一源文件中,不能给不同的类不同的包声明。
  • 类有若干种访问级别,并且类也分不同的类型:抽象类和final类等。这些将在访问控制章节介绍。
  • 除了上面提到的几种类型,Java还有一些特殊的类,如:内部类、匿名类。

3. 包Package

为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。

3.1 包的作用

  1. 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
  2. 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
  3. 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。

包语句的语法格式为:

package pkg1[.pkg2[.pkg3…]];

例如,一个Something.java 文件它的内容

package net.java.util
public class Something{
   ...
}

那么它的路径应该是 net/java/util/Something.java 这样保存的。 package(包) 的作用是把不同的 java 程序分类保存,更方便的被其他 java 程序调用。

一个包(package)可以定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。

以下是一些 Java 中的包:

java.lang-打包基础的类
java.io-包含输入输出功能的函数

开发者可以自己把一组类和接口等打包,并定义自己的包。而且在实际开发中这样做是值得提倡的,当你自己完成类的实现之后,将相关的类分组,可以让其他的编程者更容易地确定哪些类、接口、枚举和注释等是相关的。

由于包创建了新的命名空间(namespace),所以不会跟其他包中的任何名字产生命名冲突。使用包这种机制,更容易实现访问控制,并且让定位相关类更加简单。

3.2 创建包

创建包的时候,你需要为这个包取一个合适的名字。之后,如果其他的一个源文件包含了这个包提供的类、接口、枚举或者注释类型的时候,都必须将这个包的声明放在这个源文件的开头。

包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它。

如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中。

3.3 import关键字

为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。使用 "import" 语句可完成此功能。

在 java 源文件中 import 语句应位于 package 语句之后,所有类的定义之前,可以没有,也可以有多条,其语法格式为:

import package1[.package2…].(classname|*);

如果在一个包中,一个类想要使用本包中的另一个类,那么该包名可以省略。

例子: 下面的 payroll 包已经包含了 Employee 类,接下来向 payroll 包中添加一个 Boss 类。Boss 类引用 Employee 类的时候可以不用使用 payroll 前缀,Boss类的实例如下。

package payroll;

public class Boss
{
   public void payEmployee(Employee e)
   {
      e.mailCheck();
   }
}

如果 Boss 类不在 payroll 包中又会怎样?Boss 类必须使用下面几种方法之一来引用其他包中的类。

  1. 使用类全名描述,例如:payroll.Employee
  2. 用 import 关键字引入,使用通配符 "*",例如: import payroll.*;
  3. 使用 import 关键字引入 Employee 类:import payroll.Employee;

注意: 类文件中可以包含任意数量的 import 声明。import 声明必须在包声明之后,类声明之前。

3.4 package的目录结构

类放在包中会有两种主要的结果:

  • 包名成为类名的一部分,正如我们前面讨论的一样。
  • 包名必须与相应的字节码所在的目录结构相吻合。

下面是管理你自己 java 中文件的一种简单方式:

  • 将类、接口等类型的源码放在一个文本中,这个文件的名字就是这个类型的名字,并以.java作为扩展名。例如:

    // 文件名 :  Car.java
    
    package vehicle;
    
    public class Car {
       // 类实现  
    }
    
  • 接下来,把源文件放在一个目录中,这个目录要对应类所在包的名字。

    ....\vehicle\Car.java
    
  • 现在,正确的类名和路径将会是如下样子:

    类名 -> vehicle.Car
    路径名 -> vehicle\Car.java (在 windows 系统中)
    

通常,一个公司使用它互联网域名的颠倒形式来作为它的包名.例如:互联网域名是 rimi.com,所有的包名都以 com.rimi 开头。包名中的每一个部分对应一个子目录。

例如:有一个 com.rimi.test 的包,这个包包含一个叫做 JavaBasic.java 的源文件,那么相应的,应该有如下面的一连串子目录:

....\com\rimi\test\JavaBasic.java

编译的时候,编译器为包中定义的每个类、接口等类型各创建一个不同的输出文件,输出文件的名字就是这个类型的名字,并加上 .class 作为扩展后缀。 例如:

// 文件名: JavaBasic.java

package com.rimi.test;
public class JavaBasic {

}
class Google {

}

现在,我们用-d选项来编译这个文件,如下:

$javac -d . JavaBasic.java

这样会像下面这样放置编译了的文件:

.\com\rimi\test\JavaBasic.class
.\com\rimi\test\Google.class

你可以像下面这样来导入所有 \com\rimi\test\ 中定义的类、接口等:

import com.runoob.test.*;

编译之后的 .class 文件应该和 .java 源文件一样,它们放置的目录应该跟包的名字对应起来。但是,并不要求 .class 文件的路径跟相应的 .java 的路径一样。你可以分开来安排源码和类的目录。

<path-one>\sources\com\rimi\test\JavaBasic.java
<path-two>\classes\com\rimi\test\Google.class

这样,你可以将你的类目录分享给其他的编程人员,而不用透露自己的源码。用这种方法管理源码和类文件可以让编译器和java 虚拟机(JVM)可以找到你程序中使用的所有类型。

类目录的绝对路径叫做 class path。设置在系统变量 CLASSPATH 中。编译器和 java 虚拟机通过将 package 名字加到 class path 后来构造 .class 文件的路径。

<path- two>\classes 是 class path,package 名字是 com.rimi.test,而编译器和 JVM 会在 <path-two>\classes\com\rimi\test 中找 .class 文件。

一个 class path 可能会包含好几个路径,多路径应该用分隔符分开。默认情况下,编译器和 JVM 查找当前目录。JAR 文件按包含 Java 平台相关的类,所以他们的目录默认放在了 class path 中。

3.5 设置CLASSPATH系统变量

用下面的命令显示当前的CLASSPATH变量:

  • Windows 平台(DOS 命令行下):C:> set CLASSPATH
  • UNIX 平台(Bourne shell 下):# echo $CLASSPATH

删除当前CLASSPATH变量内容:

  • Windows 平台(DOS 命令行下):C:> set CLASSPATH=
  • UNIX 平台(Bourne shell 下):# unset CLASSPATH; export CLASSPATH

设置CLASSPATH变量:

  • Windows 平台(DOS 命令行下): C:> set CLASSPATH=C:\users\jack\java\classes
  • UNIX 平台(Bourne shell 下):# CLASSPATH=/home/jack/java/classes; export CLASSPATH

 

10. 内部类、源文件规则和包