1.访问修饰符
java提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):
1.公开级别:用public修饰,对外公开。
2.受保护级别:用protected修饰,对子类和同一个包中的类公开
3.默认级别:没有修饰符号,向同一个包的类公开.
4.私有级别:用private修饰,只有在类本体内可以访问,不对外公开.
2.封装
封装的实现步骤(三步):
tip: 可将set方法写在构造器中 仍然可进行验证。
3.继承
当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。画出继承的示意图
3.1基本语法
3.2 继承细节
1.子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。
2.子类必须调用父类的构造器,完成父类的初始化,在子类构造器中 默认有 super()。可通过super 指定初始化 且 this()与super ()只能有一个,且放在构造器的第一行。
3.当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
4.java所有类都是Object类的子类,Object是所有类的基类.
5.父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)
6.子类最多只能继承一个父类(指直接继承),即java中是单继承机制。思考:如何让A类继承B类和C类?【A继承B,B继承C】
7.不能滥用继承,子类和父类之间必须满足is-a的逻辑关系
3.3 继承本质
3.3.1 属性查找
会在堆空间的对象的空间内 对继承的每一类 都分配一个空间 以存放相应的属性。调用时 按照以下规则调用:
tip:
若父亲类 有 age 属性 但是为private 爷爷类 也有age属性 为 默认 用 儿子 对象调用age时 查到父亲 age 属性为 private 就会报错 不会继续再查找 爷爷类的 age.
内存布局如下:
3.3.2 方法调用
3.3.3 super
super代表父类的引用,用于访问父类的属性、方法、构造器
super调用属性和方法的规则和上面的提到的一样,只是直接跳过基类,从父类开始查找。
4.方法重写
5. 多态
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
方法重载体现多态,这里传入不同的参数,就会调用不同sum方法,就体现多态
方法重写体现多态。
5.2 对象的多态(核心,困难,重点)
多态的前提是:两个对象(类)存在继承关系
5.2.1多态的向上转型:
tip:
若写 animal.catchMouse()
因为 编译阶段 由编译类型决定,因此在编译时无法通过animal 找到该方法 因此 会报错。
若编译结束 进入到运行阶段,就按照运行类型查找方法:先在子类里 找方法 找不到再去父类。
5.2.2 向下转型
tip:
将编译类型 变为 子类的类型,因此在编译时 可以通过 Cat 找到 catchMouse方法,因此不报错。
运行 类型 还是 Cat 调用方法规则不变
2.要求aniaml 原本指向 的就是cat,才能这样用。
5.2.3属性没有重写之说!属性的值看编译类型
属性的值 直接从 编译类型 开始查找
5.2.4 动态绑定
调用方法时 会有动态绑定,即方法的调用与对象内存地址/运行类型绑定。
若调用 a.sum 运行类型 里没有 sum方法,会去父类(A类)找 sum方法 这时 有getI 方法得到 I,因为动态绑定的原因,getI 是指 运行类型里的getI(即B类 的 getI). 而 属性I 没有动态绑定 哪里声明 哪里使用,因此 I就是 运行类型的I(B 类的 I)