继承、final、多态、内部类、异常

继承(上):

1. 提高了代码的重用性

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

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

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

在java语言中只能是单继承,不支持多继承。

因为:多继承容易带来安全隐患,当多个父类有相同的功能,

当功能内容不同时,子对象不确定运行哪一个。

但是java保留这种机制,用另一种形式表示:多实现。

并且存在多层继承,也就是一个继承体系。

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

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

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

为什么具体调用时,创建最子类的对象?

1. 因为有可能父类不能创建对象。

2. 创建子类对象可以使用最多功能,包括基本的还有特有的

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

聚集:has a

1. 聚合:球员 和 球队

2. 组合:更紧密    人 和 手

1.变量

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

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

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

super 和 this的使用基本使用几乎一致

this代表的是本类对象的引用

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

clas Fu{

public String num = 4;

}

class Zi extends Fu{

int num = 5;

public void show(){

S.o.p(num);

}

}

输出结果:5

假如注销public  String num = 5;

输出结果 : 4

结论:super 和 this 指向同一个对象,父类(super)的引用指向子类的对象。

 

子父类中的函数(重写,覆盖)

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

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

如同父类的函数被覆盖一样。

这种情况就叫做重写(覆盖)

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

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

这时,没有必要定义新的功能,而是使用覆盖特殊,保留父类的功能定义,并且重写功能的内容

public class Tel{

public void show (){

s.o.p("number");

}

}

class NewTel extends Tel{

public NewTel(){

super(); //第一行必须

}

public void show(){

super.show();

s.o.p("name");

s.o.p("pic");

}

}

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

2. 静态只能覆盖静态

子父类构造函数:

不能覆盖:因为覆盖名称要一模一样,而构造函数是跟类名走,不可能存在覆盖。

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

因为在子类的构造函数中默认会调用父类的构造函数通过super();

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

因为父类中的数据在子类中直接获取,所以子类建立时需要查看父类是如何

对这些数据进行初始化的。所以子类在初始化时,先要访问一下夫列的构造函数

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

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

结论: 子类的所有的构造函数默认都会访问父类空参数的构造函数

因为子类每一个构造函数的第一行内都有隐式的父类构造函数

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

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

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

final 关键字:作为一个修饰符,相当于一个死锁永远打不开,也变不了。

1. 可以修饰类,函数,变量。

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

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

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

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

而且这个值不需要更改,所以加上final修饰。常量的书写规范是所有的单词都要大写,并且每个单词之间用下划线分隔开.

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

------------------------------final问题-------------------------

在内部类中访问局部变量,编译器实际上会为该内部类创建一个成员变量,以及带有参数的构造方法,然后将该变 量传入构造方法,也就是说外面的变量和类里面的变量就是名字相同而已,此时你无论修改哪一个都对另外一个不产生影响,这样就出现矛盾了,防止这种现象就规 定只准用final

你可以自己定义构造方法然后传进去,就没必要定义final变量

成员变量的话实际上内部类访问就是用类似于Test.this.xxx的……

该说的都被你说了,我再补充一点:就是内部类在使用局部变量的时候为什么要创建一个改局部变量的拷贝呢?

原因就是:局部变量在方法结束后生命周期就结束了,但是内部类的对象却不是,所以内部类中使用局部变量的话,就需要改变量的一份拷贝。但是既然是拷贝,就 会出现两边值(局部变量和局部变量的拷贝)不一致的情况,所以要确保同步最直接的方法就是不对该变量做修改,最终的结果就是你的疑问了,“内部类引用局部 变量为什么要求必须是final的”。

当然了“全局变量”(你的意思应该是 实例变量 )的生命周期比局部变量相对要长,不会出现该问题,也就不需要拷贝,当然也就不需要强制为final来确保值同步了

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

继承(下):

抽象类

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

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

抽象类的特点:

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

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

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

4. 抽象类中方法要想被使用,必须由子类复写这个类的所有的抽象方法后,被子类对象调用

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

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

模版方法设计模式

什么是模版方法?

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

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

示例代码:

public class Demo2 {

public static void main(String args[]){

new GetTimes().getTime();

}

}

abstract class GetTime{

public void getTime(){//final 确保方法不会被重写

Long start = System.currentTimeMillis();

doThing();

Long end = System.currentTimeMillis();

System.out.println("工作时间 = " + -(start - end));

}

public abstract void doThing();//暴露一个抽象方法给子类去实现想要做的具体事情

}

class GetTimes extends GetTime{

public void doThing(){//子类实现父类的抽象方法,去干具体想干的事情

for(int i = 0 ; i < 10000; i ++)

System.out.print(i);

}

}

接口

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

class 用于定义类     interface用于定于接口

接口定义时,格式特点:

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

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

常量: public static final

方法: public abstract

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

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

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

否则子类还是一个抽象类

·     接口可以被类多实现,也是对多继承转换形式。

多态:事物的多种体现形态

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

前提:类与类之间有关系,要么继承或实现。

好处:提高了代码的扩展性

弊端:但是只能使用父类的引用指向子类和父类同样的方法。

类型转换:向上转型   向下转型

instanceof 用于判断对象是属于哪种类型。

多态(父类的引用指向子类对象)在代码中的特点(注意事项):

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

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

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

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

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

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

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

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

 java对非静态方法的调用是采取动态绑定(运行时才判断)的方法,

                对静态成员、属性的调用是采取静态绑定(编译时就判断)的方法。

---------------------示例代码----------------------------------------

class Fu{
     public String name = "Fu";
     public static String address= "Fu address";
     public void method1(){
          System.out.println("Fu method1");
     }
          public void method2(){
          System.out.println("Fu method2");
     }

     public static void method4(){
          System.out.println("static Fu method4");
     }
}
class Zi extends Fu{
     public static String address= "Zi address";
     public String name = "Zi";
     public void method1(){
          System.out.println("Zi method1");
     }
     public void method2(){
          System.out.println("Zi method2");
     }
     public void method3(){
          System.out.println("Zi method3");
     }
     public static void method4(){
          System.out.println("static Zi method4");
     }
     public void method5(){
          System.out.println(name);
     }
     public void method6(){
          System.out.println(super.name);
     }
     public void method7(){
          System.out.println(name);
     }
}

public class Test{
     public static void main(String args[]){
          /*关于非静态/和静态函数的演示*/
          //Fu z = new Zi();
          //z.method3();//编译会报错
          //z.method2();//Zi method2
          /*为什么会出现下面的这种情况?
               因为静态方法是静态绑定好的,
               无论是在什么情况在最初的时候就已经在静态方法区把静态方法和类绑在一起,所以静态方法不存在覆盖
               不管引用指向哪个对象不没有用。
               而非静态方法是在new对象的时候把非静态方法和对象绑定一起,通过对象去调用非静态方法。
          */
          //z.method4(); //static Fu method4
          //Zi z1 = new Zi();
          //z1.method4();//static Zi method4

          /*成员变量的演示*/
          Zi z2 = new Zi();
          System.out.println(z2.name);//Zi
          //(在堆内存中同时存在两个变量,
          //那么会先找定义引用的那个类的那个变量值 和 方法不同)
          Fu z4 = new Zi();
          System.out.println(z4.name);//Fu

          /*为什么会出现这种情况?
               在非静态成员变量中,对象的引用去取成员变量是根据左边的类去找相对应的值
               在静态成员变量中是根据静态绑定的原理一样一开始就把类和静态成员绑定在一起。
               不管自己指向哪个对象
               静态的成员或方法都是直接和类进行绑定在一起称之为静态绑定

               绑定回去好好看下下...........

               java对非静态方法的调用是采取动态绑定(编译期判断但运行时才绑定)的方法,
               对静态成员、属性的调用是采取静态绑定(编译时就绑定并且判断)的方法。
          */
          //Fu z3 = new Zi();
          //System.out.println(z3.address);//Fu address
          //Zi z4 = new Zi();
          //System.out.println(z4.address);//Zi address
     }
}

接口和多态的综合使用(接口回调)

举例:主板  PCI  卡

-----------------示例代码----------------------------

class MainBoard{
     public void start(){
          System.out.println("MainBoard start!");
     }
     public void controllerCard(PCI p){//向外暴露一个接口只要是实现了该接口的方法就可以被调用执行
          if(p != null){
               p.open();
               p.close();
          }
     }
}
class SourdCard implements PCI{
     public void open(){
          System.out.println("SourdCard open");
     }
     public void close(){
          System.out.println("SourdCard close");
     }
}
interface PCI{

     public abstract void open();
     public abstract void close();
}
public class Test2{
     public static void main(String args[]){
          MainBoard mb = new MainBoard();
          mb.start();
          mb.controllerCard(new SourdCard() );
     }
}

内部的访问规则:

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

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

之所以可以直接访问外部类的成员,因为内部类持有外部类的引用,格式:Outer.this.x

访问格式:

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

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

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

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

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

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

static: 内部类具有了static特性。

当内部类被static修饰时,只能直接访问外部类的static成员,

出现了想问局限。

3.在外部类中,如何直接访问static内部类中非静态成员?

new Outer.Inner().function();

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

Outer.Inner.function();

注意:

当在内部类中定义了静态成员,那么内部类必须是静态内部类。(内部类中不能有静态声明除非内部类也是静态的)。

当外部类中的静态方法访问内部类中的方法时,那么内部类必须为静态的。

什么时候使用内部类:

当描述的事物时,事物内部还有事物,该事物就应该用内部类封装:人-人体(private)

内部类中定义在局部时,

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

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

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

匿名内部类:

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

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

内部类必修是继承一个类或者是接口

3. 匿名内部类的格式:

new 父类或者接口(){定义子类的内容}

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

5. 在匿名内部类中可以写其他成员,但每次只能调用一个方法,

但可以帮他取个名字用父类的引用指向子类的对象。

使用情况: 当使用的方法的参数类型是一个接口类型时,直接向调用方法传入一个匿名对象。

面试题:假如我没有父类,也没有接口让我去实现,还能写匿名内部类吗?

答案 :能

public class{

new Object(){

public void function(){}

}

}


jvm默认的异常处理机制就是调用printStackTrace方法

对于多异常的处理。应该是定义更具体的异常来捕捉捕捉问题

捕获异常代码块出现继承关系 应该把被继承的异常放在子类异常块的后面

throw 和 throws的区别

throw是是用在函数上,而throws是使用在函数内

throw后面跟的是异常对象,而throws跟的是异常类可以 多个

对异常的分类:

1.编译时被检测到的异常。

(值得去处理的异常,或者是希望得到调用者处理,并不影响运算意向)

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

(不值得去处理的,交给jvm去处理,出现这种异常假如处理的会影藏异常影响了

运算意向,eg :角标越界、内存溢出、除0运算、空指针)

时间: 2024-10-29 00:09:05

继承、final、多态、内部类、异常的相关文章

Java知多少(34)final关键字:阻止继承和多态

在 Java 中,声明类.变量和方法时,可使用关键字 final 来修饰.final 所修饰的数据具有“终态”的特征,表示“最终的”意思.具体规定如下: final 修饰的类不能被继承. final 修饰的方法不能被子类重写. final 修饰的变量(成员变量或局部变量)即成为常量,只能赋值一次. final 修饰的成员变量必须在声明的同时赋值,如果在声明的时候没有赋值,那么只有 一次赋值的机会,而且只能在构造方法中显式赋值,然后才能使用. final 修饰的局部变量可以只声明不赋值,然后再进行

Java 继承、多态与类的复用

摘要: 本文结合Java的类的复用对面向对象两大特征继承和多态进行了全面的介绍. 首先,我们介绍了继承的实质和意义,并探讨了继承,组合和代理在类的复用方面的异同.紧接着,我们依据继承引入了多态.介绍了它的实现机制和详细应用.此外,为了更好地理解继承和多态.我们对final关键字进行了全面的介绍. 在此基础上.我们介绍了Java中类的载入及初始化顺序.最后.我们对面向对象设计中三个十分重要的概念–重载.覆盖与隐藏进行了详细的说明. 要点: 继承 组合,继承,代理 多态 final 关键字 类载入及

面向对象(继承,多态)

二维数组的定义格式:第一种:直接给定了每一个一维数组中数组长度数据类型[][] 数组名称 = new 数据类型[m][n]第二种:给定了多少个一维数组,长度动态给定数据类型[][] 数组名称 = new 数据类型[m][] ;第三种:二维数组中直接给定元素值数据类型[][] 数组名称 = {{元素1,元素2},{元素1,元素2}-} 如何遍历二维数组 int [][] arr = {{11,22},{33,44},{55,66}} ; 外层循环:控制的是二维数组长度,内存循环,一维数组长度 代码

JAVA基础——面向对象三大特性:封装、继承、多态

JAVA面向对象三大特性详解 一.封装 1.概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: 只能通过规定的方法访问数据.     隐藏类的实例细节,方便修改和实现. 3.封装的实现步骤 需要注意:对封装的属性不一定要通过get/set方法,其他方法也可以对封装的属性进行操作.当然最好使用get/set方法,比较标准. A.访问修饰符 从表格可以看出从上到下封装性越来越差. B.this关键字 1.this关键字代表当前

类和对象、封装、继承、多态

? 类和对象 ? 类和对象的概念 类:客观存在的,抽象的,概念的东西.一个类可以被定义为描述行为的模板: 对象:对象是具体的,实际的,代表一个事物.对象具有状态和行为. 类是对象的模板,对象是类的一个具体实体. 定义Java中的类 一个类可以包含以下任意变量类型. a)局部变量: 方法里面,构造函数或块中定义的变量称为局部变量.该变量将被声明和初始化的方法中,当该方法完成该变量将被销毁. b)实例变量: 实例变量都在一个类,但任何方法之外的变量.这些变量在类被加载的实例化.实例变量可以从内部的任

Java面向对象㈡ -- 继承与多态

Java的继承是通过extends和implement来实现的,Java不支持多继承,但是Java支持多层继承以及多实现(接口).Java继承有一个关键字super是用来指向父类.Java继承衍生出覆盖的概念.覆盖被用来支持多态.实际开发中Java通常继承于抽象类,实现于接口.如果不希望一个类被继承,或者一个方法被覆盖,或者一个成员变量被改变,就可以用final修饰.这里只说明两个问题:1,重载和覆盖的区别重载和覆盖的区别:重载发生在同一个类之中,重载要求函数名相同,参数不同(参数个数||参数类

接口、继承、多态

接口.继承.多态 继承和多态是面向对象开发语言中非常重要的饿一个环节,如果在程序中使用继承和多态得当,整个程序的架构将变得非常有弹性,通知书可以减少代码的冗余性. 继承机制的使用可以复用一些定义好的类,减少重复代码的编写.多态机制的使用可以动态调整对象的调用,降低对象之间的依存关系. 1.继承机制中子类的结构化过程 子类的所构造函数,默认都会访问谷类中控参数的构造函数:因为,子类每一个构造行数内的第一行都由依据隐式的super(); 子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的,

黑马程序员——java学习5(107-126)——内部类,异常,包

1.内部类 1.1何时: 事物的内部还有事物,就用内部类(人体和心脏举例) 方法: (1)内部类可以直接访问外部类中的成员,包括私有. 之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this (2)外部类要访问内部类,必须建立内部类对象 格式: (1)当内部类定义在外部类的成员位置上,且非私有,可以在外部其他类中,可以直接创建内部类对象 Outer.Inner out=new Outer().new Inner(); (2)当内部类在成员位置上时,就可以

java基础讲解09-----接口,继承,多态

还有什么包装类,数字类,这些简单的我就不想过去介绍,前面也大概的介绍了下,继承,多态 1.类的继承 继承的思想:基于某个父类的扩展,制定一个新的子类.子类可以继承父类原有的属性,方法,也可以重写父类的方法,也可以自己增加父类不具备的方法,属性 .使用extends关键字来标识继承关系 ( 重写方法的规则如下: 1. 参数列表:必须与被重写方法的参数列表完全匹配. 2. 返回类型:必须与超类中被重写的方法中声明的返回类型或子类型完全相同 3. 访问级别:一定不能比被重写方法强,可以比被重写方法的弱

java学习中,面向对象的三大特性:封装、继承、多态 以及 super关键字和方法的重写(java 学习中的小记录)

java学习中,面向对象的三大特性:封装.继承.多态 以及 super关键字和方法的重写(java 学习中的小记录) 作者:王可利(Star·星星) 封装     权限修饰符:public 公共的,private 私有的     封装的步骤:          1.使用private 修饰需要封装的成员变量.          2.提供一个公开的方法设置或者访问私有的属性              设置 通过set方法,命名格式:     set属性名();  属性的首字母要大写 访问 通过ge