黑马程序员_java基础部分_面相对象二

------- android培训java培训、期待与您交流! ----------

 

面向对象二

对多态,继承,接口,抽象类,异常类进行总结;

1.         通过创建相应子类的对象来获取对应接口引用;

用接口的引用来调用子类的方法;

2.         多态的体现

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

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

2),多态的前提

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

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

3),多态的好处

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

4),多态的弊端:

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

5),多态的应用

3.         多态的特点;

多态只能访问父类中的方法,并且访问的方法通常被覆盖了,这样运行的就是子类中的方法;

覆盖只运行子类中的方法;

4.         如果想要调用子类中的特有方法时,如何操作?

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

///Cat c = (Cat)a;

//c.catchMouse();

5.         if(a instanceof Cat)这个方法用于判断对象的类型;

6.         多态调用方法的规则;

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

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

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

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

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

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

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

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

Fu1 f = new Zi1();

调用的父类的变量;变量不存在覆盖;只看左面

System.out.println(f.num);

调用的子类的方法,因为覆盖;看右面;

f.method1();

虽然这个是覆盖,但是它是静态覆盖;它只看左面,跟变量一样。

f.method4();

Zi1 z1 = new Zi1();

想调用子类的静态方法,只有通过创建自己的对象去调用;

z1.method4();

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

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

Object类中已经提供了,对对象是否相同的比较方法。

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

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

8.         对继承的总结

一、特点:

提高了代码的复用性。

让类与类之间产生关系,是多态性的前提。

二、Java中的继承。

1java只支持单继承,不支持多继承。为啥呢?答案:因为继承了多个父类如果有相同方法时,子类对象不确定运行哪一个。

2Java还支持多层继承。A-->B--->C  原来可以形成继承体系。

要使用体系功能,"查阅父类功能,建立子类对象调用功能。"

注解:父类的由来其实是由事物中的共性内容不断向上抽取而来的。

所以父类中定义的是该体系中的最基本,最共性功能。

三、继承出现后,代码上也有一些特点:

1,变量。

当子父类中定义了相同的名称的成员变量,

子类要使用父类中的同名变量时,需要使用关键字super来区分。

一般不会出现这种情况,因为父类中有了,子类不需要定义。

而且父类定义时,一般变量都私有化。

2,函数。

子类可以直接访问父类中非私有的成员函数。

特殊情况:当子类中定义了与父类一模一样的方法时,会发生覆盖操作,大多指的是非静态方法。

 最终会运行子类的方法,父类相当于被覆盖了。

函数的另一个特性:覆盖(重写,复写)。

什么时候用啊?

当父类的功能要被修改时,不建议修改源码,因为是灾难。

只要通过一个类继承原有类,定义一个新的升级后的功能即可。

但是功能是相同的,只是实现方法改变,这是子类可以沿袭父类中的功能定义,

并重写功能内容。这就是覆盖。

覆盖很爽,但是有注意事项:

1)子类覆盖父类时,必须权限要大于等于父类权限。

2)静态不能覆盖非静态。

3,构造函数。

构造函数可以本类进行对象初始化,也可以给子类对象进行初始化。

子类对象初始化过程:

子类中的所有构造方法都会访问父类中空参数的构造函数,

因为每一个构造函数的第一行,都有一句隐式的super语句。

为什么要有这条语句?

因为子类会获取到父类中的数据,必须要先明确父类对数据的初始化过程。

当父类中没有空参数构造函数时,子类构造函数必须通过super句来明确要访问的父类中指定的构造函数。

 

当然子类构造函数也可以通过this语句访问本类中的构造函数。

但是子类中肯定,至少有一个构造函数会访问父类。

                  

9.         抽象类:其实就是在分析事物时,事物中的功能有些是不明确的内容的,这些不明确内容就是抽象的,可以通过抽象函数来描述。

抽象函数一定要定义在抽象类中,因为,抽象函数所在类也必须被抽象标识。

写法特点:

         1,抽象函数只对函数进行声明,没有函数主体。

         2,抽象类和抽象函数都需要用abstract修饰。

         3,抽象类不可以进行实例化。

4,想要使用抽象功能,必须通过子类覆盖了父类中所有的抽象方法后,才可以对子类实例化。如果只覆盖了部分抽象方法,那么子类还是一个抽象类。

                   也可以理解为:抽象类是一个父类,是不断向上抽取而来的,

                   在抽取过程中,只抽取了方法声明,但没有抽取方法实现。

                   抽象类和一半类差不多。

                   区别:

                   抽象类可以定义抽象方法。

                   抽象类不可以建立对象。

                   其实抽象类一样用于描述事物,既可以定义抽象方法,也可以定义非抽象方法。

10.     接口

初期理解:接口看上去是一个特殊的抽象类,里面存的都是抽象方法。

特点:

格式:

一、1,通过interface来定义。

2,接口中常见成员:常量,抽象方法。

而且这些成员都有固定的修饰符。

常量:public static final

方法:public abstract

3,接口中的成员都是共有的。

4,一个类可以对接口进行多实现,也弥补了多继承带来的安全隐患,所以java对多继承进行了改良,用多实现方法来体现多继承的特性。

5,一个类可以继承一个类的同时,实现多个接口。

二、接口与接口之间是继承关系,而且可以多继承。

应用特点:

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

                   2,接口是功能的扩展。

                   3,接口的出现降低了耦合性。

三、抽象类和接口异同:

相同:

1,都可以在内部定义抽象方法。

2,通常都在顶层。

3,都不可以实例化,都需要子类来实现。

 

四、不同点:

1,抽象类中可以定义抽象方法和非抽象方法,

         而接口中只能定义抽象方法。

2,接口的出现可以多实现。

         抽象类只能单继承。

         也就是说:接口的出现,避免了单继承的局限性。

3,继承和实现的关系不一致。继承:is a,实现:like a

11.     异常类

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

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

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

对于问题的划分:两种:一种是严重的问题,一种非严重的问题。

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

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

对与非严重的,java通过Exception类进行描述。

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

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

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

Throwable

         |--Error

                  |--Exception

12.     打印异常的一些方法;

/ by zero;

System.out.println(e.getMessage());//

异常名称异常信息。                      

System.out.println(e.toString());//

异常名称,异常信息,异常出现的位置。

e.printStackTrace();//

    其实jvm默认的异常处理机制,就是在调用printStackTrace方法。

打印异常的堆栈的跟踪信息。

13.     我定义的这个功能可能有问题,所以我就要抛出异常信息,让调用者来处理这个信息;

//在功能上通过throws的关键字声明了该功能有可能会出现问题。

int div(int a,int b)throws Exception{

                   return a/b;

         }

14.     对多异常的处理。

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

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

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

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

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

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

 

15.     自定义异常。

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

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

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

要么在内部try catch处理。

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

 

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

 

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

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

 

如何定义异常信息呢?

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

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

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

自定义异常:

必须是自定义类继承Exception

继承Exception原因:

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

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

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

throwsthrow的区别

throws使用在函数上。

throw使用在函数内。

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

throw后跟的是异常对象

代码如下;

class FuShuException extends Exception

{

         private int value;

         FuShuException()

         {super();

         }

         msg父类已经实现了;我们直接调用就行了;value是我们传递的值,负数的值;

         FuShuException(String msg,int value)

         {

                   super(msg);

                   this.value = value;

         }

         public int getValue()

         {

                   return value;

         }

class Demo02

{

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

//      要么在内部try catch处理。

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

         int div(int a,int b)throws FuShuException

         {

                   if(b<0)

//手动通过throw关键字抛出一个自定义异常对象。

//因为java不认识这个异常,所以我们要手动抛出,java认识的会自动抛出;如算数异常;会自动抛给主函数;

throw new FuShuException("出现了除数是负数的情况------ / by fushu",b);

                   return a/b;

         }

}

 

你可能感兴趣的:(java基础)