类的高级特性与异常处理
I. Java类包
类名冲突:
任何类与接口都需要隶属于某一个类包。可以通过将两个同名类定义在不同的类包中解决类名冲突的问题。
类的路径:
- 同一个类包中的类相互访问时,可以不指定包名;
- 同一个包中的类不必存放在同一个位置,只要将CLASSPATH分别指向这两个位置即可。
指定包与导入包:
将
package
表达式作为文件中的第一行非注释代码,java包名必须全部使用小写字母。1
package 包名;
导入包:
1
2
3import 包名.*
import 包名.类名
import 包名.静态方法名tips:
使用
import
关键字指定一个包中的所有类时,并不会指定这个包的子包中的类,如需使用需要对子包作单独引用。
II. final 关键字
- 变量:
- 修饰常量变量;
- 对象引用被
final
修饰后无法使其指向另一个对象; - Java中定义全局变量,通常使用
public static final
修饰,是能在定义时被赋值。
- 方法:
- 被
final
修饰的方法不能被重写; private
方法隐式被指定为final
类型。
- 被
- 类:
- 被修饰的类不能被继承。
III. 内部类
成员内部类
基础用法:
成员内部类的定义:(非内部类不能被声明为private或protected访问类型)
1
2
3
4
5public class OuterClass { // 外部类
private class InnerClass { // 内部类
//...
}
}内部类中可以访问外部类的所有成员变量和方法,外部类只能通过实例化内部类对象访问内部类成员(受权限修饰关键字限制);
内部类中的变量与外部类变量同名时,可以使用
this
指针加以区分:1
2
3
4// 若内部类与外部类中均有变量x
this.x; // 内部类的x
OuterClass.this.x; // 外部类的x
x; // 同名局部变量、形参(若有)在外部类和非静态方法之外实例化内部类对象,需要使用外部类:
1
2OuterClass out = = new OuterClass();
OuterClass.innerClass in = out.new innerClass();内部类对象会依赖于外部类对象。只有存在外部类对象,才能实例化内部类对象。
内部类向上转型为接口;
- 将一个权限修饰符为
private
的内部类向上转型为一个接口,就可以完全隐藏内部类的具体实现过程; - 对于一个外部接口中的方法,可以通过在一个类中定义多个内部类,每个内部类分别实现该方法的方式,实现在类中多次实现接口中的同一个方法;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22interface OutInterface {
public void f();
}
class OuterClass {
// 定义一个外部不可访问的内部类
private class InnerClass implements OutInterface {
// 实现接口方法
public void f() {
// do something...
}
}
public OutInterface doit {
return new InnerClass(); // 将内部类向上转型为外部接口
}
}
...
OuterClass out = new OuterClass();
OutInterface outinter = out.doit();
outinter.f();
...外部不可直接访问内部类中的 f() 方法但是可以访问接口中的,通过将内部类向上转型执行内部类中定义的方法,对继承外部类的子类隐藏了实现细节。(向外提供外部类和接口)
- 将一个权限修饰符为
局部内部类
内部类可以在类的局部位置定义(如方法)
在方法中定义的内部类只能使用方法中被
final
修饰的变量。因为内部类对象的生存期超出方法运行的生存期,导致方法中的一般局部变量比内部类对象的生存期短,而被final型变量被视为常量,其生存期同样比方法运行的生存期长。
匿名内部类
1 | return new A() { |
匿名内部类编译以后,产生以“外部类名$序号”为名称的.class文件,序号以1~n排列。
静态内部类
- 创建静态内部类的对象不需要其外部类的对象;
- 静态内部类的对象中不能访问非静态外部类的对象。
内部类的继承
1 | public class OutputInnerClass extends ClassA.ClassB { |
IV. 异常捕捉
try-catch
语句:1
2
3
4
5
6try {
// 可以发生异常的代码块
}
catch(Exception e){
// 异常处理
}finally
语句:无论
try
中的语句是否发生异常,都会执行finally
中的代码块。finally
不被执行的情况:finally
中发生异常;- 之前的代码中使用
System.exit()
退出程序; - 程序所在的线程死亡;
- 关闭CPU。
tips:
Exception
是try
代码传递给catch
代码块的变量类型;- 异常处理常用的函数:
getMessage()
:输出错误性质;toString()
:给出异常的类型与性质;printStackTrace()
:指出异常的类型、性质、栈层次及出现在程序中的位置。
V. Java常见异常
异常类 | 说明 |
---|---|
ClassCastException | 类型转换异常 |
ClassNotFoundException | 未找到相应类异常 |
ArithmeticException | 算术异常 |
ArrayIndexOutOfBoundsException | 数组下标越界异常 |
ArrayStoreException | 数组中包含不兼容的值抛出的异常 |
SQLException | 操作数据库异常 |
NullPointerException | 空指针异常 |
NoSuchFieldException | 字段未找到异常 |
NoSuchMethodException | 方法未找到异常 |
NumberFormatException | 字符串转换为数字抛出的异常 |
NegativeArraySizeException | 数组元素个数为负数抛出的异常 |
StringIndexOutOfBoundsException | 字符串索引超出范围抛出的异常 |
IOException | 输入输出异常 |
IllegalAccessException | 不允许访问某类异常 |
InstantiationException | 当应用程序试图使用 Class 类中的 new Instance() 方法创建一个类的实例,而指定的类的对象无法被实例化时,抛出该异常 |
EOFException | 文件已结束异常 |
FileNotFoundException | 文件未找到异常 |
VI. 自定义异常
1 | public class MyException extends Exception { |
VII. 抛出异常
throws:用于指定方法可能抛出的异常,用于将异常向上抛出。
1
2static void pop() throws 异常1, 异常2, ... {
}throw:
- 程序在执行到
throw
语句时立即终止,其后语句都不执行; throw
抛出的异常必须使用try-catch
语句快捕捉;- 若想向上级抛出异常,必须在抛出异常的方法中使用
throws
。
- 程序在执行到
参考资料《Java从入门到精通(第5版)》