目录
2.1继承
2.2 继承的好处
2.3 权限修饰符
2.4 单继承、Object
2.5 方法重写
2.6 子类中访问成员的特点
2.7 子类中访问构造器的特点
面向对象1:静态
向对象编程之所以能够能够被广大开发者认可,有一个非常重要的原因,是因为它有三大特征,继承、封装和多态
接下来,使用继承来编写代码,注意观察继承的特点。
public class A{
//公开的成员
public int i;
public void print1(){
System.out.println("===print1===");
}
//私有的成员
private int j;
private void print2(){
System.out.println("===print2===");
}
}
然后,写一个B类,让B类继承A类。在继承A类的同时,B类中新增一个方法print3
public class B extends A{
public void print3(){
//由于i和print1是属于父类A的公有成员,在子类中可以直接被使用
System.out.println(i); //正确
print1(); //正确
//由于j和print2是属于父类A的私有成员,在子类中不可以被使用
System.out.println(j); //错误
print2();
}
}
接下来,我们再演示一下,创建B类对象,能否调用父类A的成员。再写一个测试类
public class Test{
public static void main(String[] args){
B b = new B();
//父类公有成员,子类对象是可以调用的
System.out.println(i); //正确
b.print1();
//父类私有成员,子类对象时不可以调用的
System.out.println(j); //错误
b.print2(); //错误
}
}
来看看继承的内存原理。
子类对象实际上是由子、父类两张设计图共同创建出来的。
所以,在子类对象的空间中,既有本类的成员,也有父类的成员。但是子类只能调用父类公有的成员。
先写一个父类 People,用来设计Teacher和Consultant公有的成员。
public class People{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}
再写两个子类Teacher继承People类,同时在子类中加上自己特有的成员。
public class Teacher extends People{
private String skill; //技能
public String getSkill(){
return skill;
}
public void setSkill(String skill){
this.skill=skill;
}
public void printInfo(){
System.out.println(getName()+"具备的技能:"+skill);
}
}
最后再写一个测试类,再测试类中创建Teacher、Consultant对象,并调用方法。
public class Test {
public static void main(String[] args) {
// 目标:搞清楚继承的好处。
Teacher t = new Teacher();
t.setName("播仔");
t.setSkill("Java、Spring");
System.out.println(t.getName());
System.out.println(t.getSkill());
t.printInfo();
}
}
执行代码,打印结果如下:
只需要记住 :继承可以提高代码的复用性
在刚才使用继承编写的代码中我们有用到两个权限修饰符,一个是public(公有的)、一个是private(私有的),实际上还有两个权限修饰符,一个是protected(受保护的)、一个是缺省的(不写任何修饰符)。
什么是权限修饰符呢?
权限修饰符是用来限制类的成员(成员变量、成员方法、构造器...)能够被访问的范围。
Java语言只支持单继承,不支持多继承,但是可以多层继承
什么是方法重写
当子类觉得父类方法不好用,或者无法满足父类需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。
注意:重写后,方法的访问遵循就近原则。下面我们看一个代码演示
写一个A类作为父类,定义两个方法print1和print2
public class A {
public void print1(){
System.out.println("111");
}
public void print2(int a, int b){
System.out.println("111111");
}
}
再写一个B类作为A类的子类,重写print1和print2方法。
public class B extends A{
// 方法重写
@Override // 安全,可读性好
public void print1(){
System.out.println("666");
}
// 方法重写
@Override
public void print2(int a, int b){
System.out.println("666666");
}
}
接下来,在测试类中创建B类对象,调用方法
public class Test {
public static void main(String[] args) {
// 目标:认识方法重写,掌握方法重写的常见应用场景。
B b = new B();
b.print1();
b.print2(2, 3);
}
}
执行代码,我们发现真正执行的是B类中的print1和print2方法
知道什么是方法重写之后,还有一些注意事项,需要和大家分享一下。
- 1.重写的方法上面,可以加一个注解@Override,用于标注这个方法是复写的父类方法 - 2.子类复写父类方法时,访问权限必须大于或者等于父类方法的权限 public > protected > 缺省 - 3. 重写的方法返回值类型,必须与被重写的方法返回值类型一样,或者范围更小 - 4. 私有方法、静态方法不能被重写,如果重写会报错。
关于这些注意事项( 总结起来就8个字:声明不变,重新实现)
方法重写的应用场景
方法重写的应用场景之一就是:子类重写Object的toString()方法,以便返回对象的内容。
原则:在子类中访问其他成员(成员变量、成员方法),是依据就近原则的
子类中访问构造器的语法规则
首先,子类全部构造器,都会先调用父类构造器,再执行自己。
执行顺序,如下图按照① ② ③ 步骤执行:
子类访问构造器的应用场景
如果不想使用默认的super()
方式调用父类构造器,还可以手动使用super(参数)
调用父类有参数构造器。
时候我们也需要访问自己类的构造器。语法如下
this(): 调用本类的空参数构造器 this(参数): 调用本类有参数的构造器
this和super的用法在总结一下 访问本类成员:
this.成员变量 //访问本类成员变量
this.成员方法 //调用本类成员方法
this() //调用本类空参数构造器
this(参数) //调用本类有参数构造器
访问父类成员:
super.成员变量 //访问父类成员变量
super.成员方法 //调用父类成员方法
super() //调用父类空参数构造器
super(参数) //调用父类有参数构造器
注意:this和super访问构造方法,只能用到构造方法的第一句,否则会报错。