Java学习笔记三 继承、接口和多态以及内部类

1、单例设计模式
(1)设计模式:对问题行之有效的解决办法,作为一种思想,也适用于其他的面向对象语言。
(2)解决问题:单例设计模式可以保证一个类在内存中的对象唯一性,针对多个程序使用同一个对象

(3)如何保证对象的唯一性?

  • 不允许其他程序使用new创建该类对象
  • 在该类中创建一个本类实例。
  • 对外提供一个方法让其他程序可以获取该

(4)步骤

  • 私有化该类构造函数
  • 通过new在本类中创建一个本类对象(private static)
  • 定义一个公有的方法,将创建的对象返回。(public static)
    注意,在该类中定义的成员变量一般也是private static的,不对外暴露。

2、继承的好处与弊端
(1)提高代码的复用性和可扩展性
(2) 让类与类之间产生关系,为第三个特征多态提供前提(无继承不多态)
Java支持单继承,不直接支持多继承,但对C++中的多继承机制进行改良
(3)打破底层的封装性(使用final解决)

3、单继承和多继承
(1)单继承:一个子类只有一个直接父类
(2)多继承:一个子类可以有多个直接父类(Java不允许,但进行改良)(两个父类具有相同方法时,产生调用的不确定的)在Java中通过“多实现”方式来体现。
(3)Java支持多层(多重)继承,形成一个继承体系。
(4)当要使用一个继承体系时,首先要查看该体系的顶层类,了解该体系的基本内容,然后创建该体系的最子类对象,完成功能使用。
(5)当类与类之间存在所属关系时,可以定义继承关系。

4、this和super
(1)当本类的成员变量与局部变量同名时,用this区分,当子类的成员变量与父类的成员变量同名时,用super区分。
(2)this和super的区别:
this和super用法类似,但this代表一个本类对象的引用,super代表一个父类加载的所属空间。

5、子类和父类
(1)子类中不具备父类中的私有内容,不能直接访问父类中的私有内容。
(2)当子类成员函数与父类成员函数同名时,会执行子类函数,这称之为函数的覆盖,只存在子父类之间。

6、函数的两个特性:重载与覆盖
(1)重载存在于同一个类中;
(2)覆盖(覆写,重写)存在于子类中,父类怎么定义,子类就怎么定义。

7、覆盖注意事项:
(1)子类方法覆盖父类方法时,子类权限必须大于等于父类权限
(2)静态只能覆盖静态,或者被覆盖。

8、什么时候使用覆盖?
当对一个类进行子类扩展时,子类需要保留父类功能,但要定义子类中该功能的特有内容,就是用覆盖操作。

9、子父类中的构造函数特点:
(1)在运行子类构造函数的时候,父类的构造函数也会运行,原因在于子类构造函数的第一行有默认的隐式语句:super(); 子类中所有的构造函数默认,都会访问父类中具有空参数的构造函数
(2)为什么子类初始化过程要访问父类中的构造函数?
因为子类继承 父类,获取了父类的内容(属性),在使用父类的内容前,子类要先知道父类是如何对自己的内容进行初始化的,所以子类在构造对象时,必须要访问父类的构造函数。
(3)如果在父类中没有定义空参数的构造函数,那么在子类中必须用super(参数列表)明确要调用父类中的哪个构造函数。但如果在子类的构造函数中使用了this(),就没有super(),因为它们都需要放在第一行,但可以保证的是,子类的其他构造函数中会调用父类的构造函数。
(4)super语句必须放在子类构造函数的第一行,因为父类的初始化动作要先完成。
(5)在子类的构造函数中,通过super()初始化父类内容时,子类的成员变量并未显示初始化,等到父类初始化完毕后,才开始子类成员变量初始化。并且父类和子类具有相同的方法时,即便是在父类中调用该方法,实际上执行的也是子类的方法。

10、一个对象的初始化过程:以Person p=new Person()为例
(1)JVM会读取指定路径下的Person.class文件,并加载进内存,并先加载Person的父类(如果有直接父类时)
(2) 在堆内存中开辟空间,并分配地址
(3)在对象空间中,对对象中的属性进行默认初始化
(4)调用对应的构造函数进行初始化
(5)在子类的构造函数中,会先调用父类的构造函数进行初始化,
(6)父类初始化完毕后,才对子类的属性进行显示初始化
(7)然后再进行子类构造函数的特定初始化
(8)子类初始化完毕后,将地址赋值给引用变量

11、final关键字
(1)final可以修饰类、方法和变量
(2)final修饰的类不可以被继承
(3)final修饰的方法不可以被覆盖
(4)final修饰的变量是常量,只能被赋值一次,不会对变量进行默认初始化。
(5)内部类只能访问被final修饰的局部变量
(6)public static final int num=9;全局静态常量;public 权限全局访问;static 无需对象,类名调用;final 修饰的变量为常量
(7)为什么用final修饰变量:如果变量的值是固定的,可以直接使用,但为了便于理解,用final修饰,赋予其有意义的名称,且不再改变,如PI,字母大写,多个单词,用 _ 分开。

12、抽象类
(1)方法只有声明,没有实现,该方法是抽象方法,用abstract修饰,抽象方法必须定义在抽象类中
(2)抽象类不能被实例化,因为调用抽象方法没有意义
(3)抽象类必须由其子类覆盖所有抽象方法后,子类才可以被实例化,否则,该子类还是抽象类。

13、抽象类的五个问题
(1)抽象类中有构造函数吗?
有,用于给子类对象初始化。
(2)抽象类中可以不定义抽象方法吗?
可以,目的是不让该类创建对象,AWT的适配器对象就属于这种类。这种类通常有方法体,但没有内容。
(3)抽象关键字与哪些关键字不共存?

  • private:抽象方法要被覆盖,不能被隐藏;
  • static:静态时不需要对象,用类名可以调用方法,但调用抽象方法无意义;
  • final:被final修饰的方法不能被覆盖,被final修饰的类不可被继承;
    (4)抽象类和一般类的异同点?
    1)相同点:抽象类和一般类都是用来描述事物的,都在内部定义成员
    2)不同点:
  • 一般类有足够的信息描述事物,抽象类描述事物的信息可能不足
  • 一般类只能定义非抽象方法,抽象类可以定义抽象方法,也可以定义抽象方法,
  • 一般类可以被实例化,抽象类不可被实例化

(5)抽象类一定是个父类吗?
是的,因为抽象类需要子类覆盖其方法后,才可以对子类实例化。

14、接口的特点

  • 接口是对外暴露的规则
  • 接口是程序功能的扩展
  • 接口的出现降低耦合性

(1)接口中的方法都是抽象的(public abstract),变量都是全局常量(public static final)
(2)接口中的方法由子类实现(implements)。
(3)接口弥补了单继承的缺陷,一个类只能直接继承一个父类,但可以实现多个接口。
(4)不能实现多继承,因为父类中的方法有方法体,产生调用的不确定性,而接口只有方法声明,没有方法体。
(5)子类在继承父类的同时,也可以实现多个接口。
(6)类与类之间是继承关系,类与接口之间是实现,接口与接口之间是继承关系,一个接口可以继承多个接口,多个接口存在相同的方法声明,子类只需要实现一个即可。
(7)接口类型的引用,接收实现接口的子类对象

15、接口与抽象类的区别
(1)相同点:都是抽取出来的抽象的概念
(2)区别:

  • 抽象类体现继承关系,一个类只能单继承;接口体现实现关系,接口可以多实现
  • 抽象类是继承,是“is a”关系;接口是实现,是"like a"关系
  • 抽象类可以定义非抽象方法,供子类直接使用;接口只能定义抽象方法,接口中的成员有固定的修饰符。

16、多态

  • 一个对象对应不同形态
  • 父类或接口的引用指向其子类对象
  • 好处:提高代码的可扩展性,前期定义的代码可以使用后期定义的内容
  • 弊端:前期定义的内容不能使用(调用)后期子类的特有内容。
  • 前提:必须有关系,要么继承,要么实现;要有覆盖;
  • 可以向上或向下转型,向上转型,限制使用子类特有内容;向下转型则为了使用。
  • 转型:都是子类对象在进行类型的变化,new 子类==》父类对象 ==》强制转换回来
  • 转型:一会变成父类型,一会变成本类型

17、instanceof

  • 用于判断对象的具体类型,只能用于引用数据类型判断
    通常在向下转型前健壮性的判断(if语句)

18、多态中的成员变量、成员函数和静态函数
(1)成员变量

  • 编译时,参考引用型变量所属的类中是否有调用的成员变量,有,编译通过,否,失败
  • 运行时,参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量
  • 编译和运行都参考等号左边,成员变量没有覆盖,(父/子类)谁调用就执行谁的成员变量

(2)成员函数(非静态)

  • 编译时,参考引用型变量所属的类中是否有调用的成员函数,有,编译通过,否,失败
  • 运行时,参考对象所属的类中是否有调用的成员函数
  • 编译看左边,运行看右边。
  • 非静态成员函数,依赖于对象,需要动态的绑定到指定的对象上。

(3)静态函数

  • 编译时,参考引用型变量所属的类中是否有调用的静态函数,有,编译通过,否,失败
  • 运行时,参考引用型变量所属的类中是否有调用的静态函数,并运行该所属类中的静态函数
  • 编译和运行都看左边
  • 静态函数可通过类名来调用,无需创建对象,(父/子类)谁调用就执行谁的静态函数

19、内部类
(1)访问特点

  • 内部类可以直接访问外部类的成员
  • 外部类要访问内部类的成员,需要创建内部类的实例
  • 一般用于类的设计

(2)分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的成员,这时就把还有的事物定义成内部类。
(3)直接访问外部类中的内部类的成员:
Outer.Inter in = new Outer().new Inter();
(4)如果内部类是静态的,相当于一个外部类
Outer.Inter in = new Outer.Inter();
(5)如果在内部类中定义了静态方法,该内部类也必须是静态的
(6)如果内部类是静态的,其成员也是静态的。
(7)为什么内部类可以直接访问外部类的成员?
因为内部类有外部类的引用,即:外部类名.this +外部类成员变量
(8)内部类可以存放在局部位置上
局部内部类(定义在方法中)只能访问由final修饰的局部变量

(9)匿名内部类

  • 内部类的简写形式,前提是内部类必须继承一个外部类或实现一个接口
  • 其实就是一个匿名子类对象,格式:new 父类or接口() { 子类内容 }
  • 使用场景:函数参数是接口类型,接口方法不超过三个,使用匿名内部类来传递实参
  • 相当于向上转型,(其对象)不能调用子类特有的内容。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值