Java继承特性

格式

通过 extends 关键字,可以声明一个子类继承另外一个父类,定义格式如下:

【修饰符】 class 父类 {...
}【修饰符】 class 子类 extends 父类 {...
}

继承演示,代码如下:

/** 定义动物类Animal,做为父类*/
class Animal {// 定义name属性String name; // 定义age属性int age;// 定义动物的吃东西方法public void eat() {System.out.println(age + "岁的" + name + "在吃东西");}*/
class Cat extends Animal {// 定义一个猫抓老鼠的方法catchMousepublic void catchMouse() {System.out.println("抓老鼠");}
}/** 定义测试类*/
public class ExtendDemo01 {public static void main(String[] args) {// 创建一个猫类对象Cat cat = new Cat()// 为该猫类对象的name属性进行赋值cat.name = "Tom";// 为该猫类对象的age属性进行赋值cat.age = 2;// 调用该猫的catchMouse()方法cat.catchMouse();// 调用该猫继承来的eat()方法cat.eat();}
}演示结果:
抓老鼠
2岁的Tom在吃东西

继承的特点一:成员变量

父类成员变量私有化(private)
  • 父类中的成员,无论是公有(public)还是私有(private),均会被子类继承

  • 子类虽会继承父类私有(private)的成员,但子类不能对继承的私有成员直接进行访问,可通过继承的get/set方法进行访问

代码如下:

/** 定义动物类Animal,做为父类*/
class Animal {// 定义name属性private String name; // 定义age属性public int age;// 定义动物的吃东西方法public void eat() {System.out.println(age + "岁的" + name + "在吃东西");}
}/** 定义猫类Cat 继承 动物类Animal*/
class Cat extends Animal {// 定义一个猫抓老鼠的方法catchMousepublic void catchMouse() {System.out.println("抓老鼠");2}
}/** 定义测试类*/
public class ExtendDemo01 {public static void main(String[] args) {// 创建一个猫类对象Cat cat = new Cat()// 为该猫类对象的name属性进行赋值//cat.name = "Tom";// 编译报错// 为该猫类对象的age属性进行赋值cat.age = 2;// 调用该猫的catchMouse()方法cat.catchMouse();// 调用该猫继承来的eat()方法cat.eat();}
}
父子类成员变量重名

我们说父类的所有成员变量都会继承到子类中,那么如果子类出现与父类同名的成员变量会怎么样呢?

父类代码:

public class Father {public int i=1;private int j=1;public int k=1;public int getJ() {return j;}public void setJ(int j) {this.j = j;}
}

子类代码:

public class Son extends Father{public int i=2;private int j=2;public int m=2;
}	

现在想要在子类Son中声明一个test()方法,并打印这些所有变量的值,该如何实现?

public class Son extends Father{public int i=2;private int j=2;public int m=2;public void test() {System.out.println("父类继承的i:" + super.i);//1System.out.println("子类的i:" +i);//2
//		System.out.println(super.j);System.out.println("父类继承的j:" +getJ());//1System.out.println("子类的j:" +j);//2System.out.println("父类继承的k:" +k);//1System.out.println("子类的m:" +m);//2}	
}	

结论:

(1)当父类的成员变量私有化时,在子类中是无法直接访问的,所以是否重名不影响,如果想要访问父类的私有成员变量,只能通过父类的get/set方法访问;

(2)当父类的成员变量非私有时,在子类中可以直接访问,所以如果有重名时,就需要加“super."进行区别

使用格式:

super.父类成员变量名

以上test()调用结果:

public class TestSon{public static void main(String[] args){Son s = new Son();s.test();}
}
父类继承的i:1
子类的i:2
父类继承的j:1
子类的j:2
父类继承的k:1
子类的m:2

继承的特点二:成员方法

我们说父类的所有方法子类都会继承,但是当某个方法被继承到子类之后,子类觉得父类原来的实现不适合于子类,该怎么办呢?我们可以进行方法重写 (Override)

方法重写

比如新的手机增加来电显示头像的功能,代码如下:

class Phone {public void sendMessage(){System.out.println("发短信");}public void call(){System.out.println("打电话");}public void showNum(){System.out.println("来电显示号码");}
}//智能手机类
class NewPhone extends Phone {//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能public void showNum(){//调用父类已经存在的功能使用supersuper.showNum();//增加自己特有显示姓名和图片功能System.out.println("显示来电姓名");System.out.println("显示头像");}
}public class ExtendsDemo06 {public static void main(String[] args) {// 创建子类对象NewPhone np = new NewPhone()// 调用父类继承而来的方法np.call();// 调用子类重写的方法np.showNum();}
}

小贴士:这里重写时,用到super.父类成员方法,表示调用父类的成员方法。

注意事项:

  1. @Override:写在方法上面,用来检测是不是有效的正确覆盖重写。这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。建议保留

  2. 必须保证父子类之间方法名相同,参数列表相同

  3. 返回值子类的重写方法的返回值类型要比父类被重写的方法返回值类型要小或者相同(子类与父类范围)(小于其实就是是它的子类,例如:Student < Person)。

  4. 异常子类的重写方法抛出异常类要比父类被重写的方法抛出异常类要小或者相同(子类与父类范围),或者不抛出

  5. 权限修饰符子类的重写方法的权限修饰符要比父类被重写的方法权限修饰符要大或者相同

注意:如果返回值类型是基本数据类型和void,那么必须是相同
小扩展提示:public > protected > 缺省 > private

  1. 几种特殊的方法不能被重写
  • 静态方法不能被重写
  • 私有private等在子类中不可见的方法不能被重写
  • final方法不能被重写

继承的特点三:单继承限制

  1. Java只支持单继承,不支持多继承。
//一个类只能有一个父类,不可以有多个父类。
class C extends A{} 	//ok
class C extends AB...	//error
  1. Java支持多层继承(继承体系)。
class A{}
class B extends A{}
class C extends B{}

顶层父类是Object类。所有的类默认继承Object,作为父类。

  1. 子类和父类是一种相对的概念。

    例如:B类对于A来说是子类,但是对于C类来说是父类

  2. 一个父类可以同时拥有多个子类

继承的特点四:构造方法

当类之间产生了关系,其中各类中的构造方法,又产生了哪些影响呢?

首先我们要回忆两个事情,构造方法的定义格式和作用。

  1. 构造方法的名字是与类名一致的。

    所以子类是无法继承父类构造方法的。

  2. 构造方法的作用是初始化实例变量的,而子类又会从父类继承所有成员变量

    所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的实例初始化方法,父类成员变量初始化后,才可以给子类使用。代码如下:

    class Fu {private int n;Fu(){System.out.println("Fu()");}
    }
    class Zi extends Fu {Zi(){// super(),调用父类构造方法super();System.out.println("Zi()");}  
    }
    public class ExtendsDemo07{public static void main (String args[]){Zi zi = new Zi();}
    }
    输出结果:
    Fu()
    Zi()
    

子类对象实例化过程中必须先完成从父类继承的成员变量的实例初始化,这个过程是通过调用父类的实例初始化方法来完成的。

  • super():表示调用父类的无参实例初始化方法,要求父类必须有无参构造,而且可以省略不写;
  • super(实参列表):表示调用父类的有参实例初始化方法,当父类没有无参构造时,子类的构造器首行必须写super(实参列表)来明确调用父类的哪个有参构造(其实是调用该构造器对应的实例初始方法)
  • super()和super(实参列表)都只能出现在子类构造器的首行


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部