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

一、异常

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.hqwc.cn/news/643700.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS - 多线程的安全隐患

文章目录 iOS - 多线程的安全隐患1. 卖票案例2. 多线程安全隐患的解决方案2.1 iOS中的线程同步方案2.2 同步方案的使用2.2.1 OSSpinLock2.2.1.1 使用方法&#xff1a;2.2.1.2 案例 2.2.2 os_unfair_lock2.2.2.1 使用方法&#xff1a;2.2.2.2 案例 2.2.3 pthread_mutex2.2.3.1 使…

OceanBase诊断调优 】—— 如何快速定位SQL问题

作者简介&#xff1a; 花名&#xff1a;洪波&#xff0c;OceanBase 数据库解决方案架构师&#xff0c;目前负责 OceanBase 数据库在各大型互联网公司及企事业单位的落地与技术指导&#xff0c;曾就职于互联网大厂和金融科技公司&#xff0c;主导过多项数据库升级、迁移、国产化…

mongodb 安装问题

1. mongodb启动时显示 Illegal instruction (core dumped) mongodb 5.0之后(包括5.0) 开始使用需要使用 AVX 指令集 2.启动时报错 ERROR: child process failed, exited with 1 通过指令 bin/mongod --repair 查看报错信息 根据报错信息进行修改 3. 配置服务器添加节点时…

图像处理之模板匹配(C++)

图像处理之模板匹配&#xff08;C&#xff09; 文章目录 图像处理之模板匹配&#xff08;C&#xff09;前言一、基于灰度的模板匹配1.原理2.代码实现3.结果展示 总结 前言 模板匹配的算法包括基于灰度的匹配、基于特征的匹配、基于组件的匹配、基于相关性的匹配以及局部变形匹…

TDSQL手动调整备份节点或冷备节点

一、背景描述 近期TDSQL数据库备份不稳定&#xff0c;有些set实例的备份任务未自动发起。经排查分析&#xff0c;存在多个set实例容量已经超过TB级别&#xff0c;且冷备节点都是同一台。因此&#xff0c;需要手动将当前备份节点改到其他备节点&#xff0c;开启增量备份&#x…

uniapp app权限说明弹框2024.4.23更新

华为上架被拒绝 用uni-app开发的app&#xff0c;上架华为被拒&#xff0c;问题如下&#xff1a; 您的应用在运行时&#xff0c;未见向用户告知权限申请的目的&#xff0c;向用户索取&#xff08;电话、相机、存储&#xff09;等权限&#xff0c;不符合华为应用市场审核标准。…

李沐57_长短期记忆网络LSTM——自学笔记

LSTM 1.忘记门&#xff1a;将值朝着0减少 2.输入门&#xff1a;决定不是忽略掉输入数据 3.输出门&#xff1a;决定是不是使用隐状态 !pip install --upgrade d2l0.17.5 #d2l需要更新首先加载时光机器数据集。 import torch from torch import nn from d2l import torch a…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(一)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 1 - 2节&#xff09; P1《课程介绍》 开场白&#xff0c;HarmonyOS 的一个简介&#xff0c;话不多说&#xff0c;直接看图吧&…

jar中没有主清单属性

运行springboot的jar 提示&#xff1a;jar中没有主清单属性 我的pom.xml 的plugins配置是下面 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version&g…

政安晨:【Keras机器学习示例演绎】(十二)—— 用利用 MIRNet 增强弱光图像效果

目录 简介 下载 LOL 数据集 创建 TensorFlow 数据集 MIRNet 模型 选择性核特征融合 双注意单元 多尺度残差块 MIRNet 模型 训练 推论 测试图像推理 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战…

tiktok如何影响用户行为的分析兼论快速数据分析的策略

tiktok如何影响用户行为的分析 快速数据分析的策略流程&#xff1a; 1.确定指标变量&#xff0c;也就确定了数据分析想要回答的问题。想回答不同的问题&#xff0c;就选择不同的指标变量。 变量筛选方法选出指标变量相关的变量&#xff1b; 针对筛选出的变量进行描述性分析和因…

研究发现:提示中加入数百个示例显著提升大型语言模型的性能

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…