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.mzph.cn/diannao/2716.shtml

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

相关文章

【AI写作】未来科技趋势:揭秘DreamFusion的革新力量

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

数据库之数据库恢复技术思维导图+大纲笔记

大纲笔记&#xff1a; 事务的基本概念 事务 定义 用户定义的一个数据库操作系列&#xff0c;这些操作要么全做&#xff0c;要么全不做&#xff0c;是一个不可分割的基本单位 语句 BEGIN TRANSACTION 开始 COMMIT 提交&#xff0c;提交事务的所有操作 ROLLBACK 回滚&#xff0c…

Centos之yum安装好玩的命令

1.会动的小火车 我在root下使用的 yum install sl.x86_64sl2.figlet yum install figlet.x86_64figlet 55553.cowsay会说话 yum install cowsay

防火墙详细讲解

目录 介绍 防火墙的特征 防火墙的组成 介绍 防火墙&#xff08;firewall&#xff09;是指一种计算机硬件和软件的结合&#xff0c;将内部网和公众访问网&#xff08;如Internet&#xff09;分开的方法&#xff0c;它实际上是一种隔离技术。防火墙主要由服务访问规则、验证工…

python数字验证码自动识别

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在网络上&#xff0c;许多网站和应用程序使用验证码&#xff08;Completely Automated Publ…

MYSQL 存储java.sql.Timestamp类型的数据时,mysql存储时间和java获取到的时间相差8小时

###JAVA JDBC驱动 com.mysql.cj.jdbc.DriverJDBC连接字符串 jdbc:mysql://127.0.0.1:3006/db?useUnicodetrue&characterEncodingUTF8&useLegacyDatetimeCodefalse&serverTimezoneUTCMySQL 时区 show global variables like “%time_zone%”; 问题分析 驱动…

网络安全之SQL注入漏洞复现(中篇)(技术进阶)

目录 一&#xff0c;报错注入 二&#xff0c;布尔盲注 三&#xff0c;sleep延时盲注 四&#xff0c;DNSlogs 盲注 五&#xff0c;二次注入 六&#xff0c;堆叠注入 总结 一&#xff0c;报错注入 报错注入就是在错误信息中执行 sql 语句&#xff0c;利用网站的报错信息来带…

【奶奶看了都会】用 AI做猫咪剧情短片保姆级教程

大家这段时间在刷短视频的时候&#xff0c;是不是经常会刷到那种猫咪剧情短片&#xff0c;配合喵喵喵......的魔性背景音乐&#xff0c;让人看了非常上头。最近这类视频在抖音、视频号、小红书上非常火&#xff0c;今天就来教大家如何制作。 1.GPT4账号准备 我们用到的AI生图…

应用于智能装备制造,钡铼IOy系列模块展现其强大的灵活性和实用性

随着科技的飞速发展&#xff0c;智能制造已经成为工业4.0时代的核心驱动力。在此背景下&#xff0c;钡铼技术推出的IOy系列模块以其独特的设计、卓越的性能以及无可比拟的灵活性与实用性&#xff0c;在智能装备制造领域展现出了强大的技术优势和应用价值。 首先&#xff0c;钡…

HTTP与SOCKS-哪种协议更适合您的代理需求?

网络代理技术是我们日常使用网络时必不可少的一项技术&#xff0c;它可以为我们提供隐私保护和负载均衡的能力&#xff0c;从而保证我们的网络通信更加安全和顺畅。而其中最主流的两种协议就是HTTP和SOCKS。虽然它们都是用于网络代理的协议&#xff0c;但在实际应用中却存在着一…

儿童护眼落地灯哪个牌子好?值得买的五款大路灯分享

近年来&#xff0c;随着近视问题日益严重&#xff0c;消费者越来越倾向于选购能够优化照明环境、减轻眼部压力的护眼落地灯。然而&#xff0c;市场上的护眼落地灯品质良莠不齐&#xff0c;许多品牌为了追求低廉价格和扩大市场份额&#xff0c;不惜采取模仿甚至抄袭的方式&#…

MySQL主从结构搭建

说明&#xff1a;本文介绍如何搭建MySQL主从结构&#xff1b; 原理 主从复制原理如下&#xff1a; &#xff08;1&#xff09;master数据写入&#xff0c;更新binlog&#xff1b; &#xff08;2&#xff09;master创建一个dump线程向slave推送binlog&#xff1b; &#xff…

TIMEDAY·腾讯智慧出行技术开放日:发布汽车行业大模型、升级智能汽车云

4月24日&#xff0c;北京车展前夕&#xff0c;在“2024 TIME DAY腾讯智慧出行技术开放日”上&#xff0c;腾讯发布了汽车行业大模型“全域智能”方案&#xff0c;覆盖汽车研发、生产、营销、服务、企业协同等五大核心场景。与此同时&#xff0c;腾讯发布了在智能汽车云、智能座…

C++中的程序流程结构

一、选择结构 1.1 if语句 作用&#xff1a;执行满足条件的语句 if语句的三种形式 单行格式if语句多行格式if语句多条件的if语句 #include <iostream> using namespace std;int main(){//选择结构 单行if语句//用户输入分数&#xff0c;如果分数>600,视为考上一本大…

【SpringBoot实战篇】获取用户详细信息-ThreadLocal优化

1 分析问题 对token的解析当初在拦截器中已经写过。期待的是在拦截器里写了&#xff0c;在其他地方就不写了&#xff0c;应该去复用拦截器里面得到的结果 2 解决方式-ThreadLocal 2.1提供线程局部变量 用来存取数据: set()/get()使用ThreadLocal存储的数据, 线程安全 2.2过程图…

OneFlow新概念清单,AI深度学习的革命性突破(AI写作)

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

路由过滤与引入

1、实验拓扑 2、实验要求 1、按照图示配置 IP 地址&#xff0c;R1&#xff0c;R3&#xff0c;R4 上使用 1oopback口模拟业务网段 2、运行 oSPF&#xff0c;各自协议内部互通 3、R1 和 R2 运行 RIPv2,R2&#xff0c;R3和R4在 RIP 和 oSPF 间配置双向路由引入,要求除 R4 上的业务…

mPEG-Cyanur,Methoxy PEG Cyanur具有良好的生物相容性

【试剂详情】 英文名称 mPEG-Cyan&#xff0c;mPEG-Cyanur&#xff0c;Methoxy PEG Cyanur&#xff0c;Methoxy PEG Cyan 中文名称 聚乙二醇单甲醚三聚氯氰&#xff0c;甲氧基-聚乙二醇-氰尿酸 外观性状 由分子量决定&#xff0c;固体或者粘稠液体。 分子量 0.4k&#x…

自己写的爬虫小案例

网址&#xff1a;aHR0cDovL2pzc2NqZ3B0Lmp4d3JkLmdvdi5jbi8/dXJsPS92aWV3L3dvcmtpbmdVbml0L3dvcmtpbmdVbml0Lmh0bWw 这串代码能够爬取勘察单位企业的详细信息。 import requests import time import csv f open(勘察单位公司信息.csv,w,encodingutf-8,newline) csv_writer …

从阿里云OSS迁移到AWS S3的步骤

随着企业数字化转型的加速,云计算成为企业IT基础设施不可或缺的部分。对象存储作为云计算的重要组成部分,为企业提供了可靠、安全、低成本的数据存储和管理解决方案。在选择对象存储服务时,企业需要根据自身需求和发展战略来进行全面评估。我们九河云&#xff0c;获得AWS官方认…