JAVASE基础语法(异常、常用类)

news/2024/5/18 17:32:45

一、异常

1.1 什么是异常

异常就是指不正常。是指代码在运行过程中可能发生错误,导致程序无法正常运行。

package com.atguigu.exception;public class TestException {public static void main(String[] args) {int[] arr = {1,2,3,4,5};System.out.println("数组下标为[10]的元素:" + arr[10]);//运行时发生 ArrayIndexOutOfBoundsException数组下标越界异常System.out.println("数组的长度:" + arr.length);//不执行}
}

1.2 异常的类型(怎么划分分类是重点)

Java是面向对象的编程语言,以“对象”为中心。所以,Java也把异常用对象表示。对象是由某种类new出来的,那么每一种异常的情况都会有一个异常的类来描述它。例如:数组下标越界异常 就用 java.lang.ArrayIndexOutOfBoundsException 类来描述它。

因为异常的类型非常多,所以我们有必要学习它们的继承关系图:

作为异常的根类型是java.lang.Throwable类型(当然如果类的角度来说,根类型仍然是Object)。

 Throwable有两大子类:

  • Error:是 Throwable 的子类,用于指示合理的应用程序不应该试图捕获(catch)的严重问题。例如:VirtualMachineError(虚拟机错误)下的子类StackOverflowError(栈内存溢出错误),它在我们无条件递归调用时发生过。这种错误必须停下来,修正我们的程序,或升级硬件,或软件的架构。

  • Exception:Exception 类及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。

    • 对于Exception系列的异常来说,特别是RuntimeException系列能避免的尽量避免(依赖于程序员的经验或素质)。不能避免的,就要通过try-catch来处理。

Exception下面又可以分为两大类:

  • RuntimeException及其子类:运行时异常,又称为非受检异常。非受检异常是指编译器不会对当前代码做该系列的异常类型检查。例如:ArrayIndexOutOfBoundsException(数组下标越界异常) 或 NullPointerException(空指针异常)等,编译器不会提示你,你的代码可能发生这种异常,直到程序运行时,发生异常,我们才知道。简单的说,编译器检查不出来这个系列的异常。

    • ArrayIndexOutOfBoundsException(数组下标越界异常)

    • NullPointerException(空指针异常)

    • ClassCastException(类型转换异常):向下转型可能发生

    • ArithmeticException(算术异常): a / 0 会发生这个异常

  • RuntimeException系列以外的,包括Exception本身:编译时异常,又称为受检异常。受检异常是指编译器会对当前代码做该系列的异常类型检查,不管这个异常是不是发生,会不会发生,编译器只要认为有可能发生,就会报编译错误,即编译不通过。必须等程序员写好对该异常的处理代码后,才会编译通过。

  • 总结:无论是编译时异常,还是运行时异常,当运行的时候,异常真的发生了,都会导致程序崩溃。它们的区别只是看编译器是否提醒你而已。

package com.atguigu.exception;public class TestRuntimeException {public static void main(String[] args) {int[] arr = {1,2,3,4,5};System.out.println("数组下标为[10]的元素:" + arr[10]);//这句代码编译器压根不检查,是否下标越界。无论下标是否越界,只要数组名对了,下标是int值,就会编译通过//但是编译通过,不代表运行正常}
}

 

package com.atguigu.exception;import java.io.FileInputStream;
import java.io.FileNotFoundException;public class TestCheckException {public static void main(String[] args) throws FileNotFoundException {//FileInputStream:File(文件)Input(输入)Stream(流),这个流是用来读取文件的内容//下面这句代码,表示想要从 d:\1.txt文件读取文件内容FileInputStream fis =new FileInputStream("d:\\1.txt");//此时d:\1.txt文件存不存在,编译器都会提醒你,这段代码可能发生FileNotFoundException//编译报错,不是说这个文件一定不存在,只是说可能不存在//必须要求程序员说明(通过代码说明)如果文件不存在,怎么办,编译才会通过。//例如:我告诉编译器,如果文件不存在,发生了FileNotFoundException,那么main方法不管,程序要挂就挂吧}
}

 

1.3 try-catch异常的处理(重点,围绕5个关键字)

try{可能发生异常的业务代码语句1;可能发生异常的业务代码语句2;可能发生异常的业务代码语句3;可能发生异常的业务代码语句4;可能发生异常的业务代码语句5;
}catch(异常的类型1 参数名){ //参数名一般都是写e//(1)打印异常信息的代码 ,要么打印到控制台,要么记录到日志, 打印它的目的是便于程序员后期跟踪,查看发生问题的地方,发生问题的原因,便于后期维护代码//(2)对异常的处理代码,有的时候引起异常的问题不处理,下面的代码是无法正常运行。
}catch(异常的类型2 参数名){ //
}catch(异常的类型3 参数名){ //
}

执行特点:

(1)try{}没有发生异常,那么所有的catch都不会执行。

(2)try{}中发生了异常,例如:“可能发生异常的业务代码语句3;”发生了异常,try中语句4和语句5不执行。

  • 如果语句3发生的是 异常的类型1的问题,那么就从try“语句3”跳到了 第一个catch 分支执行,下面的两个catch不会执行。

  • 如果语句3发生的是 异常的类型2的问题,那么就从try“语句3”跳到了 第二个catch 分支执行,上面的与下面的两个catch不会执行。

  • 如果语句3发生的是 异常的类型3的问题,那么就从try“语句3”跳到了 第三个catch 分支执行,上面的两个catch不会执行。

  • 如果语句3发生的是 异常的类型4的问题,3个catch都不执行了,就会导致 当前方法 异常结束,即当前方法就挂了。

    • 如果当前方法main方法,main方法是JVM调用的,那么程序就挂了。

    • 如果当前方法其他方法,那么就会“带着这个异常对象”回到调用这个方法的位置,等着调用者处理这个异常。

示例一

没有处理异常的代码:有潜在风险
package com.atguigu.exception;import java.util.Scanner;public class TestTryCatch {public static void main(String[] args) {//需求:从键盘输入2个字符串类型的整数值,然后把它们转为int值,求它们的商//本来直接输入int类型的整数,用int类型的变量接收即可,这里为了说明问题,故意把问题复杂化Scanner input = new Scanner(System.in);System.out.print("请输入第一个整数:");String str1 = input.next();//123System.out.print("请输入第二个整数:");String str2 = input.next();int a = Integer.parseInt(str1);int b = Integer.parseInt(str2);int result = a / b;System.out.println("商: " + result);input.close();//上面的代码,编译器没有发现潜在的问题//说明一会发生的异常,都是运行时异常}
}
加上处理异常的代码:更健壮
  • 如果能通过条件判断避免的,就不用try-catch,例如:除数为0的情况。

  • 如果不能通过条件判断的避免的,就需要用try-catch处理,来增强程序的健壮性

  • 如果有潜在的异常问题,不判断避免,也不用try-catch处理,程序就会很脆弱,一旦发生问题,程序就挂了。以后大家是写服务器端程序,服务器不能随便就挂了。

package com.atguigu.exception;import java.util.Scanner;public class TestTryCatch {public static void main(String[] args) {//需求:从键盘输入2个字符串类型的整数值,然后把它们转为int值,求它们的商//本来直接输入int类型的整数,用int类型的变量接收即可,这里为了说明问题,故意把问题复杂化Scanner input = new Scanner(System.in);int a = 0;while (true) {try {//选中要用try包围的代码,按快捷键Ctrl  + Alt  +TSystem.out.print("请输入第一个整数:");String str1 = input.next();//123//如果输入张三,Integer.parseInt(str1);代码会报错 java.lang.NumberFormatException//NumberFormatException数字格式化异常, “张三" 转换格式,转换为int失败了//(1)想要避免这个异常,也能做到,但是需要学习后面的知识,比如正则,判断str1中是不是纯数字(现在还未学习)//(2)也可以使用try-catcha = Integer.parseInt(str1);break;//如果Integer.parseInt(str1)没有发生异常,break就会执行//如果Integer.parseInt(str1)发生异常,break不执行,而且跳到catch执行} catch (NumberFormatException e) {e.printStackTrace();//打印异常的信息到控制台}}int b;//声明改到while上面,为了提升b变量的作用域while(true) {try {System.out.print("请输入第二个整数:");String str2 = input.next();b = Integer.parseInt(str2);if(b != 0 ){break;}else{System.out.println("除数不能为0!");}} catch (NumberFormatException e) {e.printStackTrace();//打印异常的信息到控制台}}int result = a / b;System.out.println("商: " + result);input.close();}
}

 

try-catch和循环的嵌套关系对比

示例二:

没有处理异常的代码:有潜在风险
package com.atguigu.exception;import java.util.InputMismatchException;
import java.util.Scanner;public class TestTryCatch3 {public static void main(String[] args) {//需求:从键盘输入2个整数值,求它们的商Scanner input = new Scanner(System.in);System.out.print("请输入第一个整数:");int  a = input.nextInt();System.out.print("请输入第二个整数:");int b = input.nextInt();int result = a / b;System.out.println("商: " + result);input.close();//上面的代码,编译器没有发现潜在的问题//说明一会发生的异常,都是运行时异常}
}
加上处理异常的代码:更健壮
package com.atguigu.exception;import java.util.InputMismatchException;
import java.util.Scanner;public class TestTryCatch3 {public static void main(String[] args) {//需求:从键盘输入2个整数值,求它们的商Scanner input = new Scanner(System.in);int a = 0;while (true) {try {System.out.print("请输入第一个整数:");a = input.nextInt();break;//如果a = input.nextInt();发生异常,break不执行,跳到catch执行//如果a = input.nextInt();没有发生异常,break执行,结束循环,catch不会执行} catch (InputMismatchException e) {//输入不匹配异常,本来想要让用户输入int值,结果它输入其他的e.printStackTrace();//在控制台打印异常信息/*a = input.nextInt();代码发生异常,因为我们输入的是张三回车,而nextInt()只能从输入通道中读取int值,它发现通道里面只有张三回车,nextInt()不读取张三,就报异常了。为了把张三回车给读取掉,需要加一句代码。 input.nextLine()这样才可以把张三以及张三后面的回车符一起读取掉,这样呢,用户才能有机会重新输入*/input.nextLine();}}int b;while (true) {try {System.out.print("请输入第二个整数:");b = input.nextInt();if (b != 0) {break;} else {System.out.println("除数不能为0!");}} catch (Exception e) {e.printStackTrace();input.nextLine();}}int result = a / b;System.out.println("商: " + result);input.close();}
}

1.4 try-catch-finally

try{可能发生异常的业务代码语句1;可能发生异常的业务代码语句2;可能发生异常的业务代码语句3;可能发生异常的业务代码语句4;可能发生异常的业务代码语句5;
}catch(异常的类型1 参数名){ //参数名一般都是写e//(1)打印异常信息的代码 ,要么打印到控制台,要么记录到日志, 打印它的目的是便于程序员后期跟踪,查看发生问题的地方,发生问题的原因,便于后期维护代码//(2)对异常的处理代码,有的时候引起异常的问题不处理,下面的代码是无法正常运行。
}catch(异常的类型2 参数名){ //
}catch(异常的类型3 参数名){ //
}finally{//无论上面的try是否发生了异常,//也不管catch是否可以捕获异常,//就算try或catch有return语句,finally块都会执行//一般是资源关闭代码写到这里面//如果finally里面写了return语句,try,catch中的return语句就失效了
}

示例一

异常没有处理:
package com.atguigu.exception;import java.util.InputMismatchException;
import java.util.Scanner;public class TestTryCatchFinally1 {public static void main(String[] args) {//需求:输入一个整数,然后打印它Scanner input = new Scanner(System.in);System.out.print("请输入一个整数:");int num = input.nextInt();System.out.println("num = " + num);//(1)input.close();//(2)System.out.println("下面的代码:我爱尚硅谷!");//(3)//没有异常处理代码,一旦input.nextInt()发生异常,下面所有代码(1)(2)(3)都不执行了,程序就挂了}
}
有正确捕获异常:
package com.atguigu.exception;import java.util.InputMismatchException;
import java.util.Scanner;public class TestTryCatchFinally2 {public static void main(String[] args) {//需求:输入一个整数,然后打印它Scanner input = new Scanner(System.in);try {System.out.print("请输入一个整数:");int num = input.nextInt();System.out.println("num = " + num);//(1)} catch (InputMismatchException e) {e.printStackTrace();//打印异常}input.close();//(2)System.out.println("下面的代码:我爱尚硅谷!");//(3)//上面异常正确捕获,//input.nextInt()发生异常,下面的代码(1)不执行,(2)(3)正常执行}
}
没有正确捕获异常
package com.atguigu.exception;import java.util.Scanner;public class TestTryCatchFinally3 {public static void main(String[] args) {//需求:输入一个整数,然后打印它Scanner input = new Scanner(System.in);try {System.out.print("请输入一个整数:");int num = input.nextInt();System.out.println("num = " + num);//(1)} catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();//打印异常}input.close();//(2)System.out.println("下面的代码:我爱尚硅谷!");//(3)//上面异常没有正确捕获,//input.nextInt()发生异常,下面的代码(1)(2)(3)都不执行}
}
加finally
package com.atguigu.exception;import java.util.InputMismatchException;
import java.util.Scanner;public class TestTryCatchFinally4 {public static void main(String[] args) {//需求:输入一个整数,然后打印它Scanner input = new Scanner(System.in);try {System.out.print("请输入一个整数:");int num = input.nextInt();System.out.println("num = " + num);} catch (InputMismatchException e) {e.printStackTrace();//打印异常} finally {input.close();System.out.println("下面的代码:我爱尚硅谷!");}//加finally,无论异常是否正确捕获//input.nextInt()发生异常,下面的代码(1)不执行,(2)(3)执行}
}

示例2:加return

执行finally和try的return
package com.atguigu.exception;public class TestTryCatchFinally5 {public static void main(String[] args) {int a = getANumber();System.out.println(a);//结果是1}public static int getANumber(){try {return 1;}catch(Exception e){return 2;}finally {System.out.println("finally");}}
}
执行finally和catch的return
package com.atguigu.exception;public class TestTryCatchFinally6 {public static void main(String[] args) {int a = getANumber();System.out.println(a);//返回2}public static int getANumber(){try {System.out.println(1/0);return 1;}catch(Exception e){return 2;}finally {System.out.println("finally");}}
}
执行finally和finally的return
package com.atguigu.exception;public class TestTryCatchFinally7 {public static void main(String[] args) {int a = getANumber();System.out.println(a);//返回3}public static int getANumber(){try {System.out.println(1/0);return 1;}catch(Exception e){return 2;}finally {return 3;}}
}

1.5 throws

1.5.1 throws的用法

这个关键字,用于在方法的(形参列表)后面,方法体{}的前面,写明该方法可能发生xx类型的异常,在该方法中并未“处理”,需要调用者来处理这些异常。

注意:如果调用者是main方法,那么main方法就应该选择try-catch,否则就等价于异常没有处理,一旦发生,程序就挂了。

如果调用者不是main方法,还可以继续throws,让调用 调用者的地方来处理。

【修饰符】 class 类名{【修饰符】 返回值类型 方法名(【形参列表】) throws 异常类型列表{}
}
【修饰符】 class 类名{【修饰符】 返回值类型 main(【形参列表】) {try{b(实参列表);}catch(异常类型 e){//....}//其他代码(正常执行)}修饰符】 返回值类型 b(【形参列表】) throws 异常类型列表{c(实参列表);//语句1  其他语句2 ; //如果c方法中的语句B发生异常,等价于语句1 这句代码发生异常,其他语句2不会执行,b方法就会挂掉,并且带着异常对象回到main方法}修饰符】 返回值类型 c(【形参列表】) throws 异常类型列表{语句A;语句B;//可能发生异常的代码语句C;//如果语句B发生异常,语句C不会执行,c方法就会挂掉,并且带着异常对象回到b方法。}
}
【修饰符】 class 类名{【修饰符】 返回值类型 main(【形参列表】) {b(实参列表);}修饰符】 返回值类型 b(【形参列表】) {try{c(实参列表);//语句1 }catch(异常类型 e){//....}其他语句2 ; //如果c方法中的语句B发生异常,等价于语句1 这句代码发生异常,因为这里有try-catch把异常捕获了,//那么其他语句2会执行}修饰符】 返回值类型 c(【形参列表】) throws 异常类型列表{语句A;语句B;//可能发生异常的代码语句C;//如果语句B发生异常,语句C不会执行,c方法就会挂掉,并且带着异常对象回到b方法。}
}

1.5.2 方法重写的要求

方法的重载(Overload)方法的重写(Override)
声明的位置同一个类中 或 父子类中父子类中
权限修饰符不看应该 > 或 = 被重写方法的权限修饰符,并且被重写方法不能是private
其他修饰符不看不能是static,final
返回值类型不看基本数据类型和void:必须相同 引用数据类型:应该 < 或 = 被重写方法的返回值类型
方法名必须相同必须相同
(形参列表)必须不同(类型、个数、顺序不同,和形参名无关)必须相同(类型、个数、顺序相同,和形参名无关)
throws 异常类型不看如果被重写方法没有加throws 编译时异常类型列表,那么重写时,不可以再加throws 编译时异常类型列表。 如果被重写方法加throws 编译时异常类型列表,那么重写时,throws后面的编译时类型异常 必须满足 < 或 = 的关系。 和运行时类型的异常无关。
父类Father示例代码
package com.atguigu.exception;import java.io.FileNotFoundException;public class Father {public void m1()throws Exception{//....}public void m2()throws Exception{//....}public void m3()throws FileNotFoundException {//....}public void m4(){//....}public void m5(){}
}
子类Son示例代码
package com.atguigu.exception;import java.io.FileNotFoundException;public class Son extends Father{@Overridepublic void m1() throws Exception {//throws的异常类型与父类相同///}//FileNotFoundException < Exception@Overridepublic void m2() throws FileNotFoundException {//....}/*    //Exception > FileNotFoundException@Overridepublic void m3() throws Exception {//错误//...}*//*    @Overridepublic void m4() throws FileNotFoundException {//错误,因为父类被重写方法没有throws编译时异常类型//....}*///运行时异常,编译器根本不检查public void m5()throws ArithmeticException{}
}

1.5.3 java.lang.Cloneable接口

Cloneable接口:克隆接口,克隆就是复制的意思。

在java.lang.Object类中有一个clone方法:

protected native Object clone() throws CloneNotSupportedException;

权限修饰符:protected(受保护),表示这个方法只能在本类、本包、其他包的子类本身中调用。

说明:重写clone方法的类,还必须实现java.lang.Cloneable接口。

  • 如果子类不重写clone方法,不能在子类以外的地方,调用子类对象的clone方法。例如:Student类没有重写clone方法,就不能在测试类TestCloneable中调用学生对象的clone方法

  • 如果子类不实现Cloneable接口,那么就算子类重写clone方法,也会发生CloneNotSupportedException异常。

  • 调用clone方法时,编译器会提醒你需要处理CloneNotSupportedException异常,因为CloneNotSupportedException属于编译时受检异常。

Student类
package com.atguigu.exception;public class Student implements Cloneable{private String name;private int score;public Student() {}public Student(String name, int score) {this.name = name;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", score=" + score +'}';}//重写时把方法的返回值类型从Object修改为Student,这是可以的  <=//重写时权限修饰符可以从protected修改为public,这是可以的   >=@Overridepublic Student clone() throws CloneNotSupportedException {return (Student) super.clone();}
}
测试类TestCloneable
package com.atguigu.exception;public class TestCloneable {public static void main(String[] args) {Student s = new Student("张三", 100);//复制一个s对象
/*        Student s2 = s;//不是复制,是两个变量s,s2都指向同一个对象s.setName("张四");System.out.println(s);System.out.println(s2);*/try {Student s2 = s.clone();//克隆一个对象,复制一个属性值一模一样的对象//s对象在调用clone()方法,s对象是Student类型,//只能在Student类中调用这个方法//解决办法:让Student类重写clone方法s2.setName("张四");System.out.println(s);System.out.println(s2);} catch (CloneNotSupportedException e) {//编译器提醒我们要try-catch处理,说明CloneNotSupportedException是编译时(受检)异常e.printStackTrace();}}
}

1.6 练习题讲解

练习题1

package com.atguigu.exer2;public class Test2 {public static void main(String[] args) {int test = test(3,5);System.out.println(test);//8}public static int test(int x, int y){int result = x;try{if(x<0 || y<0){//条件不成立return 0;//不执行}result = x + y;//执行 result = 8return result; //执行它/*return有两个作用:(1)返回结果给调用者    先把result变量的值8返回给调用者(2)结束当前方法      本来应该结束当前方法的执行,但是因为有finally,要先去执行finally//执行完finally,结束当前方法的执行*/}finally{result = x - y;//修改result ,result = -2}}
}

练习题2

package com.atguigu.exer3;public class Test3 {static int i = 0;public static void main(String[] args) {System.out.println(test());//2}public static int test(){try{return ++i;/*return有两个作用:(1)返回结果给调用者    计算++i的值,i=1,返回i的值1的给调用者(2)结束当前方法      本来应该结束当前方法的执行,但是因为有finally,要先去执行finally*/}finally{return ++i;/*return有两个作用:(1)返回结果给调用者    计算++i的值,i=2,返回i的值2的给调用者(2)结束当前方法      结束当前方法的执行*/}}
}

1.7 自定义异常

1、为什么要自定义?

虽然核心类库中已经给我们预备了很多的异常类型了,但是我们有时候仍然需要自定义异常类型。因为异常的类型名最好能够清晰的描述我们发生异常的问题,即异常类型名最好能见名知意。系统预定义的这些异常类型,可能并不能准确的描述你的业务层面的一些异常问题,所以就最好自定义。

2、如何自定义异常类型

  • 必须继承Throwable或其子类。通常会继承Exception(继承它,你的自定义异常就是受检异常)或RuntimeException(继承它,你的自定义异常就是非受检异常)

    • 因为只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。

    • 类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。

  • 建议自定义异常时,提供无参构造以及能为从父类继承的message属性赋值的有参构造

3、注意

自定义异常需要通过throw语句抛出,同样可以throws告诉调用者处理,最后仍然使用try-catch。

自定义异常类型:钱不能为负数的异常
package com.atguigu.exception;//钱不能为负数的异常
public class MoneyCannotNegativeException extends Exception{public MoneyCannotNegativeException() {}public MoneyCannotNegativeException(String message) {super(message);}
}
自定义异常类型:钱不够异常
package com.atguigu.exception;//钱不够异常
public class MoneyNotEnoughException extends Exception{public MoneyNotEnoughException() {}public MoneyNotEnoughException(String message) {super(message);}
}
银行账号类Account
package com.atguigu.exception;public class Account {private String id;//账号private double balance;//余额public Account() {}public Account(String id, double balance) {this.id = id;this.balance = balance;}public String getId() {return id;}public void setId(String id) {this.id = id;}public double getBalance() {return balance;}public void withdraw(double money) throws MoneyCannotNegativeException, MoneyNotEnoughException {if(money < 0){
//            System.out.println("取款不能为负数");
//            throw new MoneyCannotNegativeException();throw new MoneyCannotNegativeException("取款不能为负数!");}else if(money > balance){
//            System.out.println("余额不足!");
//            throw new MoneyNotEnoughException();throw new MoneyNotEnoughException("余额不足!");}else{balance -= money;}}public void save(double money) throws MoneyCannotNegativeException {//存款if(money < 0){
//            System.out.println("存款不能为负数");
//            throw new MoneyCannotNegativeException();throw new MoneyCannotNegativeException("存款不能为负数!");}else{balance += money;}}@Overridepublic String toString() {return "Account{" +"id='" + id + '\'' +", balance=" + balance +'}';}
}
测试类
package com.atguigu.exception;public class TestAccount {public static void main(String[] args) {Account a = new Account("111111", 5000);try {a.save(500);System.out.println("存500后:"+a);} catch (MoneyCannotNegativeException e) {e.printStackTrace();}try {a.save(-500);System.out.println("存-500后:"+a);} catch (MoneyCannotNegativeException e) {e.printStackTrace();}try {a.withdraw(500);System.out.println("取500后:"+a);} catch (MoneyCannotNegativeException e) {e.printStackTrace();} catch (MoneyNotEnoughException e) {e.printStackTrace();}try {a.withdraw(6000);System.out.println("取6000后:"+a);} catch (MoneyCannotNegativeException e) {e.printStackTrace();} catch (MoneyNotEnoughException e) {e.printStackTrace();}}
}

1.8 思考题:throw与throws有什么区别

throwthrows
位置方法体里面(形参列表)的后面,方法体的前面
作用抛出一个异常的对象告诉调用者该方法可能发生xx类型的异常
后面接的东西不同throw 后面跟一个异常对象throws后面跟一个或多个的异常的类型名
使用形式throw new 异常类型(【实参列表】);【修饰符】 返回值类型 方法名(【形参列表】) throws 异常类型1,异常类型2{ }

二、根父类

Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都继承这个类的方法。

public String toString():默认返回对象的运行时类型(new对象的类型)+@+对象的hashCode值是十六进制形式。类似于虚拟地址。建议所有子类都重写此方法。重写的快捷键:Alt + Insert 或 Ctrl + O。打印对象时,会自动调用toString()。
protected Object clone()throws CloneNotSupportedException如果子类对象要调用clone方法,要求子类重写clone方法。并且子类要实现java.lang.Cloneable接口,否则会报CloneNotSupportedException。
public final Class<?> getClass():返回此对象的运行时类(new对象的类型)。
protected void finalize()throws Throwable 这个方法已经被废弃了。比喻:它用来留临终遗言实际:当一个类的对象在被GC(垃圾回收器)回收之前(即彻底要在JVM中消失了),会自动调用这个对象的finalize()。通常在这个方法中,编写释放该对象占用的一些系统资源。有些公司的题库比较老,有一个这样的面试题:finally,final,finalize的区别?finally是与try-catch一起使用的关键字。final是用来修改类、方法、变量的关键字。finalize是Object中一个方法,用于释放系统资源的方法,现在已经废弃了。
public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。 如果用模板生成,就没有问题,但是如果自己手动重写,需要遵守如下要求:强烈建议用快捷键生成,不要手动重写。(1)自反性:自己和自己比较返回true(2)传递性:x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也一定返回true(3)对称性:x.equals(y)返回true,那么y.equals(x)也一定返回true(4)一致性:x..equals(y)前面返回true,x和y的属性都没有修改,下面再次调用x..equals(y)也要返回true(5)一个非空对象.equals(null)一定返回false
public int hashCode():返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。 只有把对象放到哈希结构的容器中,这个方法才有意义,否则没有意义。(等后面再学习它)但是,记住,equals和hashCode方法一定要一起重写。如果用模板生成,就没有问题,但是如果自己手动重写,需要遵守如下要求:强烈建议用快捷键生成,不要手动重写。(1)如果两个对象equals方法返回true,两个对象的hashCode()的结果必须相同。(2)如果两个对象的hashCode()不同,那么这个两个对象equals方法返回false。(3)如果两个对象的hashCode()相同,那么这两个对象的equals方法可能是true,可能是false。

 

示例代码1:getClass()

package com.atguigu.object;import com.atguigu.exception.Father;
import com.atguigu.exception.Son;public class TestObjectAPI {public static void main(String[] args) {Object obj = "hello";//多态引用System.out.println(obj.getClass());//class java.lang.String/*obj的编译时类型是Object,看左边obj的运行时类型是String,看右边*/Object obj2 = 1;System.out.println(obj2.getClass());//class java.lang.Integer//Object是引用数据类型,不能赋值基本数据类型的值。如果给它基本数据类型的值,会自动装箱为包装类的对象。Father f = new Son();System.out.println(f.getClass());//class com.atguigu.exception.SonString str = "hello";System.out.println(str.getClass());//class java.lang.String}
}

示例代码2:finalize(了解)

package com.atguigu.object;public class Demo {@Overrideprotected void finalize() throws Throwable {System.out.println("我轻轻的走了,不带走一段代码....");}
}
package com.atguigu.object;public class TestDemo {public static void main(String[] args) {Demo d = new Demo();d = null;//d变量不引用上面的对象了,那么上面的对象就成垃圾了System.gc();//主动呼叫GC来回收内存垃圾try {Thread.sleep(5000);//停秒,别那么着急结束main} catch (InterruptedException e) {e.printStackTrace();}}
}

 

示例代码3:equals

Person类
package com.atguigu.object;public class TestDemo {public static void main(String[] args) {Demo d = new Demo();d = null;//d变量不引用上面的对象了,那么上面的对象就成垃圾了System.gc();//主动呼叫GC来回收内存垃圾try {Thread.sleep(5000);//停秒,别那么着急结束main} catch (InterruptedException e) {e.printStackTrace();}}
}
测试类
package com.atguigu.object;import java.util.Scanner;public class TestPerson {public static void main(String[] args) {Person p1 = new Person("张三",23);Person p2 = new Person("张三",23);System.out.println(p1 == p2);//false//==比较的是对象的首地址,new了两次,两个对象的首地址一定是不同的System.out.println(p1.equals(p2));/*(1)如果Person类没有重写equals方法,从Object继承的equals也是比较对象的首地址。(2)如果想要Person对象调用equals方法时,比较对象的属性值,那么就应该重写equals方法。重写equals方法的快捷键:Alt + Insert*///  System.out.println(p1.equals(p1));//比较地址值就可以了System.out.println(p1.equals(null));//p1如果为null,就发生空指针异常了,不会进入equals方法//p1如果不为null,一个非空对象与一个null一定是不相等,就返回falseSystem.out.println(p1.equals("张三"));//p1是Person类型的,“张三"是String类型,类型不同,返回falseSystem.out.println("=======================");Integer i = 1;Integer j = 1;System.out.println(i == j);//trueInteger a = 200;Integer b = 200;System.out.println(a==b);//falseSystem.out.println(a.equals(b));//true//Integer重写了equals方法,比较两个包装类对象的数据值System.out.println("===================");Scanner input = new Scanner(System.in);System.out.print("请输入姓名:");String name = input.next();//判断输入的姓名是否是张三System.out.println(name == "张三");System.out.println(name.equals("张三"));//String类重写了equals方法//结论:以后凡是引用数据类型,包括字符串,包装类,你自己写的类的对象比较是否相等//都不要用==,而是用equals方法input.close();}
}

示例代码4:hashCode

package com.atguigu.object;public class TestHashCode {public static void main(String[] args) {System.out.println("Aa".hashCode());//2112System.out.println("BB".hashCode());//2112System.out.println("Aa".equals("BB"));//falsePerson p1 = new Person("张三",23);Person p2 = new Person("张三",23);System.out.println(p1.hashCode());//24022543System.out.println(p2.hashCode());//24022543System.out.println(p1.equals(p2));//true}
}

三、native(了解)

在Object类中,我没看到了

public native int hashCode();
protected native Object clone() throws CloneNotSupportedException;

native:本地的,原生的。

在Java中,表示这个方法的方法体不是用Java语言实现的,而是调用底层的C或C++的代码。所以,在Java层面看不到它的方法体。

但是,在Java中你可以当成普通的Java方法一样调用,一样重写。


http://www.mrgr.cn/p/38263180

相关文章

js逆向实战之莫莫铺子sign参数解密

url: http://mmpz.ttzhuijuba.com/?r=/l&cids=1&site=classify&sort=0 分析过程抓取流量包。主要关注图中框起来这条流量包,因为这条流量包返回的是当前页面数据。该流量包的url地址有个加密的参数sign,目的就是找到sign参数的加密过程。按照常规思路会去搜索ur…

记一次new ArrayList导致的cpu飙升问题排查

参考:https://mp.weixin.qq.com/s/8JDPOAvmKYP8JZxau45hdw前言当时场景正常的jvm监控曲线图产生问题的jvm监控曲线图具体分析结束语昨天线上容器突然cpu飙升,也是第一次排查这种问题所以记录一下~ 前言 首先问题是这样的,周五正在写文档,突然收到了线上报警,发现cpu占用达到…

Kafka 架构深入探索

目录 一、Kafka 工作流程及文件存储机制 二、数据可靠性保证 三 、数据一致性问题 3.1follower 故障 3.2leader 故障 四、ack 应答机制 五、部署FilebeatKafkaELK 5.1环境准备 5.2部署ELK 5.2.1部署 Elasticsearch 软件 5.2.1.1修改elasticsearch主配置文件 5.2…

安卓APP脱壳的本质以及如何快速发现ART下的脱壳点

参考:https://bbs.kanxue.com/thread-254555.htm拨云见日:安卓APP脱壳的本质以及如何快速发现ART下的脱壳点我在文章《FART:ART环境下基于主动调用的自动化脱壳方案》中简单对当前的几个脱壳方法进行了总结,然而并没有对每一种的具体原理进行分析。同时,在文章《FART正餐前…

力扣HOT100 - 114. 二叉树展开为链表

解题思路&#xff1a; class Solution {List<TreeNode> list new ArrayList<>();public void flatten(TreeNode root) {recur(root);for (int i 1; i < list.size(); i) {TreeNode pre list.get(i - 1);TreeNode cur list.get(i);pre.left null;pre.right…

冰达ROS机器人快速使用指南

欢迎来到《冰达ROS机器人极简使用指南》 Q&#xff1a;这份教程适合谁&#xff1f; A&#xff1a;适合完全0基础新手&#xff0c;需要快速跑起来机器人的基本功能。也适合技术大佬需要快速的了解冰达ROS机器人的使用方法。 Q&#xff1a;这份教程内容很少&#xff0c;是不是…

百度的代码,Comate写了27%。诚邀你来测评,获取丰厚好礼!

4月16日,在Create 2024百度AI开发者大会上发表的《人人都是开发者》主题演讲中,李彦宏指出: “百度每天新增的代码中,已经有27%是由Comate生成的。” 是的!Comate被老板表扬啦!Baidu Comate智能代码助手,和百度的工程师们共同完成了27%的代码! 而现在,Comate还走入了喜…

图表开发控件JointJS携全新4.0版本助力轻量开发

JointJS 和JointJS的v4.0版本正式发布&#xff0c;作为图表库的首个无依赖版本&#xff0c;备受期待&#xff01;新版本经过精心打磨&#xff0c;摆脱了jQuery、Backbone和Lodash的依赖&#xff0c;使得库更加精简且核心功能不变。此次慧都与JointJS厂商合作&#xff0c;携手带…

6. JSP详解

1. 什么是JSP 全称为:Java Server Pages Java服务器端页面,也和Serlvet一样,用于动态Web技术!JSP中的内容就是html,但是能够嵌套java语言 HTML只给用户提供静态数据2. JSP原理服务器内部工作 tomcat中有一个work目录 IDEA中使用Tomcat的会在IDEA的tomcat中生产一个work目录…

【计算机网络】MAC地址简介

MAC&#xff08;Medium Access Control&#xff09;&#xff0c;即媒介访问控制&#xff0c;是计算机网络通信中的重要概念。每个NIC&#xff08;Network Interface Card&#xff09;&#xff0c;即网络适配器&#xff0c;都具有独自且不变的MAC地址&#xff08;烧录的&#xf…

vis.js关系图

代码案例<!DOCTYPE html> <html lang="en"><head><title>Network</title><scripttype="text/javascript"src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script><styl…

代码随想录算法训练营第四十六天| LeetCode139.单词拆分

一、LeetCode139.单词拆分 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/0139.%E5%8D%95%E8%AF%8D%E6%8B%86%E5%88%86.html 状态&#xff1a;已解决 1.思路 单词明显就是物品&#xff0c;字符串s明显就是背包&#xff0c;那么问题就变成了物品能不能把背…

梦境绘师:揭秘生成对抗网络(GAN)的魔法

梦境绘师&#xff1a;揭秘生成对抗网络&#xff08;GAN&#xff09;的魔法 1 引言 在今日的深度学习领域&#xff0c;生成对抗网络&#xff08;GAN&#xff09;已成为一项无人能外的技术&#xff0c;以其独特的数据生成能力俘获了无数研究者和工程师的心。这项技术不仅在理论上…

Qt静态编译后使用QtCipherSqlitePlugin静态编译库

Qt静态编译后使用QtCipherSqlitePlugin静态编译库 Qt静态编译后使用QtCipherSqlitePlugin静态编译库语文功底不好,标题起的有点绕口,解释一下:就是我使用的Qt是Qt5.15.2静态编译包(要Qt静态编译文件这里下载:QT5.15.2静态编译包下载 - koomee - 博客园 (cnblogs.com)…

jmeter:测试片段使用的踩坑点

1.坑点:测试片段保存后含有两层【测试片段】,这样引用测试片段是不会成功的,检查方法:打开测试片段看看是否只有一个层级测试片段 2.测试片段的正确使用步骤方法1:选中多个请求或者配置元件>鼠标右键,保存为测试片段(测试实施过程中最常用的方法)方法2:添加测试片…

自学编程两个月,现在我月入 4 万元

这个外国小哥叫 Nico,他一开始是个编程小白,后来把自己关在房间里花了两个月时间学会了编程,如今正在开发一款名为 Talknotes 的应用,可以将语音备忘录转化为结构化的内容,月收入 5000 美元。Nico 从高中毕业就开始创业,大学只上了一个月就退学了,他尝试了很多方向,最终…

echarts折线图使用dataZoom,切换数据时渲染异常,出现竖线bug

今天做项目遇到一个省份过多时,要加滚动条的需求。但是切换数据的时候,出现上图所出现的问题。经查资料,发现可以设置一个属性来解决这个问题。 filterMode: empty dataZoom: {show: this.xiaonengXData.length>12?true:false, // 为true 滚动条出现realtime: this…

ElasticSearch有账号密码时: kibana配置

上一篇文章我们介绍过ElasticSearch关闭账号密码的的方式&#xff1a; config/elasticsearch.yml文件中 xpack.security.enabled: false 当我们关闭 账号密码&#xff0c;kibana是可以直接访问ElasticSearch的。 真实项目中&#xff0c;我们是不允许数据库裸跑的&#xff0c;所…

01 背包的变形

01 背包的变形,退背包的思想消失之物 链接:https://www.luogu.com.cn/problem/P4141 题目描述 ftiasch 有 \(n\) 个物品, 体积分别是 \(w_1,w_2,\dots,w_n\)。由于她的疏忽,第 \(i\) 个物品丢失了。 “要使用剩下的 \(n-1\) 物品装满容积为 \(x\) 的背包,有几种方法呢?”—…

百兆集成网络链接器911105A

百兆集成网络链接器&#xff08;有时也称为百兆网卡&#xff09;是一种硬件设备&#xff0c;主要用于计算机与计算机网络之间的高速数据传输。它的主要功能包括&#xff1a; 1. 高速数据传输&#xff1a;百兆集成网络链接器支持100Mbps的数据传输速率&#xff0c;比之前的以太…