黑马程序员-------继承

时间:2022-03-11 00:43:03

           -----------android培训java培训、java学习型技术博客、期待与您交流!-----------

Java的继承

1.继承的概述

继承:

1.提高了代码的复用性。

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

注意:千万不要为了获取其他类的功能,简化代码而继承。

必须是类与类之间有所属关系才可以继承。所以关系is a.

java 语言中:java只支持单继承,不支持多继承。

当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一个。

因为多继承容易带来安全隐患。

但是java保留了这种机制。并用另一种体现形式来完成表现。多实现。

java支持多层继承。也就是一个继承体系

如何使用一个继承体系中的功能呢?

想要使用体系,先查询体系父类的描述。因为父类中定义的是该体系*性的功能。

通过了解共性功能,就可以知道该体系的基本功能。

那么这个体系已经可以基本使用了。

 

 

那么在具体实现时,要创建子类的对象,为什么呢?

一是因为有可能父类不能创建对象。

二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。

简单一句话:查阅父类功能,创建子类对象使用功能。

大家记住:java中一个孩子只有一个父亲,不允许有多个父亲。

子父类出现以后,类成员的特点:

类中成员:

1.变量。

如果子类中出现非私有的同名成员变量时,

子类要访问本类中的变量,用this

子类要访问父类中的同名变量,用super

super的使用和this的使用几乎一致。

super代表的是父类对象的引用。

2.子父类中函数。

当子类出现和父类一模一样的函数时,

当子类调用该函数,会运行子类函数的内容。

这种情况是函数的另一个特性:重写(覆盖)。

 

当子类继承了父类,沿袭了父类的功能,到子类中,

但是子类虽具备该功能,但是功能内容却和父类不一致,

这时,没有必要定义新功能,而是使用覆盖的特性,

保留父类的功能定义,并重写功能内容。

覆盖:

1.子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。

2.静态只能覆盖静态。

记住大家:

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

重写:子父类方法要一模一样。包括返回值类型。

3.子父类中构造函数。

3.子父类中的构造函数。

在对子类对象进行初始化时,父类的构造函数也会运行。

那是因为子类的构造函数默认的第一行有一条隐式的语句 super();

super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super();

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

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

所以子类在对象初始化时,要先访问一下父类中的构造函数。

如果访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。

注意:super语句一定定义在子类构造函数的第一行。

子类的实例化过程.

结论:

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

因为子类每一个构造函数内的第一行都有一句隐式super();

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

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

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

为什么super构造函数 和this构造函数不能同时定义在一行?

 答:因为他们都必须写在第一行。

为什么要写第一行?

因为初始化动作要做。

final关键字

final关键字

final :最终。作为一个修饰符。

1.final可以修饰类,方法,变量。

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

3.final修饰的方法不可以被复写。

4.final修饰的变量是一个常量。只能被赋值一次。既可以修饰成员变量。又可以修饰局部变量。

当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值其个名字。方便阅读。

而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所以字母都大写,如果有多个单词组成。

单词间通过_连接。

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

 

抽象类

当多个类中出现相同功能,但是功能主体不同。

这时可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。

抽象:看不懂

抽象类的特点:

1.抽象方法一定在抽象类中。

2.抽象方法和抽象类都必须被abstract关键字修饰。

3.抽象类不可以用new创建对象。因为调用抽象方法没有意义。

4.抽象类中的抽象方法要被使用,必须有子类复写其所有的抽象方法后,建立子类对象调用。

如果子类覆盖部分抽象方法,那么该子类还是一个抽象类。

抽象类和一般类没有太大的不同。

该如何描述事物,就如何描述事物只不过,该事物出现了一些看不懂的东西。

这些不确定的东西,也就是该事物的功能,需要明确出现,但是无法定义主体。

通过抽象方法来表示。

抽象类比一般类多了抽象函数。就是在类中可以定义抽象方法。

抽象类不可以实例化。

特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

模板设计方式:

需求:获取一段程序运行的时间。

原理后期程序开始和结束的时间并相减即可。

获取时间:system.currentTimeMills();   current卡润特

当代码完成优化后,就可以解决这类问题。

这就是模板设计方式。

什么是模板方法呢?

在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分。

那么这时就将不确定的部分暴露出去。由子类去完成。

接口:

接口:初期理解,可以认为是一个特殊的抽象类。

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

class :用于定义类

interface:用于定义接口。

接口定义时,格式特点:

1.接口中常见的定义:常量,抽象方法。

2.接口中的成员都有固定修饰符。

常量:public static final

方法: public abstract

记住:接口中的成员都是public修饰的。

接口:是不可以创建对象的,因为有抽象方法。

需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类可以实例化。

否则子类是一个抽象类。

接口可以被类多实现,,也是对多继承不支持的转换形式。java支持多实现。

implements 实现。 

接口的特点:

1.接口是对外暴露的规则。

2.接口是程序功能扩展。

3.接口可以用来多实现。

4.类与接口直接是实现关系,而且类可以继承一个类的同时实现多个接口。

5.接口与接口直接可以是继承的关系。

降低偶合性。

多态

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

1.多态的体现:

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

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

instanceof:实例 关键字

 

2.多态的前提:

必须是类与类之间有关系。要么继承,要么实现。通常还有一个前提:存在覆盖。

3.多态的好处:

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

通常还有一个前提:存在覆盖。

4.多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员。

5.多态的应用:

Animal a=new Cat();//类型提升,向上转型。把猫提升为了动物。

//如果想要调用猫的特有方法是,如何操作?

//强制将父类的引用转成子类类型,向下转型。

Cat c = (cat)a;

c.catchMouse();

/*

千万不要出现这样的操作,就是将父类的对象转成子类对象。

我们能转换的是父类的引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。

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

//Animal a = new Animal();这样做是错误的,千万不要出现这样的操作,就是将父类的对象转成子类对象。

//Cat c = (cat)a

*/

6.多态的出现代码中的特点(多态使用的注意事项)

在多态中成员函数的特点(父类引用指向自己的子类):

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

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

简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

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

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

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

无论编译和运行,都参考左边。

Object:是所有对象的直接或者间接父类,传说中的上帝。

该类中定义的肯定是所有对象都具备的功能。

Object类中已经提供了对对象是否相同的比较方法。equals:比较对象的地址值。

如果自定义类中也有比较相同的功能,没有必要重新定义。

只要沿袭父类中的功能,建立自己的特有比较内容即可。这就是覆盖。

内部类:

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

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

2.外部类要访问内部类,必须建立内部类对象。

类能不能被私有修饰?

答:可以,内部类可以被私有修饰。当内部类在外部类的成员位置时,可以。

访问格式:

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

可以直接建立内部类对象。

格式 :外部类名.内部类名  变量名 =  外部类对象.内部类对象;

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

2.当内部类在成员位置上,就可以被成员修饰符所修饰。

比如,private:将内部类在外部类中进行封装。

static:内部类就是具备static的特性。

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

在外部其他类中,如何直接访问static内部类的非静态成员呢?

     new Outer.Inner().function();

在外部其他类中,如何直接访问static内部类的静态成员呢?

       Outer.Inner.funtion();

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

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

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

因为内部事物在使用外部事物的内容。

内部类定义在局部时,

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

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

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

匿名内部类:

1.匿名内部类其实就是内部类的简写格式。

2.定义匿名颞部类的前提:

内部类必须是继承一个类或者实现接口。

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

4.其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。

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

异常处理机制

异常:就是程序在运行时出现不正常情况。

java在设计异常体系时,将容易出现情况都封装成了对象。

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

其实就是java对不正常情况进行描述后的对象体现。

对于严重的,java通过Error类进行描述。

对于Error一般不编写针对性的代码对其进行处理。

对与非严重的,javaException类进行描述。

对与Exception可以使用针对性的处理方式进行处理。

无论Error或者Exception都具有一些共性内容。

比如不正常的情况信息,引发原因等。

Throwable

      |------Error

 

  |------Exception

2.异常的处理:

一般处理:

try

{

需要被检测的代码

}

catch(异常类 变量)

{

处理异常的代码;(处理方式)

}

finally

{

一定执行的语句;

}

3.对捕获的异常对象进行常见方法的操作。

String getmessage():获取异常信息.

在函数上声明异常。

便于提高安全性,让调用者进行处理。不处理编译失败。

对异常的处理:

1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体。

2.对方声明了几个异常,就对应有几个catch块。不要定义多余的catch块。

如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。

建立在进行catch处理时,catch中一定要定义具体处理方式。

不要简单定义一句e.printStackTrace().

也不要简单的就书写一条输出语句。

因为项目中会出现特有的问题,

而这些问题并未被java所描述并封装对象。

所以对于这些特有的问题可以按照java对问题封装的思想。

将特有问题,进行自定义的异常封装。

自定义异常:

需求:在本程序中,对于除数是-1,也视为是错误的是无法进行运算的。

那么需要对这个问题进行自定义的描述。

当在函数内部出现了throw抛出异常对象,那么就必须要给出对应的处理动作。

要么在内部try catch处理。

要么在函数上声明让调用者处理。

一般情况下,函数出现异常,函数上需要声明出来。

发现打印出的结果中只有异常的名称,却没有异常的信息。

因为自定义的异常并未定义信息。

 

如何定义异常信息呢?

因为父类中已经把异常信息的操作都完成了。

所以子类只要在构造时,将异常信息传递给父类通过super语句。

那么就可以直接同getMessage方法获取自定义的异常信息。

自定义异常:

必须是自定义类继承Exception.

继承Exception原因:

异常体系有一个特点:因为异常类和异常对象都被抛出。

他们都具可抛性。这个可抛性是Throwable这给体系中独有的特性。

只有这个体系的类和对象才可以被throws throw 操作。

只有这个体系中的类和对象才可以被throwsthrow操作。

throwsthrow的区别

throws使用在函数上。

throw使用在函数内。

throws后面跟的异常类。可以是多个。用逗号隔开。

throw后面跟的是异常对象。

Exception中有一个特殊的子类异常RuntimeException运行时异常。

如果在函数内部抛出该异常,函数上可以不声明,编译一样通过。

如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过。

之所以不用在函数声明,是因为不需要让调用者处理。

当该异常发生,希望程序停止。因为在运行时,出现了无法继续运行的情况,希望停止程序后,对代码进行修正。

自定义异常时:如果该异常的发生,无法再继续进行运算。

就让自定义异常继承RuntimeExcepton.

对于异常分两种:

1.编译时被检测的异常。(编译时异常。Exception以及他的子类必须在函数上声明。是可以处理的异常。

2.要么抛异常,要么try catch处理)

2.编译时不被检测的异常(运行时异常。RuntimeException以及其子类)

3.finally代码块:定义一定执行的代码。

4.通常用于关闭资源。

第一个格式:

try{} catch(){} 

第二个格式:

try{} catch(){} finally{}

第三个格式:

try{] finally{}

记住一点:catch是用于处理异常。如果没有catch就代表异常没有被处理过,

如果该异常时检测是异常。那么必须声明。

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

1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者改异常的子类。

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

3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。

如果子类方法发生异常,就必须进行try处理。绝对不能抛。

----------------------------------------------

异常:

异常是什么?是对问题的描述。将问题进行对象的封装。

异常体系:

    Throwable

    |---Error

|---Exception

     |----RuntimeException

异常体系的特点:异常体系中所有类以及建立的对象都具备可抛性。

也就是说可以被throwthrows关键字所操作。

只有异常体系具备这个特点。

throw 和 throws 的用法:

throw 定义在函数内,用于抛出异常对象。

throws 定义在函数上,用于抛出异常类,用逗号隔开。

当函数内容有 throw 抛出异常对象,并未进行try处理,必须要在函数上什么,都在编译失败。

注意: RuntimeException 除外。也就是说,函数内如果抛出异常 RuntimeException 异常,函数上可以不用声明。

如果函数声明了异常,调用者需要进行处理。处理方式可以 throws try

-----------------------------------------

异常有两种:

编译时被检测异常:

该异常在编译时,如果没有处理(没有抛出也没有try),编译失败。

该异常被标识,代表这可以被处理。

运行时异常(编译时不检测)

在编译时,不需要处理,编译器不检查。

该异常的发生,建议不处理,让程序停止。需要对代码进行修正。

异常处理语句:

try

{

需要被检测的代码;

}

catch ()

{

处理异常的代码;

}

   finally

   {

   一定会处理的代码;

   }

有三个结合格式:

第一种格式:           第二种格式                      第三种格式

try                     try                               try

{                        {                                 {

}  }                                 }

catch ()               finally                           catch()

{                        {                                 {

}                        }                                 }

                                                         finally

                                                           }

                                                          {

                                               

注意;                  {

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

2.finally 只有一种情况不会执行。当执行到 System.exit(0); finally 不会执行。

----------------------------------------------------------

自定义异常:

定义继承 Exception 或者 RuntimeException

1.为了让自定义类具备可抛性。

2.让该类具备操作异常的共性方法。

当要定义异常的信息是,可以使用父类已经定义好的功能。

自定义异常信息传递给父类的构造函数。

class MyException extends Exception

{

MyException(String message)

{

super(message);

}

}

自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。

-----------------------------------------

异常的好处:

1.将问题进行封装。

    2.将正常流程代码和问题代码相分离,方便于阅读。

异常的处理原则:

1.处理方式有两种 try 或者 throws.

2.调用到抛出异常的功能时,抛出几个,就处理几个。

一个 try 对应 多个catch.

3.多个 catch ,父类的 catch 放到最下面。

4.catch 内,需要第一针对性的处理方式。不要简单定义printStackTrace 输出语句。

也不要不写。

当捕获到的异常,本功能处理不了时,可以继续在 catch 中抛出。

try

{

throw new AExcrption();

}

catch (AException e)

{

throw e;

}

如果该异常处理不了,但是不属于该功能出现的异常。

   可以将异常转换后,在抛出和该功能相关的异常。

   或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去。

当调用者知道。并处理。也可以将不会异常处理后,转换新的异常。

try

{

throw new AException();

}

catch (AEexception e)

{

//AException处理。

throw  new  BException();

}

比如,汇款的例子。

  异常的注意事项:

在子父类覆盖时:

1.子类抛出的异常必须是父类的异常的子类或者子集。

2.如果父类后者接口没有异常抛出是,子类覆盖出现异常,只能 try 不能抛。

参阅:

ExceptionTest.java 老师用电脑上课。

ExceptionTest.java 图像面积。

(package) 

1、对类文件进行分类管理 

2、给类提供多层命名空间 

3、写在程序的第一行 

4、类名的全称是 包名.类名 

5、包也是一种封装形式 

6、Javac -d . 类名.Java