黑马程序员——继承和多态

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------

一,继承的概述

· 多个类中存在相同属性和行为时,将这些内容抽取到一个单独的类中,那么多个类无需再定义这些属性和行为,只要继承单个那个类即可

· 多个类可以称为子类,单独这个类称为父类或超类

· 子类可以直接访问父类中的非私有的属性和行为

· 通过extends关键字让类与类之间产生继承关系:class SubDemo extends Demo(){}

· 继承的出现提高了代码的复用性

· 继承的出现让类与类之间产生了关系,提供了多态的前提

二,继承的特点

· java只支持单继承,不支持多继承:即一个类只能有一个父类,不可以有多个父类

· java支持多层继承。

· 定义继承需要注意:

1. 不要仅为了获取其他类中某个功能而去继承

2. 类与类之间要有所属(is a)关系,即:子类是父类的一种

· 代码:学生和工人都有姓名年龄的属性。并且学生和工人都是人的一种,有所属关系

class Person {
   String name;
   int age;
}
class Student extends Person{
   public void study(){
      System.out.println(“学习”);
   }
}
class Worker extends Person{
   public vod work(){
      System.out.println(“工作”);
   }
}

三,super关键字

· super和this的用法相同

· this代表本类应用

· super代表父类应用

· 当子类出现同名成员时,可以用super进行区分

· 子类要调用父类构造函数时,可以使用super语句

四,函数覆盖(Override)

· 子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重写或者复写

· 父类中的私有方法不可以被覆盖

· 在子类覆盖方法中,继续使用被覆盖方法可以通过super函数获取,代码示例:

class Tel {
   void show() {
      System.out.println(“Number”);
   }
}
class NewTel {
   void show() {
      super.show();//通过super关键字直接调用父类方法
      System.out.println(“Name”);
   }
}
· 覆盖注意事项:

1. 覆盖时,子类方法权限一定要大于等于父类方法权限

2. 静态只能覆盖静态

· 覆盖的应用:当子类需要父类功能,而功能主体有自己特有的内容时,可以复写父类的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容

· 重载和重写:重载只看同名函数参数列表;重写要子类的方法和父类的方法一模一样

五,子类的实例化过程

· 子类中所有的构造函数默认都会访问父类中空参数构造函数

· 因为每一个构造函数的第一行都有一条默认的语句super();

· 子类会具备父类中的数据,所以要先明确父类是如何对这些数据进行初始化的

· 当父类中没有空参数构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函数

六,final关键字

· final可以修饰类,方法,变量

· final修饰的类不可以被继承

· final修饰的方法不可以被覆盖

· final修饰的变量只是一个常量,只能被赋值一次

· 内部类只能访问被final修饰的局部变量

七,抽象类

1,抽象类的概述

· 抽象定义:抽象就是从多个事物中将共性的,本质的内容抽取出来。例:狼和狗都是犬科,犬科就是抽象出来的概念

· 抽象类:java类可以定义没有方法体的方法,该方法具体实现由子类的完成,该方法称为抽象方法,包含抽象方法的类就是抽象类

· 抽象方法的由来:多个对象都具备相同的功能,但是功能具体内容有所不同,那么抽取过程中,只抽取定义了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。例:狼和狗虽然都有吼叫的方法,可以吼叫的内容不一样。所有抽象出来的犬科虽然都有吼叫的功能,但是并不明确吼叫的细节

2,抽象类的特点

· 抽象类和抽象方法必须用abstract关键字类修饰

· 抽象方法只有方法声明,没有方法主体,定义在抽象类中。

格式:修饰符 abstarct 返回值类型 函数名(参数列表)

· 抽象类不可以被实例化,也就是不可以用new创建对象,原因如下:

a. 抽象类是具体事物抽取出来的,本身是不具体的,没有对应的实例。例如:犬科是一个抽象的概念,真正存在的是狼和狗

b. 而且抽象类即使创建了对象,调用抽象方法也没有意义

· 抽象类通过子类实例化,而子类需要覆盖抽象类中所有的抽象方法后才可以创建对象,否则该子类也是抽象类

· 特殊:抽象类中不定义抽象方法,这样做仅仅是为了不让该类建立对象

八,接口

· 格式:interface{}

· 接口中的成员修饰符是固定的:

a. 成员常量:public static final

b. 成员函数:public abstarct

· 接口的出现将”多继承“通过另外一种形式体现出来,即”多实现“

· 子类实现接口的关键字是”implements“

· 接口用来扩展功能

· 特点:

a. 接口是对外暴露的规则

b. 接口是程序的功能扩展

c. 接口可以用来多实现

d. 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口

e. 接口与接口之间可以有继承关系

九,多态

· 定义:某一类事物的多种存在形态

· 体现:父类或者接口的引用指向或者接口自己的子类对象

· 作用:多态的存在提高了程序的扩展功能性和后期可维护性

· 前提:

1. 需要存在继承或者实现关系

2. 需要有覆盖操作

· 特点:

1. 成员函数:

a. 编译时:要查看变量所属的类是否有所调用的成员

b. 在运行时,要查看对象所属的类是否有调用的成员

2. 成员变量和static成员函数:只看变量所属的类

· 代码示例:

//有cat类和dog类
//cat对应的类应该是cat类型
Cat cat = new Cat();
//通过Cat又是Animal的一种,是其子类,所以:
Animal animal = new Cat();
//即父类引用指向子类对象

扩展:

Object类:

类层次的根类,是所有对象的直接或者间接的父类。该类中定义的肯定都是所有对象都具备的功能。所以当自己定义的类中,定义的方法,在Object类中有的时候,并且自己希望有特有的功能时,直接复写就可以了。

内部类:

· 将一个类定义在另一个类里面,对里面那个类就称为内部类(内置类、嵌套类)

· 访问特点:

1. 内部类可以直接访问外部类中的成员,包括私有成员

2. 而外部类要访问内部类中的成员必须要建立内部类对象

· 当描述事物时,事物的内部还有事物,该事物用内部类来描述

· 当内部类定义在成员上时:

1. 可以被private static 成员修饰符修饰。访问一般内部类成员的方法:Outer.Inner in = new Outer().new Inner();

2. 被static修饰的内部类只能访问外部类中的静态成员

a) 访问被static修饰的内部中非静态成员的方法:new Outer().Inner().function();

b) 访问被static修饰的内部中静态成员的放啊:Outer().Inner().function();

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

· 当内部类定义在局部位置上时:

1. 也可以直接访问外部类中的成员

2. 同时可以访问所有局部中的局部变量,但必须是final修饰的

匿名内部类:

· 就是内部类的简写

· 前提:内部类可以继承或者实现一个外部类或者接口

· 格式:new 外部类名或者接口名(){覆盖类或者接口中的代码,也可以是自定义内容}

· 简单理解为:就是建立一个带内容的外部类或者接口的子类匿名对象,而且这个对象会有点胖

· 匿名内部类,定义的方法数量最好不要超过三个。超过三个时就不建议采用匿名内部类的方法了

异常:

· 异常的体系:Throwable中有2个子类异常,一类是Error:通常出现重大问题如运行类不存在或者内存溢出等,不编写针对代码对其进行处理;一类是Exception:在运行时出现的一些情况,可以通过try catch finally处理

· Exception和Error的子类的后缀名都是其父类名

· Throwable中的方法:

getMessage(); //获取异常信息,返回字符串
toString(); //获取异常类名和异常信息,返回字符串
printStackTrace(); //获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void
printStackTrace(PrintStream s); //通常用该方法将异常内容保存在日志文件中,以便查阅

· throw和throws:

1. throws用于标识函数暴露出来异常

2. throw用于抛出异常对象

3. throws和throw的区别:

a) throws用在函数上,后面跟异常类名

b) throw用在函数内,后面跟异常对象

· 异常处理代码:

try{
   需要检测的代码;
} catch(Exception e) {
   异常处理代码;
} finally {
   一定会执行的代码;//Finally代码块只有一种情况不会被执行。就是在之前执行了System.exit(0);
}
· 自定义异常:自定义类继承Exception或者其子类即可,通过构造函数定义异常信息

· 异常细节:

1. RuntimeException以及其子类如果在函数中被throw抛出,可以不用在函数上声明

2. 一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或者异常的子类

3. 如果父类抛出多个异常,那么重写的方法必须抛出那些异常的一个子集,不能抛出新的异常

你可能感兴趣的:(java,黑马程序员)