黑马程序员——Java基础——继承与接口

来源:互联网 发布:python readline函数 编辑:程序博客网 时间:2024/06/08 19:57

点击打开链接 点击打开链接 点击打开链接 android培训、<a">点击打开链接 点击打开链接 java培训、期待与您交流!">点击打开链接 点击打开链接

继承(extends)的好处

l 提高了代码的复用性

l 让类与类之间产生了关系,有了这个关系,才有了多态的特性

注意:

l 千万不要为了获取其他类的功能简化代码而继承

l 必须是类与类之间有所属关系才继承,所属关系是is a.

   Java语言中:java只支持单继承不支持多继承,因为多继承容易带来安全隐患:当多个类中定义了相同的功能,当功能内容不同时,子类对象不确定运行哪一个。但Java保留了这种机制,用另一种体现形式来表示,叫多实现。

 

Java支持多层继承,也就是一个继承体系,如何使用一个Java体系中的功能?

  想要使用体系,先查阅父类体系的描述,因为父类中定义的是该体系中共性功能。通过了解共性功能就可以知道体系的基本功能,那么这个体系已经可以基本使用。

具体调用时要创建子类的对象,一是因为有可能父类不能创建对象,二是创建子类对象可以使用更多的功能,包括基本的、特有的。

  查阅父类功能     创建子类对象      使用功能

 

子父类成员的特点

1.变量的特点:  super:代表父类对象的引用

                this:代表本类对象的引用

  如果子父类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this,访问父类中的同名变量,用super

2.子父类中函数的特点:当子类出现和父类一模一样的函数时,当子类对象调用函数,会运行子类函数的内容,如同父类的函数被覆盖一样,这种情况是函数的另一个特性:重写(覆盖)。

 当子类继承父类,沿袭了父类的功能到子类中,但子类虽具备该功能,但功能内容却和父类不一致,这时没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。

Super.父类函数名():用于扩展功能。

注意事项:

子类覆盖父类,必须保证子类的权限>=父类权限,才可以覆盖,否则编译失败。

静态只能覆盖静态。

重名与重载的区别:

重载只看同名函数的参数列表

重写:子父类方法要一模一样,int speak()void speak()是不一样的,不能覆盖

 

3.子父类中的构造函数

    特点:在对子类对象进行初始化时,父类构造函数先运行,因为子类构造函数第一行有一条隐式语句super(),会访问父类中空参数的构造函数,而且子类中所有构造函数默认第一行都是super().

为什么子类一定要访问父类中的构造函数?

    因为父类中的数据子类可以直接获取,所以子类对象建立时,需要先查看父类是如何对这些数据进行初始化的,所以子类对象初始化时,要先访问一下父类中的构造函数。

    如果要访问父类中指定构造函数,可以通过手动定义super()语句的方式来指定。Super语句一定要放在构造函数第一行。

    当父类中没有空参数的构造函数时,子类必须手动通过superthis语句形式来指定要访问的父类中的构造函数。

子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。

子类中至少会有一个构造函数会访问父类中的构造函数。

 

final 关键字,修饰符

修饰类,方法、变量

final修饰的类不可以被继承,为了避免被继承,被子类复写功能

final修饰的方法不会被复写

final修饰的变量是一个常量,只能赋值一次即可修饰成员变量,又可修饰局部变量

  在描述事物时,一些数据的出现是固定的,这是为了增强阅读性,都给这些值起个名字方便阅读,而这个值不需要改变,所以加final修饰,作为常量,常量的书写规范是所有字母都大写,如果由多个单词组成,单词间通过下划线连接。

内部类定义在类中的局部位置时,只能访问局部被final修饰的局部变量。

 

abstract抽象的,看不懂的 修饰类和方法

  当多个类中出现相同功能,但功能主体不同,这时可以进行向上抽取,只抽取功能定义而不抽取功能主体。

抽象方法:被abstract修饰的方法

抽象类的特点:

l 抽象方法一定定义在抽象类中

l 抽象方法和抽象类都必须被abstract修饰

l 抽象类不可以用new创建对象,因为调用抽象方法无意义,

l 抽象类中的方法要被使用,必须由子类复写所有的抽象方法,建立子类对象调用。如果子类只是复写了部分抽象方法,那么该子类还是一个抽象类。

l 抽象类和一般类没有太大的不同,该如何描述事物就如何描述事物,只不过,该事物出现了一些看不懂的东西,这些不确定的部分,也是该事物的功能,需要明确出现,但是无法定义主体,通过抽象方法来表示。

 

抽象类与一般类的区别:

l 抽象类比一般类出现了抽象函数。就是类中可以定义抽象方法,作用是不让该类建立对象

l 抽象类不可以实例化

l 抽象类可以不定义抽象方法,这样做仅仅不让该类建立对象。

 

此处插入Test5

/*例:假如我们在开发一个系统时需要对员工进行建模,员工包含3个属性:姓名、工号及工资,  经理也是员工,出了含有员工的属性外,另外还有一个奖金属性,  请使用继承的思想设计出员工类和经理类,要求类中提供必要的方法进行属性访问。  思路:     这个模型中包含两个类,普通员工类和经理类,两个类中有共性的东西:姓名、工号、工资          但也有各自的特点,例如都会工作,但工作的内容不同,这时可以进行向上抽取出一个员工类,  工作方法需要抽象,所以定义抽象类  */class Test5 {public static void main(String[] args) {ptemployee p= new ptemployee("fdf","1255",12);Manager m=new Manager("fdf","1255",12.5,12.3);p.work();m.work();}}//抽象员工基类abstract class Employee{     //含有姓名、工号及工资 private String name; private String id; private double pay;//构造函数,对象一初始化就有姓名、工号及工资Employee(String name,String id,double pay){ this.name=name; this.id=id; this.pay=pay; } //抽象工作方法 public abstract void work();}//普通员工类继承员工类class ptemployee extends Employee{//重写工作方法public void work(){System.out.println("pt....work");}ptemployee(String name,String id,double pay){super(name,id,pay);}}//经理类继承员工类class Manager extends Employee{   //特有的奖金属性   private double bonus;   Manager(String name,String id,double pay,double bonus)   {        super(name,id,pay);this.bonus=bonus;   }   //重写工作方法public void work(){System.out.println("manager....work");}}


 

例:获取一段程序运行的时间System.currentTimeMillis()Test6

 

//子类继承获取时间类class Test6 extends GetTime{public static void main(String[] args) {//子类一初始化就会计算出自个复写的runcode()代码的运行时间Test6 t=new Test6();}//复写父类的抽象方法public void runcode(){for(int i=0;i<600;i++){System.out.print("libin");}}} //抽象的获取时间类abstract class GetTime { long start,end; //获取时间的方法,加上final,不允许子类复写。final GetTime() {        start=System.currentTimeMillis();runcode();end=System.currentTimeMillis();System.out.println("程序运行时间:"+(end-start)+"毫秒"); } //抽象的方法,子类必须复写,定义自个需要计算出时间的运行代码public abstract void runcode(); }


模板方法:在定义功能时,功能的一部分是确定的,但是有一部分不确定,确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去,由该类的子类去完成。

  

接口:是一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。

格式: interface {}

接口中的成员修饰符是固定的。其成员都是public的。

成员常量:public static final

成员函数:public abstract

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

 

implements 实现

    接口是不可以创建对象的,因为有抽象方法,需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实例化,否则子类是一个抽象类。

接口可以被类多实现,一个类可以实现多个接口,用,号隔开

接口与接口之间有继承关系,能有多继承。

 

接口的特点:

l 接口是对外暴露的规则

l 接口是程序的功能扩展

l 接口可以用来多实现

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

l 接口与接口之间可以有继承关系,能有多继承。

 

多态:事物存在的多种体现形态。

多态的体现

  父类的引用指向了自己的子类对象。

 Animal c = new cat();

父类的引用也可以接受自己的子类对象。

1.多态的前提

 必须是类与类之间有关系,要么继承,要么实现

通常还带有一个前提,存在覆盖

2.多态的好处

多态的出现大大的提高了程序的扩展性

3.多态的弊端

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

 

Animal a=new Cat();类型提升,向上转型

Cat c=(Cat)a;向下转型,强制将父类的引用转成子类类型。不能将父类对象转成子类类型,能转的是父类应用指向自己的子类对象时,该应用可以被提升,也可以被强制转换。

多态自始至终都是子类对象在做着变化。

 

instanceof 关键字

a instanceof cat   判断所属类型

多态的应用

 

多态的出现在代码中的特点

在多态中非静态成员函数的特点:

l 在编译时期,参阅应用类型所属的类中是否有调用方法,如果有编译通过,如果没有,编译失败。

l 在运行时期,参阅对象所属类中是否有调用方法。

l 成员函数在多态调用时,编译看左边,运行看右边。

在多态中,成员变量的特点

无论编译或运行都参考左边(引用型变量所属类)

在多态中,静态成员函数的特点:无论编译或运行,都参考左边。

 

Object

   是所有对象的直接或间接父类。该类中定义的是所有对象(包括数组)都具备的功能。

方法摘要

protected Objest    clone()   创建并返回此对象的一个副本

     boolean      equals(Object obj)  指示其他某个对象是否与此对象“相等”

protected  void    finalize()   当垃圾回收器确定不存在该类对象的更多引用时,由对象的垃圾回收器调用此方法

Class<?>    getClass() 返回此object的运行时类

int hashCode()  返回该类对象的哈希码值

void notify()  唤醒此对象监视器上等待的单个线程

void   notifyAll()  唤醒在此对象上监视器上等待的所有线程

String   toString()  返回该对象的字符串表示

void   wait()  其他线程在调用此对象的notify()方法或notifyAll()方法前,导致当前线程等待。

void wait(long timeout)  其他线程在调用此对象的notify()方法或notifyAll()方法,或其他某个线程中断当前线程,或者已经超过某个实际时间量前,导致当前线程等待。

 

内部类

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

访问特点:

l 内部类可以直接访问外部类中的成员,包括私有成员。之所以可以直接访问外部类中的成员,是因为内部类中持有外部类的引用,格式:外部类名.this

l 而外部类要访问内部类的成员必须要建立内部类的对象。

 

访问格式

    当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中建立内部类对象。

格式

   外部类名.内部类名 变量名=new 外部类对象.内部类对象;

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

当内部类在成员位置上,就可以被成员修饰符修饰,比如privatestatic

当内部类被static修饰后,只能访问外部内的静态成员,出现了访问局限。

访问static 内部类的非静态成员:new Outer.Inner().function();

访问static内部类的静态成员:Outer.Inner.function();

 

注意:当内部类中定义了静态成员,该内部类必须是static的。

      当外部内中静态方法访问内部类时,内部类也必须是静态的。

 

当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事务在使用外部事物的内容。

 

内部类定义在局部时

1.不可以被成员修饰符修饰

2.可以直接访问外部内中的成员,因为还持有外部内的引用

 但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

 

匿名内部类:内部类的简写格式

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

2.匿名内部类的格式:new 父类或者接口(){定义子类的内容}

3.其实匿名内部类就是一个匿名子类对象,带内容的对象

4.匿名内部类中定义的方法最好不超过3个。

 

0 0
原创粉丝点击