目录
参考《java2实用教程》
个人java笔记,为了日后学习方便,用于记录所学的东西,有误的话还希望加以指正,感谢!!!
Java基础总结2
五、子类与继承
1. 子类与父类
- 继承的概述
假如父类是一个动物类,子类是一个🐟类,鱼必须具有动物所具有的一些共有属性,而这些属性可以在鱼类中不必再写出来,直接复用动物类的属性行为,然后再加上自己的部分属性行为即可- 继承是一种由已有的类创建新类的机制。利用继承,可以先定义一个共有属性的一般类,根据该一般类再定义具有特殊属性的子类,子类继承一般类的属性和行为,并根据需要增加它自己新的属性和行为
- 被继承的类称为父类(超类),由继承得到的类称为子类,子类只能有一个父类,而父类可以有多个子类
- 子类
在类的声明中通过关键字extends来声明一个子类
class 子类名 extends 父类名 {
……
}
- 类的树形结构
如果C是B的子类,B是A的子类,则称C是A的子孙类,在java中的类按照继承关系形成树结构,根节点是Object类(java.lang包中),Object类是所有类的祖宗类,其他类都是Object的子孙类
2. 子类的继承性
所谓子类继承父类的方法/成员作为子类中的一个方法/成员,就像它们是在子类中直接定义了一样,可以被子类中自己定义的任何实例方法调用/操作。如果子类中的实例方法不能操作父类的某个成员或方法,该成员/方法就没有被继承
- 子类和父类在同一包中的继承性
- 在同一包中时子类自然的继承了父类中不是private的 成员变量/成员方法 作为自己的 成员变量/成员方法,继承的变量或方法的访问权限保存不变
- 子类和父类在不同包中的继承性
- 子类和父类在不同包中时,父类中的private和友好访问权限的成员变量不会被子类继承,也就是,子类只继承父类中protected和public访问权限的成员变量/成员方法
protected
- protected
- protected的访问权限:类内、包内和子类
- 对于子类D自己声明的protected成员变量和方法,只要Other类和D类子啊同一个包中,D类创建的对象就可以访问这些protected成员变量和方法
- 对于子类D从父类继承的protected成员变量或方法,需要追溯到这些protected成员变量或方法所在的祖先类,只要存在祖先类和other类在同一个包中,D类创建的对象就能访问继承的protected变量和方法
3. 子类与对象
- 子类对象的空间分配
- 子类构造方法创建一个子类对象时,不仅子类的成员变量,而且父类的成员变量也都分配了内存空间,但只将其中一部分,即子类继承的那部分成员变量,作为分配给子类对象的变量。即父类中private成员变量分配了内存空间,也不作为子类对象的变量。
- 子类还有一部分方法是从父类继承的,这部分方法却可以操作这部分未被继承的变量。因而分配空间给未继承的变量是有必要的。
instanceof
- 关于instanceof运算符
- Java独有的双目运算符
- 判断instanceof左边的对象是否是由右边的类所创造的,如果是,运算结果位true,否则为false
student instanceof People
4. 成员变量的隐藏和方法的重写
-
成员变量的隐藏
- 在编写子类时,如果所声明的成员变量的名字和从父类继承来的成员变量的名字相同,子类就会隐藏所继承的成员变量
- 隐藏成员变量的特点:
- 子类自己定义的方法操作子类中(与父类同名的成员变量)重新声明的成员变量
- 子类继承的方法所操作的成员变量一定是被子类继承或隐藏的成员变量
-
方法重写
- 重写的方法的名字、参数个数、参数的类型和父类的方法完全相同
- 重写的目的:
- 子类通过方法的重写可以隐藏继承的方法,子类通过方法的重写可以把父类的状态和行为改变为自身的状态和行为
- 如果子类想使用被隐藏的方法或成员变量,必须使用关键字super
- 如果子类的方法名与相同,参数列表相同,必须覆盖重写,否则会产生编译错误:
父类: float computer (float x ,float y) { return x+y; } 子类: double computer(float x ,float y) { return x*y; }
这里会出现编译错误,父类方法的返回值类型是float,而子类是 double,这样子类就无法隐藏继承的方法,这样是不允许的
- 重写的方法类型可以是父类方法的子类型,也就是重写的方法类型不一定完全与父类的一致,例如:
父类: class A{ Object get(){ return null; } } 子类: class B extends A{//已知Integer类是Object的子类 Integer get(){ return new Integer(100); } }
这样是编译正确的
- 重写时的访问权限问题
- 重写父类的方法时不允许降低访问权限,但是可以提高访问权限
- 例如:父类A方法的访问权限为protected,子类重写A方法时的访问权限是public,这样是没有错的。
- 访问权限由高到低:public、protected、友好的、private
5. super关键字
- 用super操作被隐藏的成员变量和方法:
super.x;super.y();
//这就是用super分别调用被子类隐藏的成员变量x和方法y() - 用super调用父类的构造方法
- 当用子类的构造方法来创建一个子类对象时,子类的构造方法总是先调用父类的某个构造方法,子类构造方法没有明显的指明是哪个构造方法时,子类就调用父类不带参数的构造方法
- 子类不继承父类的构造方法,因此子类在器构造方法中需要使用super来调用父类的构造方法,而且super必须是子类构造方法中的头一条语句,如果子类中没有明显的用super来调用一个构造方法,则默认子类构造方法中的最开始调用了
super();
- 如果类里面定义了一个或多个构造方法时,那么java不提供默认的构造方法(不带参数的构造方法),因此在父类中定义多个构造方法时,应当包括一个无参数列表的构造方法,以方子类省去super时出现的错误
6. final关键字
final关键字可以修饰类、成员变量和成员方法中的局部变量
- final类
- 用final修饰的类,final类不能被继承(无子类)
final class{……}
- 目的:出于安全性考虑,例如String类,java不允许用户扩展String类,因此java将它修饰为final类
- final方法
- final修饰的方法不能被重写,也就是子类必须完全、原封不动地继承父类中被final修饰的方法
- 常量
- 如果成员变量或局部变量被修饰为final类,那它就是常量。由于常量在运行期间不允许再发生变化,所以常量在声明时没有默认值,因而程序在声明常量时必须指定该常量的值
final double PI = 3.1415926;
- 如果成员变量或局部变量被修饰为final类,那它就是常量。由于常量在运行期间不允许再发生变化,所以常量在声明时没有默认值,因而程序在声明常量时必须指定该常量的值
7. 对象的上转型对象
- 概念:假设Animal类时Tiger类的父类,当用子类创建一个对象,并把这个对象的引用放到父类中时,陈父类引用的对象是子类引用对象的上转型对象:
例1:
Animal a;
a = new Tiger;
例2:
Animal a;
Tiger b = new Tiger();
a = b;
上述当中a是b的上转型对象
- 上转型对象的实体是子类创建的,但上转型对象会失去一些原对象的一些属性和功能
- 上转型对象不能操作子类新增的成员变量,不能调用子类新增的方法
- 上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类重写的实例方法。
- 如果子类重写了父类的某个实例方法之后,当上转型对象调用这个实例方法时一定是调用了子类重写的实例方法。
- 注意:
- 可以将对象的上转型对象再强制转换到一个子类对象,这时,该子类对象又具备了子类所有的属性和功能。
- 不可以将父类创建的对象的引用赋值给子类声明的对象(不能说动物是老虎)
- 如果子类重写了父类的静态方法,那么子类对象的上转型对象不能调用子类重写的静态方法,只能调用父类的静态方法。
Animal a;//Animal是父类,Tiger是子类
a = new Tiger();
Tiger tiger = (Tiger)a;
//把上转型对象强制转换称为子类对象,
//于是a又具有Tiger类的全部属性和功能
8.继承与多态
- 多态:
当一个类具有很多子类时,并且这些子类都重写了父类中的某种方法,那么当把子类创建的对象的引用放到一个父类对象中,所得到的上转型对象调用这个方法时就可能具有多种形态。因为不同的子类重写时可能会产生不同的行为。
class animal {
void cry(){}
}
class dog{
void cry(){System.out.println("汪汪汪");}
}
class cat{
void cry(){System.out.println("喵喵喵");}
}
public class main(){
public static void mian(String args[]){
animal a ;
a = new dog(); a.cry();//汪汪汪
a = new cat(); a.cry();//喵喵喵
}
}
9.abstract类和abstract方法
- 抽象方法与抽象类的表示形式:
抽象类:
abstract class A {
……
}
抽象方法:
abstract 类型 方法名(参数列表);
abstract int min(int x, int y);
abstract 方法只允许声明,不允许实现,没有方法体,不允许使用final和abstract同时修饰一个类或者一个方法,也不允许static修饰abstract方法,即abstract方法必须时实例方法。