关于java中面型对象的三大特性---封装,继承,多态
面向对象的三大特性:
封装,继承,多态
面向对象的三大特点:
1.更符合我们平时的思维习惯
2.把复杂的问题简单化
3.把我们从执行者变成指挥者
Java中使用类来描述事物
类:一类事物的抽象
对象:这类事物的实例(具体化)
关于封装
体现:
1.方法的定义
2.私有成员变量
3.描述一个事物(定义一个类)
好处:
1.提高代码的复用性
2.提高代码的安全性
3.提高代码的多样性
关于私有成员变量:
用private修饰的成员变量就是私有成员变量.
private:权限修饰符 私有的
修饰:成员变量和成员方法
被修饰后 :被修饰的成员只能在本类中访问;
关于类:
构造方法:
格式:
修饰符 类名(形式参数列表){
方法体;
}
构造方法的作用:
1.提供多种创建对象的方式
2.在创建对象的同时给对象的属性进行赋值
3.在创建对象的同时完成某些功能(自己完成)
构造方法的特点:
1.若在一个类中不写任何构造方法,JVM会默认给与一个无参构造方法;
2.若在一个类中写了任意一种构造方法,JVM提供的默认无参构造就没有;
new的过程做了哪些事情:
1.创建一个对象
2.调用了相应的构造方法
3.在堆内存中开辟了空间
创建对象的格式:
类名 对象名 = new 类名(实际参数列表);
事物描述类的编写步骤
1.私有成员变量 -->写属性
2.自动生成无参构造方法
3.自动生成含参构造方法
4.自动生成getters and setters 方法
5.若该类型的事物有行为 你可以自行的编写相应的成员方法
事物描述类的使用
1.创建main方法(main方法不要写在事物描述类中)
2.创建对象
3.对象调方法(对象调属性)
关于继承
继承:类与类之间的关系
继承的特点:单一继承,多层继承
继承的原则:子类继承父类,子类可以使用父类中所有非私有的成员
继承的关键字: extends
继承的格式:
public class 子类名 extends 父类名{
}
注意:当一个类没有任何继承关系的时候,默认继承Object
Object:根类,基类,超类 是所有类直接或者间接的父类
继承中成员变量的特点:
只要有对象调属性,编译看左边,运行看左边;(看的是对象,看对象里是否有这个属性,后者 )
-->就近原则
当局部位置有该变量,优先使用局部位置的变量
当局部位置和本类成员位置都有该变量,若要使用本类成员位置的变量: this.变量名
当局部位置,本类成员位置和父类成位置都有该变量,若要使用父类成员位置的变量: super.变量名
继承中成员方法的特点:
只要有对象调方法,编译看左边,运行看右边;(看的是对象,看对象里是否有这个方法,或者父类里有没有这个方法)
-->动态绑定:
当子类中有该方法,执行子类的该方法;
若子类中没有该方法,去父类中找该方法,若有就执行,若没有报错!
继承中构造方法的特点:
子类对象要加载要优先加载父类; 原因:有可能子类对象会使用到父类的成员;
构造代码块:对象的预加载 -->为对象的出生做准备
什么时候执行:只要new对象 就优先于构造方法执行构造代码块
执行多少次:只要new 对象,new一次就执行一次构造代码块
静态代码块:类的预加载 -->驱动 -->为类的加载做准备
什么时候执行:当这个类第一次被加载的时候执行;
执行多少次:只在类第一次被加载的时候执行一次,优先于构造代码块优先于构造方法;
super:本类父类对象的引用
this:本类对象的引用
this.变量名:调用本类中成员位置的该变量
this.方法名:调用本类中的某个成员方法
super.变量名:调用本类父类中成员位置的该变量
super.方法名:调用本类父类中的某个成员方法
this():调用本类中的无参构造方法,只是调用构造方法并没有创建对象
this(实际参数):调用本类中的含参构造方法,只是调用构造方法并没有创建对象
super():调用本类父类中的无参构造方法,只是调用构造方法并没有创建对象
super(实际参数):调用本类父类中的含参构造方法,只是调用构造方法并没有创建对象
super():
1.当一个类的构造方法的第一行代码没有调用其他任何一个构造方法,默认存在一句super();(只能在构造方法的第一句)!
2.若你在构造方法的第一句调用了任意某个本类或者父类的构造方法,默认存在的super()就不存在了!
3.一个类中一定会有一个构造方法的第一句是在调用父类的构造方法!
方法的重写:
当子类中出现了与父类中方法声明完全一致的情况,称为方法的重写; (除了权限修饰符)
必须要求子类重写方法:返回值类型相同,方法名相同,形式参数列表完全相同
要求:子类重写的方法权限修饰符要大于或者等于父类的该方法
权限修饰符等级排名: public > protected > 默认不写 > private
注解: @Override -->检查方法是否是重写方法 -->最好加上
关于多态
多态:事物的多种形态
多态的前提条件:
1.必须有继承关系
2.必须有方法的重写 -->动态绑定 (父引用调用的是子类重写的成员方法)
3.父类引用指向子类对象
多态的格式:
父类型 父类引用 = new 子类型();
多态的成员特点:
成员变量:只要有对象调属性,编译看左边,运行看左边;
成员方法:只要有对象调方法,编译看左边,运行看右边;
多态的弊端:
父类引用不能访问子类特有的成员 我们可以通过向下转型把父引用转换成具体的子类对象;
多态的应用:
1.作为容器的类型,当一个父类型的容器创建,该容器可以存储该父类型所有子类型的对象
2.把父类型作为方法的形式参数,当调用此方法的时候可以传入任意的子类对象; -->这种思想:接口回调
引用数据类型间的类型转换:
前提:必须是子父类关系
向上转型: 子类 --> 父类
以多态的形式创建对象;
向下转型: 父类 --> 子类
子类型 子类对象 = (子类型)父类引用;
instanceof:专门判断继承关系中,对象是否是属于某个类型
格式:
对象 instanceof 类名
这个表达式的结果一定是boolean类型,一般作为if语句的判断,为了避免代码出现类型转换异常(ClassCastException)
ClassCastException:
产生原因:兄弟类之间转换
解决办法:
使用关键字 instanceof 关键字提前判断,若满足条件再转换
类的实例化内存图:
这里创建了一个Car的事物描述类,里面定义了成员变量和成员方法.还创建了一个CarDemo,来实例化Car类,并实现Car类中的方法.
这里,先加载了CarDemo.class到方法区,然后将main方法压栈进栈,在栈里开辟一块空间,之后要实例化一个Car对象,那么,Car.class文件加载到方法区,然后才可以在堆内存中new一个Car,开辟一块空间,在这个堆空间里,加载Car类里的成员变量,和成员方法在方法区的地址,然后调用了实例化对象的方法,c.run().
run()方法执行完后,就销毁,然后调用c.isGas()方法,在栈内存中开辟一块空间,给b传入的参数是true.
由图可以看出成员方法是通过地址来找到的,每new一个对象,就会在堆中创造一块空间,加载成员参数和成员方法的地址.方法一旦执行完毕,就会从栈内存中销毁.