【黑马程序员】面向对象(五) 第九天

2023-10-31

-------  android培训java培训java学习型技术博客、期待与您交流! ----------

知识点

异常处理能够使一个方法给它的调用者抛出一个异常。
异常发生在一个方法的执行过程中。RuntimeException和Error都是免检异常,其它所有异常都是必检的。
当声明一个方法时,如果这个方法可能抛出一个必检异常,则必须声明为必检异常,告诉编译器可能会出现什么错误。
声明异常的关键字是throws,而抛出异常的关键字是throw
如果调用了必检异常的方法,必须将该方法调用放在try语句中。在方法不断重复直到异常被捕获或者传递给Main方法。
可以从一个通用的父类派生出各种不同的异常类。如果一个catch块捕获到父类的异常对象,它也能捕获这个父类的子类的所有异常对象。
在catch块中,异常被指定顺序是非常重要的。如果在一个类的父类的异常对象之前没有指定这个类的一个异常对象,就会导致一个编译错误。
当方法发生异常时,如果异常没有被捕获,方法将会立即退出。如果方法想在退出前执行一些任务,可以在方法中捕获这个异常,然后再重新抛给真正的处理器。
任何情况下都会执行finally块中的代码,不管try块中是否出现或者捕获了异常。
异常处理将错误处理代码从正常的程序设计任务中分离出来,这样,就会使程序更易于阅读和修改。
不应该使用异常处理代替简单的测试。  应该尽可能地测试简单异常,将异常处理保留为处理那些无法用if语句处理的异常。

01)内部类访问规则(一)

1:内部类可以直接访问外部类中的成员,包括私有。
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
2:外部类要访问内部类,必须要建立内部类对象。
public class InnerClassDemo {
	public static void main(String[] args) {
		//直接访问内部类中的成员。
		Outer.Inner in = new Outer().new Inner();
		in.function();
		System.out.println("------------");
		Outer o = new Outer();
		o.method();
	}
}
class Outer{
	private int x = 3;
	void method(){
		Inner in = new Inner();//创建内部类Inner对象。
		in.function();
	}
	
	class Inner{//内部类
		void function(){
			System.out.println("Innner: " + x);
		}
	}
}
运行结果如下图所示:

02)静态内部类

public class InnerClassDemo_2 {
	public static void main(String[] args) {
		new Outer_1.Inner().function_1();//直接访问static内部类中的非静态成员。
		System.out.println("-------------");
		Outer_1.Inner_2.function_2();//直接访问static内部类中的静态成员。
	}
}
class Outer_1{
	private static int x = 3;
	static class Inner{//静态内部类
		void function_1() {
			System.out.println("Inner: " + x);
		}
	}
	static class Inner_2{//静态内部类
		static void function_2() {
			System.out.println("Inner: " + x);
		}
	}
}
运行结果如下图所示:

03)内部类定义原则

当描述事物时,事物内部还有事物,该事物用内部类来描述。
因为该事物需要使用外部事物的内容。

04)匿名内部类

05)异常概述

/*
 * 异常:就是程序在运行时出现不正常情况。
 * 异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。
 * 			其实就是java对不正常情况进行描述后的对象体现。
 * 对于问题的划分:两种:一种是严重的问题,一种是非严重的问题。
 * 对于严重的,java通过Error类进行描述。对于非严重的,java通过Exception类进行描述。
 */
public class ExceptionDemo {
	public static void main(String[] args) {
		Demo d = new Demo();
		int a = d.div(10, 3);
		System.out.println("A: " + a);
//		int b = d.div(10, 0);//除数不能为0。
//		System.out.println("B: " + b);//异常:ArithmeticException
	}
}
class Demo{
	int div(int a, int b){
		return a / b;
	}
}

06)try-catch

一:异常的处理:Java提供了特有的语句进行处理。
try{
需要被检测的代码。
}catch(异常类 变量){
处理异常的代码。(处理方式)
}finally{
一定会执行的语句。
}
二:对捕获的异常对象进行常见方法操作。
String getMessage() :获取异常信息
String toString():获取异常名称和异常信息。
String printStackTrace():获取异常名称、异常信息和异常出现的位置。
public class ExceptionDemo_2 {
	public static void main(String[] args) {
		Demo_2 d = new Demo_2();
		try{
			int a = d.div(10, 3);
			System.out.println("A: " + a);
			int b = d.div(a, 0);//异常:ArithmeticException
			System.out.println("B: " + b);
		}catch(Exception e){//Exception e = new ArithmeticException();//多态。
			System.out.println("除数不能为O");
			System.out.println(e.getMessage());//打印异常信息
			System.out.println(e.toString());//打印异常名称+异常信息。
			e.printStackTrace();//打印异常名称+异常信息+异常出现的位置。
								//这是JVM默认的异常处理机制。
		}
	}
}
class Demo_2{
	int div(int a, int b){
		return a / b;
	}
}
运行结果如下图所示:

07)异常声明(throws)

public class ExceptionDemo_3 {
	public static void main(String[] args){
		Demo_3 d = new Demo_3();
		try{
			int a = d.div(100, 10);
			System.out.println("A: " + a);
			int b = d.div(a, 0);//出现异常后,下面一行语句将不执行。
			System.out.println("B: " + b);
		}catch (Exception e){
			System.out.println(e.toString());
		}
		
	}
}
class Demo_3{
	int div(int a, int b) throws Exception{//在功能上通过throws的关键字声明了该功能有可能会出现问题。
		return a / b;
	}
}
运行结果如下图所示:

08)多异常处理

1:声明异常时,建议声明更为具体的异常。这样处理的可以更具体。
2:对方声明几个异常,就应该有几个catch块。不要定义多余的catch块。
如果多个catch块中的异常出现继承关系,父类异常catch块放在最后。
建议:在进行catch处理时,catch中一定要定义具体的处理方式。 不要简单定义一句:e.printStackTrace(),也不要就简单的就书写一条输出语句。
public class ExceptionDemo_4 {
	public static void main(String[] args) {
		Demo_4 d = new Demo_4();
		try{
			int a = d.div(5, 2);
			System.out.println("A: " + a);
		}catch (ArithmeticException e){
			System.out.println("除数不能为0: " + e.toString());
		}catch (ArrayIndexOutOfBoundsException e){//被捕获
			System.out.println("下标越界异常: " + e.toString());
		}catch (Exception e){
			System.out.println("发现异常: " + e.toString());
		}
	}
}
class Demo_4{
	int div(int a, int b) throws ArithmeticException, ArrayIndexOutOfBoundsException{
		int[] arr = new int[a];
		System.out.println(arr[5]);//发生异常,结束语句。
		return a / b;
	}
}
运行结果如下图所示:

09)**自定义异常

因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java的对问题封装的思想。将这些特有的问题进行自定义的异常封装。
/*
 * 自定义异常:
 * 需求:在本程序中,对于除数是负数,也视为错误的是无法进行运算的。那么就需要对这个问题进行自定义的描述。
 * 当函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。
 * 要么在catch内部try catch处理。
 * 要么在函数上声明让调用者处理。
 * 
 * 一般情况下,函数内部出现异常,函数上需要声明。
 * 定义异常信息:因为父类中已经把异常信息的操作都完成了。
 * 				所以子类在构造时,只要将异常信息传递给父类,通过super语句。就可以直接通过getMessage()方法获取自定义的异常信息。
 * 
 */
public class ExceptionDemo_5 {
	public static void main(String[] args) {
		Demo_5 d = new Demo_5();
		try{
			int a = d.div(10, -6);
			System.out.println("A: " + a);
		}catch (FuShuException e){
			System.out.println(e.toString());
			System.out.println("错误的负数是: " + e.getValue());
		}
		
	}
}
class Demo_5{
	int div(int a, int b) throws FuShuException {//抛出异常
		if (b < 0)
			throw new FuShuException("出现了除数为负数的情况", b);
		return a / b;
	}
}
class FuShuException extends Exception{
	private int value;
	FuShuException(){
		super();
	}
	FuShuException(String mag, int value){
		super(mag);
		this.value = value;
	}
	public int getValue(){
		return value;
	}
}
运行结果如下图所示:
10)throw和throws的区别
throws使用在函数上,throw使用在函数内。
throws后面跟的是异常类。可以跟多个,用逗号“,”隔开。
throw后面跟的是异常对象。
11)RuntimeException
RuntimeException的异常如果在函数内被抛出,在函数上可以不声明。
如果在函数上声明了该异常,调用者可以不用进行处理。
/*
 * 练习:汤姆在看电视。
 * 思考汤姆在看电视时会遇到的问题。
 * 
 * 比如问题是:电视卡屏、电视冒烟、杰瑞来捣乱。
 * 对问题进行描述,封装成对象。
 * 当出现第一种情况:电视机卡屏。重启电视机。
 * 当出现第二种情况:电视机冒烟。汤姆找斯派克修理电脑。
 * 当出现第三种情况:杰瑞来捣乱。汤姆抓杰瑞。
 */
public class ExceptionDemoTest {
	public static void main(String[] args) {
		Tom tom = new Tom("汤姆");
		try{
			tom.userTV();
		}catch (SPKException e){
			System.out.println(e.getMessage());
		}
	}
}
class TV{//电视机
	private int state = 2;//其它的都代表正常状态。这里初始化state为第二种状况:电视机冒烟。
	public void run() throws KaPException, MaoYException, JieRException{
		if (state == 1)
			throw new KaPException("第一种情况:电视机卡屏");
		if (state == 2)
			throw new MaoYException("第二种情况:电视机冒烟");
		if (state == 3)
			throw new JieRException("第三种情况:杰瑞来捣乱");
		else
			System.out.println("电视机正常运行");
	}
	public void reset(){//电视机出现问题后重启.
		System.out.println("重启电视机");//为了方便把关机再开机并为重启。
	}
}

class Tom{//汤姆使用电视机
	private String name;
	private TV tv;
	Tom(String name){
		this.name = name;
		tv = new TV();
	}
	public void userTV() throws SPKException{//抛给调用者
		try{
			tv.run();
			System.out.println("看电视");
		}catch (KaPException e){
			System.out.println(e.getMessage());
			tv.reset();
		}catch (MaoYException e){
			System.out.println(e.getMessage());
			System.out.println("不看电视啦");
			throw new SPKException("汤姆找斯派克修理电视机");//汤姆处理不了异常,只能抛出异常。
		}catch (JieRException e){
			System.out.println(e.getMessage());
			System.out.println("汤姆抓杰瑞");
		}
	}
}

class KaPException extends Exception{//卡屏异常
	KaPException(String mag){
		super(mag);
	}
}
class MaoYException extends Exception{//冒烟异常
	MaoYException(String mag){
		super(mag);
	}
}
class JieRException extends Exception{//杰瑞捣乱异常
	JieRException(String mag){
		super(mag);
	}
}
class SPKException extends MaoYException{//异常抛给斯派克
	SPKException(String mag){
		super(mag);
	}
}
private int state = 2;//其它的都代表正常状态。这里初始化state为第二种状况:电视机冒烟。
运行结果如下图所示:

附言:我是Java新人,如有错误的地方请指出。
                         每天学习一点点,纠错一点点,进步很大点。

-------  android培训java培训java学习型技术博客、期待与您交流! ----------


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【黑马程序员】面向对象(五) 第九天 的相关文章

随机推荐