Java日报
部门: **大数据开发六部
姓名: cqmfx(阡陌飞絮)
日期: 2020.11.1
大纲
一、继承入门
二、继承—重写
三、继承—父子类构造器
四、类的加载顺序
五、基本数据类型和引用类型比较内容
六、equals方法、instance of和对象转型
Java面向对象之继承
一、继承入门
1、基本概念
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承需要符合的关系是:is-a,父类更通用,子类更具体。子类会具有父类的一般特性也会具有自身的特性。
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
2、类的继承格式
class 父类 {
}
class 子类 extends 父类 {
}
3、继承的特性
- 子类拥有父类非 private 的属性、方法。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
- Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
- 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)
- 继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。
4、关键字
1)extends关键字
在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
public class Al {
private String name;
private int id;
public A(String myName, String myid) {
//初始化属性值
}
public void eat() { //吃东西方法的具体实现 }
public void sleep() { //睡觉方法的具体实现 }
}
public class B extends A{
}
2)implements关键字
使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
3)super 与 this 关键字
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类
this关键字:指向自己的引用
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m7Bdzf3k-1604298688274)(E:\day++\day9\Java面向对象之继承.assets\image-20201101233951373.png)]
4)final关键字
final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:
-
声明类:
final class 类名 {//类体}
-
声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
注:实例变量也可以被定义为 final,被定义为 final 的变量不能被修改。被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final
5、继承类型
二、继承—重写
1、规则
- 参数列表与被重写方法的参数列表必须完全相同。
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
- 访问权限不能比父类中被重写的方法的访问权限更低(可以等于)。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
- 父类的成员方法只能被它的子类重写。
- 声明为 final 的方法不能被重写。
- 声明为 static 的方法不能被重写,但是能够被再次声明。
- 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
- 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
- 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
- 构造方法不能被重写。
- 如果不能继承一个类,则不能重写该类的方法。
- 任何的类都默认继承一个顶级父类,Object,不写都继承
2、总结
重写遵循“两同两小一大”原则:
1)两同:
1.1)方法名相同
1.2)参数列表相同
2)两小:
2.1)子类方法的返回值类型要小于或等于父类
2.1.1)void时,必须相同
2.1.2)基本数据类型时,必须相同
2.1.3)引用类型时,小于或等于
2.2)子类方法抛出的异常要小于或等于父类的----异常之后
3)一大:
3.1)子类方法的访问权限要大于或等于父类的----访问控制修饰符之后
3、实操
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
@Override
public void move(){
super.move(); // 应用super类的方法
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal b = new Dog(); // Dog 对象
b.move(); //执行 Dog类的方法
}
}
三、继承—父子类构造器
1、父类构造器
1)定义
Java中的所有类而言,它们有一个根父类,即java.lang.Object类。
对于Java中构造器执行的顺序而言,程序执行的顺序为,先执行父类的非静态代码块,然后执行父类的相应的构造器,最后执行子类的非静态代码块
Java中的静态代码是在字节码文件在最开始加载的时候就完成的
2)使用
- 当父类没有任何构造器时,会默认自动生成一个无参构造器,子类实例化时就算没有super()也会默认先调用父类的无参构造器。
- 当父类有显式的无参构造器时,子类实例化时就算没有super()也会默认先调用父类的无参构造器。
- 当父类有有参构造器了,如果没有显式地写入无参构造器,系统也不会自动生成无参构造器,此时子类构造器的首行必须要调用父类的有参构造器,有以下方式:
① 用super(…)直接调用父类的有参构造器
② 用this(…)间接调用父类的有参构造器 - 子类构造方法必须指定调用了父类的哪一个构造方法,子类构造方法Student(String name,String id)直接调用了父类的有参构造方法Person(String name),而子类构造方法也因为有this(name,id);而调用了上面的另一个子类构造方法而间接调用了父类的有参构造方法Person(String name),子类必须调用父类的构造方法
2、子类构造器
1)规则
-
子类的构造器不能访问父类的私有域,所以必须用的父类的构造器来对这部分的私有域进行初始化,我们可以通过super实现对父类的构造器的调用,使用super调用父类构造器的语句,必须放在子类构造器的第一句。
-
如果子类的构造器没有显示的调用父类的构造器,则将自动的调用默认的构造器,如果父类中没有不带参数的构造器,并且子类的构造器中没有显示的调用父类中的其他构造器,则会报错。
super关键字有两个用途:调用父类的方法
调用父类的构造器
this关键字有两个用途,引用隐式参数
调用该类其他的构造器
四、类的加载顺序
父类的静态字段——>父类静态代码块——>子类静态字段——>子类静态代码块——>父类成员变量(非静态字段)——>父类非静态代码块——>父类构造器——>子类成员变量——>子类非静态代码块——>子类构造器
五、基本数据类型和引用类型比较内容
1、基本数据类型比较
在java中,基本数据类型可以直接比大小。
在JVM中内部,已经具备这样的指令,所以可以直接比较大小。
2、引用类型比较
1)equals
java引用类型不能直接用>或<比较,但可以使用==比较。
这是因为每个类都默认继承了Object类,Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址
2)compare
要完全实现对引用类型的比较,只是有equals()方法是不够的。
可以借用compare方法来实现对对象进> < =的比较操作。
六、equals方法、instance of和对象转型
这里说的对象类型转换,是指存在继承关系的对象,不是任意类型的对象。当对不存在继承关系的对象进行强制类型转换时,java 运行时将抛出 java.lang.ClassCastException 异常。
1.向上类型转换(隐式/自动类型转换)
是从小类型到大类型的转换
2.向下类型转换(强制类型转换)
是从大类型到小类型,这种转换有风险,可能会溢出。
3.instanceof运算符
解决引用对象的类型,避免类型转换的安全问题
在继承链中,我们将子类向父类转换称为“向上转型”,将父类向子类转换称为“向下转型”。很多时候,我们会将变量定义为父类的类型,却引用子类的对象,这个过程就是向上转型。程序运行时通过动态绑定来实现对子类方法的调用,也就是多态性。然而有些时候为了完成某些父类没有的功能,我们需要将向上转型后的子类对象再转成子类,调用子类的方法,这就是向下转型。注意:不能直接将父类的对象强制转换为子类类型,只能将向上转型后的子类对象再次转换为子类类型。也就是说,子类对象必须向上转型后,才能再向下转型。
instanceof可以判断一个引用是否是某个类型或者是某个类型的子类型,它会返回一个布尔值