day10.final-内部类-异常-Object类

  1. 课前回顾:
  2. 1.抽象:abstract
  3. 2.注意:
  4. 抽象方法所在的类一定是抽象类
  5. 抽象类中不一定非得有抽象方法(还可有构造,成员变量,成员方法)
  6. 抽象类不能直接new对象,需要创建子类对象来实现
  7. 子类重写抽象父类时,需要重写父类中所有的抽象方法,除非子类也是一个抽象类
  8. 3.多态:
  9. 前提:
  10. 必须有子父类继承关系还有就是接口实现关系
  11. 必须有方法重写,没有方法重写多态没有意义
  12. 父类引用指向子类对象
  13. 好处:
  14. 当参数传递时,传递父类类型,到时候传递实参时,可以传递任何这个父类的子类,扩展性强
  15. 弊端:
  16. 不能调用子类特有功能
  17. 转型:
  18. 向上转型:默认的
  19. 向下转型:强转 ->调用子类的特有方法
  20. 关键字:instanceof 判断类型
  21. 对象名 instanceof 类型 ->判断对象是否属于这个类型
  22. 4.接口:标准
  23. 关键字: interface(接口) implenments(实现)
  24. 成员:
  25. jdk7:
  26. 抽象方法:带abstract 不写也有
  27. 成员变量:public static final ->常量 接口名直接调用
  28. jdk8:
  29. 默认方法:带default的方法->可重写可不重写
  30. 静态方法:带static的方法->接口名直接调用
  31. 5.接口和抽象类的区别:
  32. 相同点:
  33. 两者都是作为继承的顶端
  34. 不同点:
  35. 抽象类一般作为父类使用:可以抽取共有的变量,成员方法等
  36. 接口作为一个功能的标准:抽取的都是方法
  37. 6.接口特点:
  38. 接口可以多继承
  39. 一个类可以实现一个或者多个接口
  40. 一个类还可以继承一个父类的同时实现一个或者多个接口
  41. 7.final关键字:
  42. a.被final修饰的类不能被继承
  43. b.被final修饰的方法不能被重写 不能和abstract一起使用
  44. 今日重点:
  45. 1.会使用final关键字
  46. 2.会使用匿名内部类
  47. 3.会使用throws处理异常
  48. 4.会使用try...catch处理异常
  49. 5.分清楚什么是编译时期异常,什么是运行时期异常

第一章.final关键字

  1. 1.概述:最终的,最后的

1.final修饰类

  1. 1.格式:
  2. public final class 类名{
  3. }
  4. 2.特点:
  5. final修饰的类,不能被继承的
  1. public final class Animal {
  2. public void eat(){
  3. System.out.println("动物都要吃饭");
  4. }
  5. }
  1. public class Dog extends Animal{//因为Animal类被final修饰了,所以不能被继承
  2. }

2.final修饰方法

  1. 1.格式:
  2. 修饰符 final 返回值类型 方法名(参数){
  3. 方法体
  4. return 结果
  5. }
  6. 2.特点:
  7. final修饰的方法不能被重写的
  8. 3.注意:
  9. finalabstract不能同时修饰方法
  1. public abstract class Animal {
  2. public final void eat(){
  3. System.out.println("动物都要吃饭");
  4. }
  5. /*
  6. final和abstract不能一起修饰方法,因为冲突
  7. final修饰的方法不能被重写
  8. abstract修饰的方法必须要被重写
  9. 所以冲突
  10. */
  11. //public final abstract void drink();
  12. }
  1. public class Dog extends Animal{
  2. /*
  3. 被final修饰的方法不能被重写
  4. public void eat(){
  5. }
  6. */
  7. }

3.final修饰局部变量

  1. 1.格式:
  2. final 数据类型 变量名 =
  3. 2.特点:
  4. final修饰的局部变量,不能被二次赋值,可以理解为是一个常量
  1. public class Test01 {
  2. public static void main(String[] args) {
  3. final int i = 10;
  4. //i = 20;final修饰的变量不能被二次赋值
  5. final int j;
  6. j = 100;//属于给变量j第一次赋值
  7. //j = 200;//属于给j第二次赋值
  8. }
  9. }

4.final修饰对象

  1. 1.格式:
  2. final 类型 对象名 = new 类名()
  3. 2.特点:
  4. final修饰的对象地址值不能改变,但是对象的属性值可以变
  1. public class Person {
  2. private String name;
  3. private int age;
  4. public Person() {
  5. }
  6. public Person(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. }
  1. public class Test01 {
  2. public static void main(String[] args) {
  3. final Person p1 = new Person("柳岩", 36);
  4. System.out.println(p1);//地址值
  5. //p1 = new Person("金莲",32);p1被final修饰,地址值直接定死,不能改变地址值
  6. p1.setName("杨幂");
  7. p1.setAge(32);
  8. System.out.println(p1.getName()+"..."+p1.getAge());
  9. }
  10. }

5.final修饰成员变量

  1. 1.格式:
  2. final 数据类型 变量名 =
  3. 2.特点:
  4. final修饰的成员变量不能被二次赋值
  5. final修饰的成员变量需要手动赋值
  1. public class Person {
  2. final String name = "大郎";
  3. public Person() {
  4. //name = "大郎";
  5. }
  6. /* public Person(String name) {
  7. this.name = name;
  8. }*/
  9. public String getName() {
  10. return name;
  11. }
  12. /* public void setName(String name) {
  13. this.name = name;
  14. }*/
  15. }

小结:

final修饰类:不能被继承

final修饰方法:不能被重写

final修饰局部变量:不能被二次赋值

final修饰对象:地址值不能变,属性值可以改变

final修饰成员变量:需要手动赋值 不能被二次赋值

第二章.内部类

  1. 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使 用内部类。
  2. Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者 称为外部类。
  3. public class A{
  4. class B{
  5. }
  6. }
  7. B就是A的内部类
  8. A就是B的外部类
  9. Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完 整的名称。
  10. Inner class的名字不能与包含它的外部类类名相同;
  11. 分类:
  12. 成员内部类(static成员内部类和非static成员内部类)
  13. 局部内部类
  14. 匿名内部类

1 静态成员内部类

  1. 1.格式:直接在声明内部类的时候加上static关键字即可
  2. 类名{
  3. static class 类名{
  4. }
  5. }
  6. 2.注意:
  7. a.类中可以定义属性,方法,构造等
  8. b.静态内部类可以被final abstract修饰
  9. final修饰之后,不能被继承
  10. abstract修饰之后,不能被new
  11. c.静态内部类不能调用外部类的非静态成员(静态不能直接调用非静态)
  12. d.还可以被四种权限修饰符所修饰
  13. 3.如何调用静态内部类成员
  14. 外部类类名.静态内部类类名 对象名 = new 外部类类名.静态内部类类名()
  1. public class Person {
  2. public void eat(){
  3. System.out.println("人要吃饭");
  4. }
  5. //静态成员内部类
  6. static class Heart{
  7. public void jump(){
  8. System.out.println("心会跳");
  9. //new Person().eat();在静态内部类中调用外部类中非静态成员
  10. }
  11. }
  12. }
  1. public class Test01 {
  2. public static void main(String[] args) {
  3. //外部类类名.静态内部类类名 对象名 = new 外部类类名.静态内部类类名()
  4. Person.Heart heart = new Person.Heart();
  5. heart.jump();
  6. }
  7. }

2 非静态成员内部类

  1. 1.格式:直接在声明内部类的时候不加上static关键字即可
  2. 类名{
  3. class 类名{
  4. }
  5. }
  6. 2.注意:
  7. a.类中可以定义属性,方法,构造等
  8. b.静态内部类可以被final abstract修饰
  9. final修饰之后,不能被继承
  10. abstract修饰之后,不能被new
  11. c.非静态内部类能调用外部类的非静态成员(非静态能直接调用非静态)
  12. d.还可以被四种权限修饰符所修饰
  13. 3.如何调用非静态内部类成员
  14. 外部类.内部类 对象名 = new 外部类().new 内部类()
  1. public class Person {
  2. public void eat(){
  3. System.out.println("人要吃饭");
  4. }
  5. //非静态成员内部类
  6. class Heart{
  7. public void jump(){
  8. System.out.println("心会跳");
  9. //eat();在非静态内部类中调用外部类中非静态成员
  10. }
  11. }
  12. }
  1. public class Test01 {
  2. public static void main(String[] args) {
  3. //外部类类名.静态内部类类名 对象名 = new 外部类类名.静态内部类类名()
  4. /*Person.Heart heart = new Person.Heart();
  5. heart.jump();*/
  6. Person.Heart heart = new Person().new Heart();
  7. heart.jump();
  8. }
  9. }

如果外部类的成员变量和内部类的成员变量以及局部变量重名,该如何区分?

  1. public class Person {
  2. String name = "柳岩";
  3. class Heart{
  4. String name = "心脏";
  5. public void display(String name){
  6. System.out.println(name);//局部变量name->就近原则
  7. System.out.println(this.name);//内部类成员变量 name
  8. System.out.println(Person.this.name);//外部类成员变量 name
  9. }
  10. }
  11. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. //外部类.内部类 对象名 = new 外部类().new 内部类()
  4. Person.Heart heart = new Person().new Heart();
  5. heart.display("涛哥");
  6. }
  7. }

3 局部内部类

  1. 1.可以在方法中,代码块中,构造方法中使用
  1. public class Person {
  2. public void method(){
  3. //局部内部类
  4. class Heart{
  5. public void jump(){
  6. System.out.println("心在跳");
  7. }
  8. }
  9. new Heart().jump();
  10. }
  11. }
  12. public class Test01 {
  13. public static void main(String[] args) {
  14. Person person = new Person();
  15. person.method();
  16. }
  17. }
  1. public interface USB {
  2. public abstract void open();
  3. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. USB usb = method();//多态
  4. usb.open();//调用的是实现类重写的方法
  5. }
  6. public static USB method(){
  7. class Mouse implements USB{
  8. @Override
  9. public void open() {
  10. System.out.println("鼠标打开了");
  11. }
  12. }
  13. return new Mouse();
  14. }
  15. }

4.匿名内部类(重点)

  1. 1.是内部类的简化写法。它的本质是一个`带具体实现的` `父类或者父接口的` `匿名的` **子类对象**。开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作,
  2. a. 定义实现类
  3. b. 重写接口中的方法
  4. c. 创建子类对象
  5. d. 调用重写后的方法
  6. 我们的目的,最终只是为了调用方法,那么能不能简化一下,把以上四步合成一步呢?匿名内部类就是做这样的快捷方式。
  7. 2.可以定义的位置:可以在方法中,代码块中,构造方法中使用->匿名内部类也是局部的
  8. 3.格式:
  9. new 父类/接口(){
  10. 重写方法
  11. }.重写的方法;
  12. 或者
  13. 父类类型/接口类型 对象名 = new 父类/接口(){
  14. 重写方法
  15. };
  16. 对象名.重写的方法;
  17. 4.注意:匿名内部类代表的是子类对象
  1. public interface USB {
  2. public abstract void open();
  3. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. Mouse mouse = new Mouse();
  4. mouse.open();
  5. System.out.println("================");
  6. new USB(){
  7. @Override
  8. public void open() {
  9. System.out.println("鼠标开启啦");
  10. }
  11. }.open();
  12. System.out.println("================");
  13. USB usb = new USB(){
  14. @Override
  15. public void open() {
  16. System.out.println("鼠标开启啦啦啦啦啦了");
  17. }
  18. };
  19. usb.open();
  20. }
  21. }

2.2 匿名内部类复杂用法_当参数传递

  1. public interface USB {
  2. public abstract void open();
  3. }
  1. public class Test02 {
  2. public static void main(String[] args) {
  3. //method(new Mouse());
  4. //使用匿名内部类传递
  5. method(new USB() {
  6. @Override
  7. public void open() {
  8. System.out.println("鼠标开启啦");
  9. }
  10. });
  11. }
  12. public static void method(USB usb){//USB usb = mouse
  13. usb.open();
  14. }
  15. }

day10[final_内部类_异常_Object类] - 图1

2.3 匿名内部类复杂用法_当返回值返回

  1. public interface USB {
  2. public abstract void open();
  3. }
  1. public class Test03 {
  2. public static void main(String[] args) {
  3. USB usb = method();
  4. usb.open();//重写的open
  5. }
  6. public static USB method(){
  7. //return new Mouse();
  8. return new USB() {
  9. @Override
  10. public void open() {
  11. System.out.println("键盘开启");
  12. }
  13. };
  14. }
  15. }

day10[final_内部类_异常_Object类] - 图2

第三章.异常

1.异常介绍

  1. 1.已经见过的异常:
  2. ArrayIndexOutOfBoundsException:索引越界异常
  3. NullPinterException:空指针异常
  4. ClassCastException:类型转换异常
  5. 2.概述:异常在java中其实是一个一个的类,一旦出现,代表我们的代码有问题
  6. 3.异常体系:如下图

day10[final_内部类_异常_Object类] - 图3

  1. public class Demo01Exception {
  2. public static void main(String[] args) throws FileNotFoundException {
  3. int[] arr = new int[3];
  4. //System.out.println(arr[120]);//运行时期异常
  5. //FileInputStream fis = new FileInputStream("day10\\1.txt");//编译时期异常
  6. //错误
  7. int[] arr1 = new int[999999999];
  8. System.out.println(arr1[9]);
  9. }
  10. }

2.异常出现的过程

day10[final_内部类_异常_Object类] - 图4

3.创建异常对象(了解)

  1. 1.格式:
  2. throw new 异常对象()->创建异常对象并抛出
  1. public class Demo03Exception {
  2. public static void main(String[] args) {
  3. String s = null;
  4. method(s);
  5. }
  6. public static void method(String s){
  7. if (s==null){
  8. //创建异常对象,throw代表抛出
  9. throw new NullPointerException("我的身体被掏空!");
  10. }
  11. System.out.println("哈哈哈哈");
  12. }
  13. }

4.异常处理方式(重点)

4.1 异常处理方式一_throws

  1. 1.格式:
  2. 在方法声明上->参数后面,方法体左半个大括号前面
  3. throws 异常
  1. public class Demo04Exception {
  2. public static void main(String[] args)throws FileNotFoundException {
  3. String s = "";
  4. method(s);
  5. System.out.println("涛哥涛哥涛哥涛哥");
  6. }
  7. public static void method(String s)throws FileNotFoundException{
  8. if (!s.endsWith(".txt")){
  9. //创建异常对象,throw代表抛出
  10. throw new FileNotFoundException("文件没找到!");
  11. }
  12. System.out.println("哈哈哈哈");
  13. }
  14. }

4.2 异常处理方式一_throws多个异常

  1. 1.格式:throws 异常,异常...
  2. 2.注意:
  3. a.如果要抛多个异常,且多个异常之间有子父类继承关系,我们只需要throws一个父类即可
  4. b.如果要抛多个异常,先抛子类,再抛父类
  5. c.如果我们不知道要抛具体什么异常,我们可以直接抛Exception
  1. public class Demo04Exception {
  2. public static void main(String[] args)throws Exception/*IOException*//*,FileNotFoundException*/ {
  3. String s = "";
  4. method(s);
  5. System.out.println("涛哥涛哥涛哥涛哥");
  6. }
  7. public static void method(String s)throws Exception/*IOException*//*,FileNotFoundException*/{
  8. if (s==null){
  9. //创建异常对象
  10. throw new IOException();
  11. }
  12. if (!s.endsWith(".txt")){
  13. //创建异常对象,throw代表抛出
  14. throw new FileNotFoundException("文件没找到!");
  15. }
  16. System.out.println("哈哈哈哈");
  17. }
  18. }

4.3 异常处理方式二_try…catch

  1. 1.格式:
  2. try{
  3. 可能会出现异常的代码
  4. }catch(异常 对象名){
  5. 异常的处理方式->将异常信息放到日志文件中
  6. }
  7. 2.注意:
  8. 如果try中的代码有问题,被catch到了,相当于代码变正常了,后续的代码还能继续执行
  9. 如果try中的代码有问题,没有被catch到,相当于没将代码处理,默认就会给jvm处理
  1. public class Demo06Exception {
  2. public static void main(String[] args) {
  3. String s = "";
  4. //添加功能
  5. try {
  6. add(s);
  7. } catch (FileNotFoundException e) {
  8. e.printStackTrace();
  9. }
  10. //删除功能
  11. System.out.println("删除");
  12. }
  13. public static void add(String s) throws FileNotFoundException {
  14. if (!s.endsWith(".txt")) {
  15. //创建异常对象,throw代表抛出
  16. throw new FileNotFoundException("文件没找到!");
  17. }
  18. }
  19. }

4.4 异常处理方式二_多个catch

  1. 1.格式:
  2. try{
  3. 可能会出现异常的代码
  4. }catch(异常 对象名){
  5. 异常的处理方式->将异常信息放到日志文件中
  6. }catch(异常 对象名){
  7. 异常的处理方式->将异常信息放到日志文件中
  8. }catch(异常 对象名){
  9. 异常的处理方式->将异常信息放到日志文件中
  10. }...
  11. 2.注意:
  12. a.如果catch的多个异常之间有子父类继承关系,只catch一个父类即可
  13. b.如果catch的多个异常之间有子父类继承关系,先catch子类,再catch父类
  14. c.如果catch的多个异常之间有子父类继承关系,只catch一个Exception即可
  1. public class Demo07Exception {
  2. public static void main(String[] args) {
  3. String s = "";
  4. //添加功能
  5. /*try {
  6. add(s);
  7. } catch (IOException e) {
  8. e.printStackTrace();//将异常具体信息打印到控制台上
  9. }catch (FileNotFoundException e){
  10. e.printStackTrace();//将异常具体信息打印到控制台上
  11. }*/
  12. /* try {
  13. add(s);
  14. } catch (IOException e) {
  15. e.printStackTrace();//将异常具体信息打印到控制台上
  16. }*/
  17. try {
  18. add(s);
  19. } catch (Exception e) {
  20. e.printStackTrace();//将异常具体信息打印到控制台上
  21. }
  22. //删除功能
  23. System.out.println("删除");
  24. }
  25. public static void add(String s) throws /*FileNotFoundException,*//*IOException*/Exception {
  26. if (s==null){
  27. throw new IOException();
  28. }
  29. if (!s.endsWith(".txt")) {
  30. //创建异常对象,throw代表抛出
  31. throw new FileNotFoundException("文件没找到!");
  32. }
  33. }
  34. }
  1. public class Demo08Exception {
  2. public static void main(String[] args) {
  3. String s = "";
  4. //添加功能
  5. try {
  6. String s1 = null;
  7. /*
  8. 出现空指针异常->NullPointerException
  9. 如果catch不到,相当于没有处理,后续代码会受到影响
  10. */
  11. System.out.println(s1.length());
  12. add(s);
  13. } catch (FileNotFoundException e) {
  14. e.printStackTrace();
  15. }
  16. //删除功能
  17. System.out.println("删除");
  18. }
  19. public static void add(String s) throws FileNotFoundException {
  20. if (!s.endsWith(".txt")) {
  21. //创建异常对象,throw代表抛出
  22. throw new FileNotFoundException("文件没找到!");
  23. }
  24. }
  25. }

5.finally关键字

  1. 1.finally:代表的是一定要执行的代码
  2. 2.用法:和try...catch结合使用
  3. try{
  4. 可能会出现异常的代码
  5. }catch(异常 对象名){
  6. 异常的处理方式->将异常信息放到日志文件中
  7. }finally{
  8. 一定要执行的代码
  9. }
  1. public class Demo09Exception {
  2. public static void main(String[] args) {
  3. String s = "";
  4. //添加功能
  5. try {
  6. String s1 = null;
  7. /*
  8. 出现空指针异常->NullPointerException
  9. 如果catch不到,相当于没有处理,后续代码会受到影响
  10. */
  11. System.out.println(s1.length());
  12. add(s);
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. }finally {
  16. System.out.println("我一定要执行");
  17. }
  18. //删除功能
  19. System.out.println("删除");
  20. }
  21. public static void add(String s) throws FileNotFoundException {
  22. if (!s.endsWith(".txt")) {
  23. //创建异常对象,throw代表抛出
  24. throw new FileNotFoundException("文件没找到!");
  25. }
  26. }
  27. }

注:快捷键

如果有编译时期异常:我们可以使用alt+回车->快速生成try…catch

如果有运行时期异常:我们可以选中->ctrl+alt+T

  1. public class Test01 {
  2. public static void main(String[] args) {
  3. int method = method();
  4. System.out.println(method);
  5. }
  6. private static int method() {
  7. try{
  8. String s = null;
  9. System.out.println(s.length());
  10. return 2;
  11. }catch (Exception e){
  12. e.printStackTrace();
  13. // System.out.println("我是catch");
  14. return 1;
  15. }finally {
  16. System.out.println("我一定要执行");
  17. //return 3;
  18. }
  19. }
  20. }
  1. 运行结果:
  2. 我一定要执行
  3. 1
  4. 如果finally中再写一个return 3执行结果为
  5. 我一定要执行
  6. 3

finally的使用场景:

  1. 关闭资源

当一个对象没有用时,GC(垃圾回收器)会将没有用的对象从内存中清理,释放内存

但是,有的对象GC清理不了,比如:IO流对象 Socket对象 数据库连接对象等,所以我们需要用完之后手动关闭资源,释放资源

所以,GC清理不了的对象,就需要我们再finally中手动清理

6.抛异常时注意的事项

  1. 1.问题:
  2. 父类中的方法抛了异常,那么子类重写方法之后要不要抛?
  3. 可抛可不抛
  4. 父类中的方法没有抛异常,那么子类重写方法之后要不要抛?
  5. 不抛

什么时候用try…catch 什么时候用throws

1.如果想不影响后面功能的执行,就可以用try…catch

2.如果方法之间有递进关系,我们可以先throws 但是到了最后一层,需要统一作用一个try…catch处理

day10[final_内部类_异常_Object类] - 图5

7.自定义异常

  1. 需求:完成一个注册案例,如果注册失败,抛出RegisterException,提示:该用户已经被注册
  1. 步骤:
  2. 1.定义一个字符串,表示已经注册过的用户名
  3. 2.创建Scanner,调用next(),表示要注册的用户名
  4. 3.和已有的用户名进行比较,如果内容一样,证明注册过了,显示注册失败,抛出注册失败异常
  5. 4.否则注册成功
  1. public class RegisterException extends Exception{
  2. public RegisterException() {
  3. }
  4. public RegisterException(String message) {
  5. super(message);
  6. }
  7. }
  1. public class Test {
  2. public static void main(String[] args) throws RegisterException {
  3. //1.定义一个字符串,表示已经注册过的用户名
  4. String username = "root";
  5. //2.创建Scanner,调用next(),表示要注册的用户名
  6. Scanner sc = new Scanner(System.in);
  7. System.out.println("请您输入要注册的用户名:");
  8. String name = sc.next();
  9. //3.和已有的用户名进行比较,如果内容一样,证明注册过了,显示注册失败,抛出注册失败异常
  10. if (name.equals(username)){
  11. throw new RegisterException("注册失败!");
  12. }else{
  13. //4.否则注册成功
  14. System.out.println("注册成功");
  15. }
  16. }
  17. }

1.随便一个类

2.如果继承Exception,此自定义异常类为编译时期异常

如果继承RuntimeExecption,此自定义异常类为运行时期异常

3.提供有参和无参构造,方便设置异常提示信息

8.打印异常信息的三个方法

  1. Throwable类中定义了一些查看异常信息的方法:
  2. - public String getMessage():获取异常的描述信息,原因(提示给用户的时候,就提示错误原因。
  3. - public String toString():获取异常的类型和异常描述信息(不用)。
  4. - public void printStackTrace():打印异常的跟踪栈信息并输出到控制台。
  1. public class Test02 {
  2. public static void main(String[] args) {
  3. String s = "";
  4. try {
  5. method(s);
  6. } catch (FileNotFoundException e) {
  7. //Throwable类中定义了一些查看异常信息的方法:
  8. //- public String getMessage():获取异常的描述信息,原因(提示给用户的时候,就提示错误原因。
  9. //System.out.println(e.getMessage());
  10. //- public String toString():获取异常的类型和异常描述信息(不用)。
  11. //System.out.println(e.toString());
  12. //- public void printStackTrace():打印异常的跟踪栈信息并输出到控制台。
  13. e.printStackTrace();
  14. }
  15. }
  16. private static void method(String s) throws FileNotFoundException {
  17. if (!s.endsWith(".txt")){
  18. throw new FileNotFoundException("文件找不到");
  19. }
  20. }
  21. }

第四章.Object类

  1. 1.概述:
  2. 所有的类的父类
  3. 2.如果一个类没有明确写明extends 父类 默认的父类就是Object
  4. 所有的类都会直接或者间接的去继承Object

1.Object类中的toString方法

  1. public String toString() {//返回该对象的字符串表示。
  2. return getClass().getName() + "@" + Integer.toHexString(hashCode());
  3. }
  4. 1.如果我们的类中没有重写toString,那么直接输出对象名时,默认会调用Object类中的toString方法,输出的就是地址值
  5. 2.如果我们的类中重写toString方法,默认会调用重写后的toString方法,所以我们重写之后,返回的应该是内容(属性值)
  6. 总结:
  7. 如果直接输出对象名,不想输出地址值的话,那么就在这个对象内部重写Object类中的toString方法,输出内容(和getxxx方法无关)
  1. public class Person {
  2. private String name;
  3. private int age;
  4. public Person() {
  5. }
  6. public Person(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Person{" +
  25. "name='" + name + '\'' +
  26. ", age=" + age +
  27. '}';
  28. }
  29. }

2.Object类中的equals方法

  1. Object类中的equals方法://判断两个对象是否相等
  2. public boolean equals(Object obj) {
  3. return (this == obj);
  4. }
  5. ==:针对于基本类型,比较的是值
  6. 针对于引用类型,比较的是地址值
  7. 1.如果一个对象没有重写equals方法,调用equals方法时,是调用的Object类中的equals方法,比较的是地址值
  8. 2.如果一个对象重写了equals方法,再比较地址值就没意义了,所以我们重写equals之后应该比较内容(属性值)
  1. public class Person {
  2. private String name;
  3. private int age;
  4. public Person() {
  5. }
  6. public Person(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Person{" +
  25. "name='" + name + '\'' +
  26. ", age=" + age +
  27. '}';
  28. }
  29. /*
  30. 问题1:如果传递的不是Person类型,向下转型会出现ClassCastException
  31. 解决问题1:类型判断
  32. 问题2:如果传递null咋整?
  33. 解决问题2:先做一个非空判断,如果是null直接返回false
  34. 问题3:如果传递自己呢?
  35. 解决问题3:如果传递同一个对象,直接返回 true
  36. */
  37. /* @Override
  38. public boolean equals(Object o) {//Object o = p2
  39. if (this==o){
  40. return true;
  41. }
  42. if (o==null){
  43. return false;
  44. }
  45. if (o instanceof Person){
  46. //向下转型
  47. Person p2 = (Person)o;
  48. return this.name.equals(p2.name) && this.age==p2.age;
  49. }
  50. return false;
  51. }*/
  52. @Override
  53. public boolean equals(Object o) {
  54. if (this == o) return true;
  55. if (o == null || getClass() != o.getClass()) return false;
  56. Person person = (Person) o;
  57. return age == person.age &&
  58. /*
  59. Objects.equals也是比较的字符串内容
  60. 可以防止空指针异常
  61. */
  62. Objects.equals(name, person.name);
  63. }
  64. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. Person p1 = new Person("柳岩", 36);
  4. Person p2 = new Person("柳岩", 36);
  5. System.out.println(p1.equals(p2));
  6. ArrayList<String> list = new ArrayList<>();
  7. System.out.println(p1.equals(list));
  8. System.out.println(p1.equals(null));
  9. System.out.println(p1.equals(p1));
  10. /* String s = null;
  11. boolean b = s.equals("哈哈哈");
  12. System.out.println(b);*/
  13. boolean result = Objects.equals(null, "abc");
  14. System.out.println(result);
  15. }
  16. }

总结:

1.如果直接输出对象名不是地址值的话,而是属性值->重写toString

2.如果比较的时候想比较内容而不是地址值->重写equals