第 9章
管理类别档案
– 内部类别
– package与 import
成员内部类别、区域内部类别
成员内部类别,基本上是在一个类别中直接宣告另一个类别
所产生的文件名为「外部类别名称 $内部类别名称,class」
public class OuterClass {
//内部类别
private class InnerClass {
//,...
}
}
成员内部类别、区域内部类别
区域内部类别定义于一个方法中,类别的可视范围与生成之对象仅止于该方法之中
内部类别还可以被宣告为 "static“
由于是? static”,它不能存取外部类别的方法,而必须透过外部类别所生成的对象来进行呼叫成员内部类别、区域内部类别
被宣告为 static的内部类别,事实上也可以看作是另一种名称空间的管理方式
public class Outer {
public static class Inner {
....
}
....
}
Outer.Inner inner = new Outer.Inner();
匿名内部类别
内部匿名类别可以是继承某个类别或是实作某个接口
new[类别或接口 ()] {
//实作
}
Object obj =
new Object() {
public String toString() { //重新定义 toString()
return"匿名类别物件 ";
}
};
System.out.println(obj);
匿名内部类别
注意如果要在内部匿名类别中使用外部的局部变量,变量在宣告时必须 為 "final"
....
public void someMethod() {
finalint x = 10; //宣告 final
Object obj =
new Object() {
public String toString() {
return String.valueOf(x); //x可在匿名类别中使用
}
};
System.out.println(obj);
}
....
匿名内部类别
局部变量 x并不是真正被拿来于内部匿名类别中使用
x会被匿名类别复制作为数据成员来使用
编译程序会要求您加上? final”关键词,这样您就知道不能在内部匿名类别中改变 x的值
内部匿名类别在编译完成之后会产生「外部类别名称 $编号,class」,编号为 1,2、
3...n,每个编号 n的档案对应于第 n个匿名类别设定包( package)
包被设计与文件系统结构相对应
为了要能建立与包相对应的文件系统结构,
您在编译时可以加入 "-d"参数,并指定产生的类别档案要储存在哪一个目录之下
package onlyfun.caterpillar;
public class PackageDemo {
public static void main(String[] args) {
System.out.println("Hello! World!");
}
}
设定包( package)
javac -d,UsePackage.java
在目前的工作位置中会出现 onlyfun目录,
之下会有个 caterpillar目录,而当中有 個
PackageDemo.class档案
package”的设定会成为类别名称的一部份
– 完整类别名 onlyfun.caterpillar.PackageDemo
– java onlyfun.caterpillar.PackageDemo
设定包( package)
「完全描述」( Fullyqualified)名称
– 完整的指出「包加类别」名称
最后编译完成的,class档案必须放在 onlyfun
目录的 caterpillar目录下
onlyfun.caterpillar.Point2D p1 = new
onlyfun.caterpillar.Point2D(10,20);
bad class file,.\Point2D.classclass file contains
wrong class,onlyfun.caterpillar.Point2DPlease remove
or make sure it appears in the correct subdirectory of
the classpath.
Point2D p1 = new Point2D(10,20);
^1 error
import的意义
您可以使用 "import"关键词,告知编译程序您所要使用的类别是位于哪一个包
import onlyfun.caterpillar.Point2D;
public class Point2DDemo2 {
public static void main(String[] args) {
Point2D p1 = new Point2D(10,20);
System.out.printf("p1,(x,y) = (%d,%d)%n",
p1.getX(),p1.getY());
}
}
import的意义
使用 "import"指定时,可于包指定 加上 '*'
import onlyfun.caterpillar.*;
public class Point2DDemo3 {
public static void main(String[] args) {
Point2D p1 = new Point2D(10,20);
System.out.printf("p1,(x,y) = (%d,%d)%n",
p1.getX(),p1.getY());
}
}
import的意义
可能出现以下的错误讯息
将原始码与编译完成的档案放在一起并不是一个好的管理方式
指定 Classpath的方式如下执行程序
bad class file,.\Point2D.java
file does not contain class Point2D
Please remove or make sure it appears in the correct
subdirectory of the classpath.
javac -d,/classes,/src/*.java
java -cp,/classes Point2DDemo3
import的意义
同名冲突
import java.util.Arrays;
import onlyfun.caterpillar.Arrays;
public class SomeClass {
....
}
java.util.Arrays is already defined in a single-type import
import onlyfun.caterpillar.Arrays;
^1 error
public与包
没有被宣告为? public”的类别只能被同一个包中的类别之实例呼叫使用
类别成员也可以宣告为 "public",宣告为 "public"
的类别成员可以被其它对象呼叫使用
如果宣告类别时不使用 "public","protected"或
"private"设定权限,则预设为「包存取范围」
Point2DDemo.java:3,onlyfun.caterpillar.Point2D is not
public in onlyfun.caterpillar; cannot be accessed from
outside package
onlyfun.caterpillar.Point2D p1 = new
public与包
Point2DDemo.java:7,getX() is not public in
onlyfun.caterpillar.Point2D; cannot be accessed from
outside package
p1.getX(),p1.getY());
^
public与包
类别上的权限设定会约束类别成员上的权限设定
效果等同于
package onlyfun.caterpillar;
class SomeClass {
//,..
public void someMethod() {
//,...
}
}
package onlyfun.caterpillar;
class SomeClass {
//,..
void someMethod() {
//,...
}
}
public与包
定义一个类别,但没有定义建构方法时,
编译程序会自动帮您产生一个预设建构方法package onlyfun.caterpillar;public class Test {
....
}
package onlyfun.caterpillar;
public class Test {
public Test() {
}
....
}
public与包
如果您自行定义建构方法,则编译程序就不会帮您加上预设建构方法
在建构时,就必须指明使用哪个建构方法
package onlyfun.caterpillar;
public class Test {
public Test(int i) {
...
}
....
}
public与包
建议即使没有用到,在定义自己的建构方法的同时,也加上个没有参数的建构方法
没有使用 super()指定要使用父类别的哪个建构方法,则预设会寻找父类别中无参数的建构方法
package onlyfun.caterpillar;
public class Test {
public Test() { //即使没用到,也先建立一个空的建构方法
}
public Test(int i) {
...
}
....
}
public与包
预设建构方法的访问权限是跟随着类别的访问权限而设定
由于类别宣告为 public,所以预设建构方法访问权限 為 public
package onlyfun.caterpillar;
public class Test {}
public与包
如果是以下的话
则预设建构方法访问权限为包访问权限,
也就是编译程序会自动为您扩展为
package onlyfun.caterpillar;
class Test {}
package onlyfun.caterpillar;
class Test {
Test() { }
}
public与包存取修饰 同一类别 同一包 子类别 全局
private OK
(default) OK OK
protected OK OK OK
public OK OK OK OK
import静态成员
import static java.lang.System.out;
public class HelloWorld {
public static void main(String[] args) {
out.println("Hello! World!");
}
}
import static java.lang.System.out;
import static java.util.Arrays.sort;
public class ImportStaticDemo {
public static void main(String[] args) {
int[] array = {2,5,3,1,7,6,8};
sort(array);
for(int i,array) {
out.print(i + " ");
}
}
}
import静态成员
如果您想要? import”类别下所有的静态成员,也可以使用 ‘ *’ 字符
对于名称冲突编译程序可能透过以下的几个方法来解决
– 成员覆盖
– 局部变量覆盖
– 重载( Overload)方法上的比对
import static java.util.Arrays.*;