黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

时间:2022-04-29 00:31:32

第一讲  多态

1、  定义

可以理解为事物存在的多种体现形态。

在java中,当函数的功能内容不确定时,可以将此方法定义为抽象方法,让其子类去实现。当子类对象不同时,调用同一个函数名,会执行不同的函数体,得到不同的结果,从而体现了多态性。

2、  多态的体现形式

  • 父类的引用指向了自己的子类对象:Fu f = new Zi();
  • 父类的引用也可以接受自己的子类对象;

        黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常              

3、  多态的前提条件

  • 必须是类与类之间有关系,要么继承,要么实现(接口);
  • 函数之间存在覆盖(重写);

4、  多态的好处

大大的提高了程序的扩展性。——当子类对象增加时,尽可能的少该代码。

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

5、  多态缺陷

  提高了扩展性,但只能使用父类的引用访问父类中的成员。父类的引用不能访问子类中的成员。

  如下,父类的引用an1访问了子类特有方法kanjia();

  黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

6、  子父类类型转换

  Fu f = new Zi();————类型自动提升,向上转型,将子类型转成父类型。

  Zi z = (Cat) f ; ————强制将父类的引用转成子类类型,向下转型。

  注意:不能将父类型对象转成子类型。

7、  多态的应用

建立两个类:基础班学生 和 高级班学生,都有学习、睡觉功能。要求将这两类事物进行抽取。

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

8、  多态的出现,代码中的特点——多态使用的注意事项

  1)  多态中非静态成员函数的特点

    编译时期:参阅引用类型变量所属的类中是否有调用的方法,若有,编译通过,否则编译失败。因为:编译时,对象还没被创建,父      类和子类还没有建立关系。

    运行时期:参阅对象所属的类中是否有调用的方法,若有,则执行对象所属类中的功能,否则,执行父类中的功能。

    总结:成员函数在多态调用时,编译看左边(引用类型),运行看右边(对象所属的类)。

  2)  多态中成员变量的特点

    无论编译还是运行,都参考左边(引用型变量所属的类。如果引用型变量所属的类中没有此成员变量,则编译失败。运行时,也会调用引用型变量所属类中的变量。

    在多态中访问子类变量方法:当需要访问子类中的成员变量时,可以用强制类型转换,将父类型的引用强制转换成子类型:zi x = (zi)y,其中y代表指向子类型的父类型的应用变量

  3)  多态中,静态成员函数的特点

    无论编译还是运行,都参考左边(引用型变量所属的类)。

    原因:非静态方法和静态在内存中存储的位置不同,非静态方法区中有两个引用(this和super),而静态方法区中只有类名引用.

 

第二讲  Object

1、  概念

  Object是所有对象的直接或间接父类。该类中定义的肯定是多有对象都具备的功能。

2、  Object类应用

  Object类中已经提供了对对象是否相同的比较方法equals(),如果自定义类中也有比较相同的功能,没有必要重新定义,只要沿袭父类中的功能,建立自己特有的比较内容即可——这就是覆盖。

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

 

 

第三讲  内部类

1、  定义

2、  访问规则

  1)  内部类可以直接访问外部类中的成员,包括私有的,因为此时,内部类处于成员位置上,可以任务是外部类中的一个成员,内部类中持有了一个外部类的引用,格式:Outer.this.x——这里的this代表的是内部类对象。这就是内部类能够直接访问外部类成员的原因。

  2)  外部类要访问内部类,就必须建立内部对象:

    Inner inner = new Inner();

  3)  其他外部类访问内部类的方式

    当内部类定义为非私有,可以在外部其他类中直接建立内部类对象进行访问,格式如下:

      Outer.Inner  inner = new Outer().new Inner();

    当内部类在成员位置上时,可以被成员修饰符锁修饰

            如,private修饰:将内部类在外部类进行封装,只能外部类访问;

    Static 修饰:内部类就具备了static的特性。此时,内部类只能访问外部类中的static成员,出现了访问局限。

    外部其他类访问static修饰的内部类非静态成员方法如下:

    ————new Outer.Inner().function();——Inner类是Outer类的静态成员,可以直接用类名调用。

           外部其他类直接访问static修饰的内部类的静态成员方法如下:

           ————Outer.Inner.function();——静态成员可以直接被类名调用。

    注意:当内部类中定义了静态成员,该内部类必须是静态的;当外部类中的静态方法访问内部类时,内部类也必须是静态的。

    ——一个大原则:静态只能访问静态成员。

  内部类在局部位置上时:

    不能被static修饰;

    可以访问外部类中的成员,因为还持有外部类中的引用。但是不能访问它所在的局部中的变量,只能访问被final修饰的局部变量。

如下:a 只有被final修饰后,才能被内部类访问。

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

如下,内部类被定义在了局部位置上。系统默认给内部类一个外部类的引用Outer.this

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

  总结:不管内部类定义在成员位置还是局部位置上,外部类需要内部类对象才能访问内部类中成员,内部类得到了外部类对象(系统默认提供外部类引用Outer.this)才能访问外部类成员。

3、  匿名内部类

定义:匿名内部类其实就是内部类的简写格式。

定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

 

第四讲  异常

1、  定义

异常:程序运行时出现的不正常情况。

异常由来:问题也是现实生活中的一个具体的事物,也可以通过java类的形式进行描述,并封装成对象,即,对不正常情况进行描述后的对象体现。

异常划分:严重问题 和 非严重问题。

严重问题:java通过Error类进行描述,对于Error一般不编写针对性的代码进行处理。

非严重问题:java通过Exception进行描述,可以使用针对性的处理方式进行处理。

其中,Error和Exception同为Throwable的子类。

2、  异常处理

  异常处理目的:把异常处理掉,让try外面的后续语句继续执行。若不处理,程序就会被停下来,不处理后续语句。

原因:如果虚拟机调用的程序没有的处理此项异常的功能,该异常会被抛给虚拟机,而虚拟机处理异常的默认机制是:直接把此程序停掉。

异常处理代码格式如下:

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

处理异常有两种方式:

  第一种是:向上(向调用者)抛出异常;

  第二种是:自己内部捕获异常并处理。

3、  多异常处理

  1)  函数中只要有异常发生,函数就停下了;

  2)  被调用函数声明了几个异常,调用者就对应有几个catch块,如果多个catch块中的异常出现继承关系,父类异常catch块必须放在最下面;

  3)  若程序出现了被调用函数所声明以外的异常,最好将此异常抛给虚拟机,将程序停掉;

  4)  建议进行catch处理时,catch中一定要定义具体的处理方式,而不是简单的打印异常。异常信息可以输出到硬盘中相应的文档中,方便后续异常查找及处理;

4、  自定义异常

  可以自定义java机制中没有定义的异常。

  注意:Java不会自动识别自定义异常,所以,需要手动建立自定义异常对象并抛出(java本身定义的异常可以被默认抛出)

  1)  自定义异常信息

    因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息通过super语句传递给父类,然后就可以直接通过  getMessage方法获取自定义的异常信息了

  2)  自定义异常特点

    必须继承Exception。因为:异常体系有一个特点:异常类和异常对象都被抛出,它们都具备可抛性,这是Throwable体系中独有的特点。只有这个体系中的类和对象才可以被throws和throw操作。

5、  Throws和throw的区别

  1)  Throws使用在函数上;Throw使用在函数内;

  2)  Throws后面跟着异常类,可以多个,用逗号隔开;Throw后面跟着异常对象;

  注意:Throw下面不应跟其他语句,因为异常抛出后,下面语句不会再执行。Throw和return作为函数的结束标识。但是系统退出(System.exit(0))时不会执行。

6、  RuntimeException

定义:函数内抛出异常,则函数上必须声明抛出异常,否则编译不通过,但RuntimeException不需要函数声明抛出。如果函数上声明了该异常,调用者可以不用进行异常处理,编译也能通过。

RuntimeException不需要在函数上声明的原因是:此异常不需要调用者处理。此类异常发生时,希望程序停止,因为在程序运行时出现了无法继续运算的情况,希望停止程序后,对代码进行修正。

7、  异常覆盖时的特点

异常在子父类覆盖中的体现:

  1)子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖类方法只能抛出父类的异常或者该异常的子类,或者不抛出异常;

  2)如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集;

  3)如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须要进行try处理,绝对不能抛出。

 

 

知识点总结

1、  继承类和实现接口

父类中定义了某类事物的通用属性,而接口中往往定义的是某类事物的扩展功能。

2、  Throw 和 throws的用法

  1)  Throw定义在函数内,用于抛出异常对象;

  2)  Throws定义在函数上,用于抛出异常类,可以抛出多个,用逗号隔开;

3、  异常分两种:编译时异常 和 运行时异常

  1)  编译时被检测的异常:函数内被抛出,则函数上必须要声明,且在调用者中必须处理或向外抛出;

  2)  编译时不被检测的异常(即,运行时异常,RuntimeException)

函数上不需要声明,不需要调用者进行处理。

4、  异常处理中finally块中语句特点

  1)  finally中定义的通常是:关闭资源代码。因为资源必须被释放。

  2)  finally只有一种情况不会执行:当执行到System.exit(0);时,finally中的语句不会执行。