- 1.Java类的继承
- 类继承的实现
- 方法覆盖(重写)
- super关键字
- 调用父类构造方法
- 子类构造方法
- 构造方法的调用过程
- 2.封装性 访问修饰符
- 类访问权限
- 类成员访问权限
- 3.防止类扩展和方法覆盖
- 4.抽象类
- 5.对象转换与多态(重点)
- 对象转换
- instanceof运算符
- 多态与动态绑定
Java语言中实现类的继承用到extends关键字
格式:[public] class SubClass extends SuperClass //类体定义
类继承的几点说明:
- 子类继承父类中的非private的成员变量与方法
- 定义类时不加extends关键字,则默认为Object类的直接子类
- Java仅支持单重继承
子类中可以定义与父类中名字、参数列表、返回值类型都相同的方法,这时子类方法称为覆盖或重写了父类的方法
为防止覆盖方法时写错方法头,可在方法前加==@Override==注解,表示其后方法必须覆盖父类的一个方法,如果注解后方法没有覆盖父类的方法,编译器将给出错误。
关于方法覆盖的注意事项:
- 父类的private方法不能覆盖,如果子类定义了一个方法在父类中是private的,则这是两个不相关的方法。
- 父类中的static方法可以被继承,但不可以覆盖,如果子类定义了一个相同的方法,则父类中的方法被隐藏,但仍可以通过类名.方法名()调用
public class class1 {
public static void method1(){
System.out.println(666);
}
}
public class class2 extends class1{
}
public class class3 {
public static void main(String[] args) {
class2.method1(); // 输出666
}
}
super关键字
子类中可以使用super关键字来引用当前对象的父类对象,应用场景可能为如下3种情况
- 在子类中调用父类被覆盖的方法,格式:super.methodName([paramlist])
- 子类调用父类构造方法 super([paramlist])
- 在子类中调用父类被隐藏的成员变量 super.variableName
子类不能继承父类的构造方法,java语言规定,在创建子类对象时,必须先创建该类的所有父类,因此,在编写子类的构造方法时,必须保证他能调用父类的构造方法,
调用父类的构造方法有两种方式
- 使用super关键字
super指直接父类的构造方法,不能通过super调用间接父类的构造方法,如super.super()是不合法的 - 调用父类默认构造方法
子类构造方法若没有使用super调用父类构造方法,则编译器会自动在子类的构造方法第一句加上super(),即调用父类无参构造,若父类中没有无参构造,则编译器会报错.
public class class1 {
public class1(int a){
}
}
public class class2 extends class1{
public class2(){ //此处产生编译错误,默认super()时找不到父类的空参构造。
}
}
构造方法的调用过程
任何情况下,创建一个类的实例,将会沿着继承链调用所有父类的构造方法,叫做构造方法链,创建子类对象时,系统首先调用所有父类的构造方法,包括根类Object类的构造方法.
2.封装性 访问修饰符 类访问权限- public修饰,可被任何其他类使用
- 缺省修饰仅能被同一包中的类使用
- private修饰:私有成员只能被这个类本身访问,外界不能访问(最体现对象的封装性)。
- 缺省:一般称为包可访问,成员可被类本身和同包中类访问。
- protected修饰:成员可被类本身、同包类。以及子类(包括同包与不同包)访问。
- public修饰:可被任何其他类访问,前提是该类是可访问的。
- final修饰类
一个类使用final修饰,该类成为最终类,最终类不能被继承,尝试继承最终类会发生编译错误,例如
final class A{
}
class B extends A{ //这里发生错误
}
定义final类隐含定义了其中的所有方法都是final都,因此类不能被继承,也不能覆盖其中的方法。
2. final修饰方法
如果一个方法被final修饰,则该方法不能被子类覆盖,否则发生编译错误,例如
class A{
public final void method(){}
}
class B extends A{
public void method(){} //此处发生编译错误
}
- final修饰变量
变量被final修饰,则为常值变量,一旦赋值变不能改变
编译时常量:使用static final组合定义类常量,编译器可以将该变量带入任何用到他的表达式中,减轻运行时负担。
尝试改变final变量会产生编译错误,例如
class Test{
public static final int size = 50;
public void methodA(final int i){
i = i + 1; // 该语句产生编译错误,不能改变final变量值
}
}
注意:如果final修饰一个引用变量,表示该变量的引用(地址)不能改变,一旦引用被初始化指向一个对象,就无法使他指向另一个对象,但对象本身是可以改变的,java没有提供任何机制使对象本身保持不。
4.抽象类抽象类是包含抽象方法的类,类前用abstract修饰
定义抽象方法需要在方法前加上abstract修饰符,抽象方法只有方法的声明,没有实现,包含抽象方法的类必须定义为抽象类。
抽象方法的声明后用分号结束,而不需要大括号。
public abstract class Shape(){
String name;
public Shape(){}
public Shape(String name){
this.name = name;
}
public abstract double getArea();
public abstract double getPerimeter();
}
抽象类中可以定义非抽象方法,可以创建抽象类的子类,子类还可以是抽象类,只有非抽象的子类才能使用new创建该类的对象,抽象类中可以没有抽象方法,但仍需要被子类继承才能实例化。
注意:因abstract类必须被继承而final类不能被继承,所以两个修饰符不能在定义类时同时使用。
子类是父类的特殊化,每个子类的实例都是父类的实例,但反过来不成立,子类和父类对象在一定条件下可以相互转换,成为对象转换或造型,有自动转换和强制转换之分。
- 向上转换(自动):子类(类或接口对象) -> 父类(直接或间接)
可以将任何对象转换为继承链中任何一个父类对象,包括Object - 向下转换(强制): 转换运算符"()"
public class CastDemo{
public static void main(String[] args) {
Employee emp = new Employee();
Person p = emp; //自动类型转换
emp = (Employee) p; //强制类型转换
}
}
注意:不是任何情况下都可以进行强转,例如
public class Example{
public static void main(String[] args) {
Person p = new Person();
Employee employee = (Employee) p; //不能把父类对象强制转换为子类对象
}
}
提醒:
- 上述代码要将父类转换为子类对象,代码编译时没有错误,但运行时会抛出ClassCastException异常
- 将父类对象转换为子类,必须要求父类对象是由子类构造方法生成的(包括子类型向上转型为父类型).
- 当将一个子类对象转换为父类对象时,该引用可以调用重写父类的或从父类继承的方法,这些方法都不是父类的方法,但它不再能看到子类中的特有的方法。
用于测试一个实例是否是某种类型或其父类的实例 格式:variable instanceof TypeName。 该表达式返回逻辑值
public class E{
public static void main(String[] args) {
Fruit fruit = new Apple();
Orange orange = new Orange();
fruit instanceof Fruit; //true
fruit instanceof Orange; //false
orange instanceof Fruit; //true
orange instanceof Orange; //true
}
}
多态与动态绑定
java语言支持两种类型的多态:
- 静态多态:也称编译时多态,通过方法重载实现。
- 动态多态:也称运行时多态,通过方法覆盖(重写)实现。
将方法调用与方法体关联起来称方法绑定。
程序执行前绑定叫前期绑定,如C语言的函数调用
程序运行时根据对象类型进行绑定,称后期绑定或动态绑定。Java除static和final方法都是动态绑定。
对重载的方法,Java运行时系统根据传递给方法的参数个数与类型确定调用哪个方法,
对覆盖的方法,运行时系统根据对象类型决定调用哪个方法。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)