2019年09月18日(星期三)  农历:己亥年八月二十

作者:三年。分类: JAVA

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/1455 人参与

发表评论:



手Q扫描加入Java初学者群