Java基础11--Object类--异常机制

11-1,Object类-equals方法

1,Object是所有类的根类。

Object是不断向上抽取而来的,具备着所有对象都具备的共性的内容。

2,equals方法:指示其他某个对象是否与此对象相等。equals(Object obj)。

equals方法比较的是两个对象的地址值。

他在Java中的源代码为:

public boolean equals(Object obj) {
	return this == obj;
}

调用格式为obj1.equals(obj2);

如:

Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;
System.out.println(p1 == p2);
System.out.println(p1.equals(p3));

11-2,equals方法覆盖

1,开发时一般都会覆盖equals方法,因为值判断地址值没有太大意义。

根据对象的特有内容,建立判断对象是否相等的依据。

如:

比较两个人的年龄是否相同:

public boolean equals(Object obj) {
	if(!(obj instanceof Person)) { //判断obj是否是Person类型
		throw new ClassCastException("类型错误");//如果不是Person类型,则不能向下转型
	}
	Person p = (Person)obj; //向下转型后才能使用子类中的特有内容
	return this.age == p.age;
}

这里因为用Object obj接收参数,相当于Object obj = p;把p2向上转型为Object类型,p2里面的特有内容不能使用。

 

11-3,Object类-hashCode方法

1,作用:返回该对象的散列码值(哈希码)。

2,Person p = new Person();

System.out.println(p.hashCode()); //打印十进制的哈希值

3,验证哈希码是否相同

Person p1 = new Person(20);
System.out.println(p1);
System.out.println(Integer.toHexString(p1.hashCode()));//把十进制的哈希值转成十六进制

11-4,Object类-getClass方法

1,作用:返回此Object的运行时类。

Person p1 = new Person();
Person p2 = new Person();
Class clazz1 = p1.getClass();
Class clazz2 = p2.getClass();
//比较获取的字节码文件的内存地址,由于p1和p2都是由Person创建的,所以地址相同
System.out.println(clazz1 == clazz2); //true
//返回字节码文件的名称
System.out.println(clazz1.getName()); //Person

以上例来说,Person类加载创建了Person.class文件,这个文件就是Person类以后创建对象的顶层字节码文件,Person.class字节码文件在内存中有且只有一个,p1和p2这些对象都是依据Person.class文件创建的。

getClass方法返回的就是这样的字节码文件。

 

11-5,Object类-toString方法

1,作用:返回该对象的字符串表示。

2,Person p1 = new Person();

Person p2 = new Person();

System.out.println(p1);//Person@616d63

System.out.println(p1.getClass().getName+ "$"+Integer.toHexString(p1.hashCode()));//Person$616d63

3,Object类的toString方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at标记符@和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:getClass().getName()+"@"+Integer.toHexString(hashCode());

4,为了实际应用,通常在子类中重写equals、hashCode和toString方法。

如:

public String toString() {
	return "Person : " + age;
}

11-6,异常-概述

1,异常:是在运行时间发生一些不正常的情况。

在Java中用类的形式对不正常的情况进行了描述和封装对象。

描述不正常的情况的类,就称为异常类。

以前正常的流程代码和问题处理代码相结合,现在将正常流程代码和问题处理代码分离,提高了阅读性。

其实异常就是Java通过面向对象的思想将问题封装成了对象。

用异常类对其进行描述。

不同的问题用不同的类进行具体的描述。比如角标越界,空指针等。

旧方法与新方法的比较:

class ExceptionDemo {
	public static void main(String[] args) {
		int[] arr = new int[3];
		arr = null;
		System.out.println(arr[3]);//抛出指向为空的异常,若没有arr=null则抛出角标越界异常
		sleep(-5); //若时间为负或大于10000,则抛出异常。
	}
	public static void sleep(int time) {
		/* 原始解决办法,正常流程代码和问题处理代码相结合
		if(time < 0) {
			处理办法...
		}
		if(time > 10000) {
			处理办法...
		}
		System.out.println("我睡" + time);
		*/
		//抛出异常的处理办法,正常流程代码和问题处理代码相分离
		//代码时间为负的情况,这个FuTime对象中会包含异常的名称,信息,位置等信息。
		if(time < 0) {
			抛出 new FuTime();
		}
		if(time > 10000) {
			抛出 new BigTime();
		}
		System.out.println("我睡" + time);
	}
}
//定义异常解决办法的类
class FuTime {
	处理办法...
}
class BigTime {
	处理办法...
}

11-7,异常体系

1,Java中有很多异常,每一个异常都是一个类。问题很多,意味着描述他的类也很多,将其共性向上抽取,就形成了异常体系。

2,最终问题分为两大类:

(1)一般不可处理的,用Error类表示。

(2)可以处理的,用Exception类表示。

Throwable

    |--Error

    |--Exception

无论是Error还是Exception,问题发生就应该可以抛出,让调用这知道并处理。该体系的特点就在于Throwable及其所有的子类都具有可抛性。

3,可抛性到底指的是什么呢?怎样体现可抛性呢?

是通过两个关键字来体现的,就是throws和throw,凡是可以被这两个关键字所操作的类和对象都具备可抛性。

4,Error的特点为:

是由JVM抛出的严重性的问题,这种问题发生一般不针对性处理,直接修改程序。

5,该体系的特点:

子类的后缀名都是用其父类名作为后缀,阅读性很强。

 

11-8,异常-原理&异常对象的抛出throw

1,异常抛出过程,用下面程序为例说明:

class Demo {
	public void method(int[] arr, int index) {
		/*  第一步:
		这一句会抛出一个异常
		throw new ArrayIndexOutOfBoundsException(index);
		这个抛出动作由JVM自动执行,运行到此处,发现角标越界,便抛出此异常
		抛给调用者,即主函数,抛出异常后,这个方法结束,不再输出haha。
		*/
		System.out.println(arr[index]);
		System.out.println("haha");
	}
}
class ExceptionDemo {
	public static void main(String[] args) {
		int[] arr = new int[3];
		Demo d = new Demo();
		/* 第二步:
		throw new ArrayIndexOutOfBoundsException(index);
		调用者主函数接收抛出的异常,继续向上抛出,抛给JVM,抛出后不再输出over。
		*/
		d.method(arr,3);
		System.out.println("over");
	}
}

第三步:

JVM的处理方式为:在控制台输出异常信息,反馈给用户,程序结束。

 

2,自定义异常抛出信息。

系统自带的抛出信息为英文,有时会在成阅读不便。故自定义信息,使其简明易懂。

class Demo {
	public int method(int[] arr, int index) {
		if(arr == null) 
			throw new NullPointerException("数组的引用不能为空!");
		if(index >= arr.length) 
			throw new ArrayIndexOutOfBoundsException("数组角标越界!" + index);
		if(index < 0) 
			throw new ArrayIndexOutOfBoundsException("数组角标不能为负数:" + index);
		return arr[index];
	}
}
class ExceptionDemo {
	public static void main(String[] args) {
		int[] arr = new int[3];
		Demo d = new Demo();
		int num = d.method(null,-30);
		System.out.println("num = " + num);
		System.out.println("over");
	}
}

使用throw关键字抛出异常。

 

11-9,异常-自定义异常&异常类的抛出

1,对于角标是正数不存在,可以用角标越界表示。

对于角标为负数的情况,准备用复数角标异常来表示。

负数角标这种异常在Java中并没有定义过,那就按照Java异常的创建思想,面向对象,将服输角标进行自定义描述,并封装成对象。

这种自定义的问题描述称为自定义异常。

注意:如果让一个类称为异常类,必须要继承异常体系,因为只有称为异常体系的子类才有资格具备可抛性,才可以被两个关键字所操作,throws和throw。

2,若要成为异常类,必须继承Exception类,并在产生此异常的方法后加上throws 异常类名。

调用此方法的语句的所属的方法也要加上throws 异常类名。

示例:

//自定义异常类必须继承Exception类,才具备可抛性
class FuShuIndexException extends Exception {
	FuShuIndexException() {}
	FuShuIndexException(Stirng msg) {
		super(msg);//用的是父类的构造方法,传参数调用
	}
}
class Demo {
	//在方法上throws声明这个方法可能抛出的异常
	public int method(int[] arr, int index) throws FuShuIndexException {
		if(index < 0) {
			throw new FuShuIndexException("角标不能是负数!");
		}
		return arr[index];
	}
}
class ExceptionDemo {
	//调用了可能抛出异常的方法,调用他的方法也要抛出异常
	public static void main(String[] args)throws FuShuIndexException {
		int[] arr = new int[3];
		Demo d = new Demo();
		int num = d.method(arr,-30);//此语句可能抛出异常
		System.out.println("num : " + num);
	}
}

 

11-10,异常-编译时检测异常和运行时异常的区别&throw和throws的区别

1,异常的分类:

(1)编译时被检测异常,只要是Exception和其子类都是,除了特殊子类RuntimeException体系这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。这样的问题都可以针对性的处理。

(2)编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类,这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的,或者是引发了内部状态变化而导致的。那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。

所以自定义异常类时,要么继承Exception,要么继承RuntimeException。

2,throw和throws的区别。

(1)throws使用在函数上。

    throw使用在函数内。

(2)throws抛出的是异常类,可以抛出多个,用逗号隔开。

    throw抛出的是异常对象。

3,11-9的例子中,若写为:

Class FuShuIndexException extendsRuntimeException,则Demo类中的方法和ExceptionDemo中的main方法就不用throw FuShuIndexException了。

 

11-11,异常-异常捕获try-catch

1,异常处理的捕捉形式:

这是可以对异常进行针对性处理的方式。

具体格式是:

try{
	//需要被检测异常的代码
} catch(异常类 变量) { //该变量用于接收发生的异常对象
	//处理异常的代码
} finally {
	//一定会被执行的代码
}

示例:

class ExceptionDemo {
	public static void main(String[] args) {
		int[] arr = new int[3];
		Demo d = new Demo();
		try {
			int num = d.method(arr, -1);
			/*
			由于num是局部变量,出了作用域便不可用,如后面的代码用到此变量
			也要放到try中。
			*/
			System.out.println("num=" + num);
		} catch(FuShuIndexException e) { //接收的是什么异常,此处就写什么异常类。
			System.out.println("message:" + e.getMessage());//打印异常信息
			//打印e的信息,格式为:异常名:信息,toString可以不写。
			System.out.println("string:" + e.toString());
			/*
			void类型的方法,不能在sop中输出。此方法输出异常的名称,信息,位置等,
			等同于throw出的异常信息,JVM默认的处理机制就是调用异常对象的这个方法。
			*/
			e.printStackTrace();
			System.out.println("负数角标异常");
		}
		System.out.println("over");
	}
}
class Demo {
	//抛出此异常,catch中也应该接受此异常处理要有针对性。
	public int method(int[] arr, int index) throws FuShuIndexException {
		if(index < 0) {
			throw new FuShuIndexException("角标不能是负数");
		}
		return arr[index];
	}
}

2,捕捉过程


步骤:

(1)调用method方法时,method方法声明了抛出的异常,传入的-30满足index<0的条件,用throw抛出了异常,抛给main中的调用者,调用者用trycatch对异常进行了解决。

(2)满足index<0抛出异常。

(3)由于用trycatch形式处理异常,会直接在catch中解决,输出”负数角标异常”,之后的”over”也输出。

 

11-12,异常-多catch情况

throws声明异常可以有多个,用逗号隔开,用下例说明:

class FuShuIndexException extends Exception {
	FuShuIndexException() {}
	FuShuIndexException(String msg) {
		super(msg);
	}
}
class Demo {
	public int method(int[] arr, int index) throws NullPointerException,FuShuIndexException {
		if(arr == null) 
			throw new NullPointerException("没有任何数组实体");
		if(index < 0)
			throw new FuShuIndexException();
		return arr[index];
	}
}
class ExceptionDemo {
	public static void main(String[] args) {
		int[] arr = new int[3];
		Demo d = new Demo();
		try {
			//在try后面,一般都先执行第一个catch,若Exception在最上面,则其他catch白写。
			int num = d.method(null, -1);
			System.out.println("num = " + num);
		} catch(NullPointerException e) {
			System.out.println(e.toString());
		} catch(FuShuIndexException e) {
			System.out.println("message:" + e.getMessage());
			System.out.println("String:" + e.toString());
			e.printStackTrace();
			System.out.println("负数角标异常");
		} catch(Exception e) {}
		/*
		多catch情况,父类的catch放在最下面
		Exception是所有异常类的父类,若可能有抛出的以外的其他异常的情况发生,
		需要使用Exception解决时,Exception必须放在最下面。
		*/
		System.out.println("over");
	}
}

 

11-13,异常处理原则

1,原则:

(1)函数内部如果抛出需要检测的异常,那么函数上必须声明。否则必须在函数内使用trycatch捕捉,否则编译失败。

(2)如果调用了声明异常的函数,要么trycatch要么throws,否则编译失败。

(3)什么时候用catch,什么时候用throws呢?

功能内部可以解决用catch;

解决不了,用throws告诉调用者,由调用者解决。

(4)一个功能如果抛出了多个异常,那么调用时,必须有对应的多个catch进行针对性的处理。内部有几个需要检测的异常,就抛出几个异常,抛出几个就catch几个。

 

11-14,异常-finally代码块

1,finally通常用于关闭(释放)资源,以下例说明,finally不管怎样都会执行,但若在finally前使用了System.exit(0);则finally不执行,System.exit(0);直接退出了JVM。

class Demo {
	public int show(int index) throws ArrayIndexOutOfBoundsException {
		if(index < 0)
			throw new ArrayIndexOutOfBoundsException("角标越界");
		int[] arr = new int[3];
		return arr[index];
	}
}
class ExceptionDemo {
	public static void main(String[] args) {
		Demo d = new Demo();
		try {
			int num = d.show(-1);
			System.out.println("num:" + num);
		} catch(ArrayIndexOutOfBoundsException e) {
			System.out.println(e.toString());
			//return;退出main函数,只输出e.toString()和finally中的内容
			//System.exit(0);退出JVM,只输出e.toString()
		} finally {//通常用于关闭(释放)资源
			System.out.println("finally");
		}
		System.out.println("over");
	}
}

2,例如:

连接数据库

查询:抛出异常Exception

关闭连接

在连接数据库后,进行查询的时候抛出了异常,若没有finally去结束链接,则数据库不会断开连接,会占用大量资源。Finally是无论怎样都会执行的代码块,若在抛出异常后,在finally中结束链接,则会释放资源。

3,try,catch,finally代码的组合特点

(1)try-catch-finally常规组合

(2)try catch(多个)

    当没有必要资源需要释放的时候,可以不定一finally。

(3)try-finally

异常无法直接用catch处理,但是资源需要关闭时使用。

如:

void show() throws Exception { //方法中有抛出异常,需要声明
	try{
		//开启资源
		//抛出异常后无法正常关闭资源,用finally关闭,这个异常无法用catch直接处理
		throw new Exception();
	} finally {
		//关闭资源
	}
}

11-15,异常应用

需求:老师用电脑上课

这个问题涉及两个对象,老师和电脑。

其中可能产生的问题:比如电脑蓝屏,冒烟,没响应。

//首先定义三个异常类
class LanPingException extends Exception {
	LanPingException() {}
	LanPingException(String msg) {
		super(msg);
	}
}
class MaoYanException extends Exception {
	MaoYanException() {}
	MaoYanException(String msg) {
		super(msg);
	}
}
class NoPlanException extends Exception {
	NoPlanException() {}
	NoPlanException(String msg) {
		super(msg);
	}
}
class Computer {
	//初始化状态,0表示正常,1表示蓝屏,2表示冒烟
	private state = 0;
	public void run() throws LanPingException,MaoYanException {
		if(state == 1)
			throw new LanPingException("电脑蓝屏了!");
		if(state == 2)
			throw new MaoYanException("电脑冒烟了!");
		System.out.println("电脑运行");
	}
	public void reset() {
		state = 0;
		System.out.println("电脑重启");
	}
}
class Teacher {
	private String name;
	private Computer comp;
	Teacher(String name) {
		this.name = name;
		//老师携带电脑,在初始化时创建Computer对象
		comp = new Computer();
	}
	//捕获的冒烟异常中抛出了此异常
	public void prelect() throws NoPlanException {
		try {
			comp.run();
			System.out.println(name + "讲课");
		} catch(LanPingException e) {
			System.out.println(e.toString());
			comp.reset();
			prelect();
		} catch(MaoYanException e) {
			System.out.println(e.toString());
			test();
			throw new NoPlanException("课时进度无法完成,原因:" + e.getMessage());
			/*
			这里虽然抛出的是冒烟异常,但是抛出后上级无法解决,所以抛出计划无法完成异常,
			让上级能够解决。抛出异常和声明异常应根据实际情况而定。
			*/
		}
	}
	public void test() {
		System.out.println("大家练习");
	}
}
class ExceptionTest {
	public static void main(String[] args) {
		Teacher t = new Teacher("老师");
		try {
			t.prelect();
		} catch(NoPlanException e) {
			System.out.println(e.toString() + "...");
			System.out.println("换老师");
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值