java面向对象编程的特征(查漏补缺)
封装
- 信息的隐藏以及行为实现细节的隐藏。
- 维护数据的一致性和安全性
- 缩小访问权限(private),将信息私有化话之后,如果需要和其他对象之间进行交流,可以通过提供统一访问入口的方法提供给所有人统一访问方式。
继承
目的:父类代码的复用。简化子类构建过程。
Note:
1.满足is a或者is kind of语义关系
2.子类可以继承父类所具有的属性和行为。
3.子类还可以具有比父类更多的特征。
4.子类可以具有和父类完全同名的方法,子类可以覆盖父类本身所具有的行为。
5.子类可以 具有和父类完全一致的属性。
6.可以使用父类类型的变量接收子类类型的对象实例
引用类型数据类型转换:
1.隐式:
父类类型的引用指向子类对象
ShoutAnimal an = new Dog();
2.显示:
Dog d = (Dog)an;
Cat c = (Cat)an;
只要满足继承关系的子父类在进行强制(显示)类型转换时,编译期语法都可以通过,但是运行时有可能出现跨种族转换(虚拟机抛出ClassCastException),为了在运行时减少类型转换异常,推荐,在使用引用类型的强制类型转换之前先使用instanceof判断是否能够进行转换。
an instanceof ShoutAnimal : true
an instanceof Dog: true
an instanceof Cat: false
Tips:若子类强转为父类,则父类的引用指向子类的对象,这话没错,但是,也只能说半对,为啥,来看看这段代码和运行结果
运行结果:
null
I’m B
代码很简单,就是子类与父类具有共同的方法和属性,在main中,创建了一个子类对象B,隐式转换成父类A,并使用该引用b2a访问属性name,访问方法pr()。调用方法不难理解,但是调用属性肯定很多人会理解错,认为结果应该是传入的值I'm B
,但是运行结果摆在这里了,我们就好好来理解一下吧。(关于默认修饰符protect修饰的属性能不能继承请看:传送门,这里就不再展开讲了)
在执行
new B("I'm B");
的时候发生了什么呢,当然是先创建了父类A,后创建了子类B(若子类中有静态方法,则先执行父类的静态方法,后执行子类静态方法,然后依次执行父类代码块和构造方法,再依次执行子类代码块和构造方法:详情参考)。那么
A b2a
中的b2a
指向的是父类还是子类B呢,一般书上都会讲是指向子类B,这样说没错,但严格意义上是指向父类的,指向子类还是父类是由类型修饰符来决定的,这里是A
,所以,b2a
取name
属性取用的是父类的name
,而父类的name
没有赋值,即为空值null,如下图:
多态
1. 运行时多态
相同类域的不同对象在调用相同方法时的表现不同
方法的重写
1. 有子父类继承关系存在/接口和实现类关系
2. 子类覆盖父类的行为/实现类实现接口中的方法
3. 父类类型的引用指向子类对象/接口类类型的引用指向实现类的对象
4. 调用被 重写了的方法/调用被实现了的方法
2. 编译时多态
方法的重载
12345678
class Shape{ getArea(int r){ System.out.println("圆形"); } getArea(int a,int b){ System.out.println("三角形"); }}