1.面向对象特征之:封装
1.1.封装的介绍:
- 1.程序设计追求高内聚和低耦合,我们
隐藏对象内部的复杂性
,仅仅对外公开简单接口。便于外界调用,从而提高了系统的可扩展性、可维护性。- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合:对外暴露少量方法于使用
- 2.然后所谓的封装就是把抽象出的数据(属性)和对数据操作的方法(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作,才可以对数据进行操作
1.2.封装的好处:
- 1.实现了隐藏实现的细节
- 2.可以对数据进行验证,保证数据的合理与安全
1.3.封装的实现
a.实现方式举例:
- 1.将
数据进行私有化private
,这样就不可以直接对属性进行修改了 - 2.提供一个公共的
public
方法set方法,达到对属性赋值的目的
- 3.提供一个公共的
public
方法get方法,达到获取属性赋值的目的
- 4.
单例模式也是对封装思想的提现
b.四种权限修饰符:
- 1.四种权限修饰符可以修饰类的内部结构:
属性、方法、构造器、内部类
- 2.修饰类的话,就只能使用:
缺省、public
2.面向对象特征之:继承
2.1.继承的概述:
a.为什么需要继承(继承的优点)
- 1.提高代码的复用性,减少了代码荣誉
- 2.代码的扩展性和维护性提高了
- 3.为之后的多态性的使用,提供了前提
b.继承的基本介绍
- 继承可以
解决代码复用
,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中 抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来 声明继承父类即可
。
2.2.继承的基本语法
class 子类 extends 父类{
//方法体
}
- 1.子类会自动拥有父类定义的属性与方法
- 2.父类又叫
超类
- 3.子类又叫
派生类
2.3.继承的细节问题
- 1.子类继承了所有的属性和方法,对于这些
非私有
的属性和方法可以在子类直接访问 ,对于私有的属性和方法写被继承,只不过是因为封装性的原因,子类不可以直接调用,但私有属性和方法不能在子类直接访 问
,可以通过父类提供公共的方法去访问
- 2.
子类必须调用父类的构造器, 完成父类的初始化
- 3.当创建子类对象时,不管使用子类的哪个构造器,
默认情况下总会去调用父类的无参构造器
,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定
使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过 - 4.如果希望指定去调用父类的某个构造器,则显式的调用一下 :
super(参数列表)
- 5.
super 在使用时,必须放在构造器第一行
(super 只能在构造器中使用
) - 6.
super() 和 this() 都只能放在构造器第一行
,因此这两个方法不能共存在一个构造器
- 7.java 所有类都是 Object 类的子类,
Object 是所有类的基类
- 8.父类构造器的调用
不限于直接父类
!将一直往上追溯直到 Object 类(顶级父类)
- 9.子类最多
只能继承一个父类
(指直接继承),即 java 中是单继承机制,子类和父类之间必须满足 is-a
的逻辑关系
2.4.继承的本质分析
案例:看一个案例来分析当子类继承父类,创建子类对象时,内存中到底发生了什么事情—》》》
其实是发生了当子类对象创建完毕后,建立了查找关系
。
- 1.属性的初始化:
- 2.属性的引用关系:
2.5.super 和this关键字:
a.super 关键字
super基本介绍
super 代表父类的引用
,用于访问父类的属性、方法、构造器
基本语法
- 1.super可用于访问父类中定义的属性,但是
不能访问父类private的属性
- 2.super可用于调用父类中定义的成员方法,但是
不可以访问private方法
- 3.super可用于在子类构造器中调用父类的构造器
注意事项:
- 1.调用父类构造器的好处就是:分工明确,父类属性由父类初始化,子类属性由子类初始化
- 2.
super 的访问不限于直接父类
,如果爷爷类和本类中有同名的成员,也可以使用 super 去访问爷爷类的成员
; - 3.如果多个基类(上级类)中都
有同名的成员
,使用super 访问遵循就近原则
,A->B->C ,当然也遵守访问权限修饰符的原则 - 4.当子类和父类中成员(属性,方法)同名字的时候,为了访问父类的成员,必须要通过super。
如果没有重名,使用super,this直接访问效果都是一个样
- 5.super和this的用法相像,
this代表本类对象的引用,super代表父类的内存空间的标识
调用父类的构造器
- 1.子类中
所有的构造器默认都会访问父类中空参数的构造器
- 2.当父类中没有空参数的构造器时,子类的构造器必须通过
this(参数列表)
或者super(参数列表)
语句指定调用本类
或者父类
中相应的构造器。同时,只能”二选一”,且必须放在构造器的首行 - 3.如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错
b.super和this的比较:
c.使用super和this的案例分析:
- 1.测试继承中,执行的顺序:
package com.jianqun.extendtest;
/**
* @author: jianqun
* @email: 1033586391@qq.com
* @creat: 2022-04-03-13:14
* @Description:
*/
public class TestExtends {
public static void main(String[] args) {
B b = new B();
System.out.println(b);
}
}
class A {
// 无参构造
A(){
System.out.println("a");
}
// 有参构造
A(String name){
System.out.println("a name");
}
}
class B extends A{
// 无参构造
B(){
this("abc");
System.out.println("b");
}
// 有参构造
B(String name){
System.out.println("b name");
}
}
2.6.方法重写/覆盖(override)
a.重写的概念:
- 1.在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的
重置
、覆盖
。在程序执行时,子类的方法将覆盖父类的方法
b.重写的要求:
- 1.方法重写时
子类有一个方法和父类的方法的名称,参数返回值,都是一样的
, - 2.方法重写时返回值与父类相同或者是父类返回值的子类,比如说:父类返回类型是 Object ,子类方法返回类型是 String,那子类的这个方法我们就叫做是子类方法覆盖了父类方法`
- 3.子类重写的方法,
子类方法不能缩小父类方法的访问权限
:public > protected > 默认>private
- 4.子类不能重写父类中声明为private权限的方法
- 5.子类方法抛出的异常
不能大于
父类被重写方法的异常
c.注意:
- 1.
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写)
,或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法
d.重写和重载比较
e.重写代码举例:
2.7.四种访问权限修饰符:
- 1.Java权限修饰符
public
、protected
、(缺省)
、private
置于类的成员定义前,用来限定对象对该类成员的访问权限
- 2.对于
class的权限修饰只可以用public和default(缺省)
- public类可以在任意地方被访问。
- default类只可以被同一个包内部的类访问。
3:面向对象特征之:多态
3.1.什么是多态:
a.问题引出多态:
- 人类
master
对不同的动物分别喂养不同的食物
- 为了解决下面这样的问题,引出了多态:所谓的多态就是说
方法或者对象具有多种形态
。多态是建立在封装和继承的
基础上的
3.2.多态在方法中的体现:
package com.jianqun.poly02;
/**
* @author: jianqun
* @email: 1033586391@qq.com
* @creat: 2022-04-03-20:39
* @Description:
*/
public class PloyMethod {
public static void main(String[] args) {
A a = new A();
// 方法的重载体现出来的多态
// 这里我们传入不同的参数,就会调用不一样的sum方法
System.out.println(a.sum(1,2));
System.out.println(a.sum(1,2,3));
// 方法重写体现的多态
B b = new B();
a.say();
b.say();
}
}
class B{
public void say(){
System.out.println("B say() 方法被调用。。。");
}
}
class A extends B{
//方法的重载
//子类
public int sum(int n1,int n2){
return n1 + n2;
}
public int sum(int n1,int n2,int n3){
return n1 + n2 + n3;
}
public void say(){
System.out.println("A say() 方法被调用。。。");
}
}
3.3.多态在对象中的体现(核心,困难,重点):
- 1.一个对象的
编译类型和运行类型
是可以不一致的Animal animal = new Dog()
:animal是编译类型
,运行类型是Dog
;animal = new Cat()
:animal的运行类型就变成Cat
,编译类型还是Animal
运行类型是谁,调用的方法就是谁的
- 2.
编译类型在定义对象的时候
就确定了,不可以改变
- 3.
运行类型
是可以改变
的 - 4.编译类型看定义时 “=“的左边,运行类型看“=” 的右边
3.4.多态解决开始喂养动物的问题:
3.5.多态注意事项和细节讨论
- 1.多态的
前提是
:两个对象(类)存在继承关系
- 2.多态的向上转型
- a.本质是:父类的引用指向了子类的对象
- b.语法:
父类类型 引用名称 = new 子类类型()
; - c.特点:
- 编译类型看左边,运行类型看右边
- 可以调用父类中所有成员
- 不可以调用子类中的特有成员
- 最终运行效果看子类的具体体现
- 3.多态向下转型
- 语法:
子类类型 引用名称 = (子类类型) 父类引用
只能强转父类的引用
,不能强转父类的对象- 要求
父类的引用必须指向的是当前目标类型的对象
- 当向下
转型后,可以调用子类类型中所有成员
- 语法: