继承

1 继承的概述

  • 先观察如下代码
package java007;

/**
 * 2017/9/9
 * 说明:学生
 */
public class Student {
    String name;
    int age;

    public void study(){
        System.out.print("我叫"+name+",今年"+age+",我是一名学生,正在学习");
    }
}
package java007;

/**
 * 2017/9/9
 * 说明:工人
 */
public class Worker {
    String name;
    int age;

    public void work(){
        System.out.print("我叫"+name+",今年"+age+",我是一名工人,正在工作");
    }
}
package java007;

/**
 * 2017/9/9
 * 说明:
 */
public class StudentAndWorkderTest {
    public static void main(String[] args) {
        Student s = new Student();
        s.name = "张三";
        s.age = 15;
        s.study();

        Worker w = new Worker();
        w.name = "李四";
        w.age = 34;
        w.work();
    }
}
    • 我们可以发现学生类和工人类中都有姓名和年龄属性,属于重复字段,那么如何解决?,且看如下代码。  
package java007;

/**
 * 2017/9/9
 * 说明:
 */
public class Person {
    String name;
    int age;
}
package java007;

/**
 * 2017/9/9
 * 说明:学生
 */
public class Student extends Person {

    public void study(){
        System.out.print("我叫"+name+",今年"+age+",我是一名学生,正在学习");
    }
}
package java007;

/**
 * 2017/9/9
 * 说明:工人
 */
public class Worker extends Person{

    public void work(){
        System.out.print("我叫"+name+",今年"+age+",我是一名工人,正在工作");
    }
}
package java007;

/**
 * 2017/9/9
 * 说明:
 */
public class StudentAndWorkderTest {
    public static void main(String[] args) {
        Student s = new Student();
        s.name = "张三";
        s.age = 15;
        s.study();

        Worker w = new Worker();
        w.name = "李四";
        w.age = 34;
        w.work();
    }
}

 

  • 继承的好处:
    • ①提高了代码的复用性。
    • ②让类与类之间产生关系,给第三个特征多态提供了前提。  

 

2 继承的特点

  • Java中支持单继承(一个子类只能有一个父类),不直接直接多继承,支持多层继承。

 

3 super关键字

  • 当本类的成员变量和局部变量同名的时候,使用this区分。
  • 当子父类的成员变量同名的时候,使用super区分父类。
  • this和super的用法很相似。

 

  • 示例1:本类的成员变量和局部变量同名的时候
package java007;

/**
 * 2017/9/9
 * 说明:
 */
class Fu{
    private int age = 20;
    public void show(){
        int age = 10;
        System.out.print("局部变量:"+age+",成员变量:"+this.age);

    }
}
public class ExtendsDemo {
    public static void main(String[] args) {
        Fu f = new Fu();
        f.show();
    }

}

    • 解释说明
      • ①先使用javac ExtendsDemo.java命令将ExtendsDemo编译成class文件,当然,顺便将Fu.java也编译成class文件。
      • ②使用java ExtendsDemo命令,虚拟机会从方法区中,将main()方法识别,并加载到栈中。
      • ③执行了new Fu();会在堆内存中开辟一个空间,(将Fu(){}加载到栈内存中,因为这一部分对本程序而言不是很重要,所以省略相关描述),用来存储对象,并初始化age=0。然后执行到private int age = 20;的时候,就将20赋值给age,此时age在堆内存中是20。
      • ④Fu f = new Fu();main()方法所在的栈内存中,开辟了一个引用变量f,然后将堆内存中的对象的地址赋值给f,那么此时f就指向堆内存中的对象。
      • ⑤f.show();从方法区将show()方法加载到栈中,此时,注意的是,show()方法内部就包含了this关键字,同时f变量的地址值给了this,因为this表示的是当前对象的引用,而调用show()方法的恰恰是f,所有this和f此时的值是相同的,那么show()方法也指向了堆内存中的对象,然后在show()方法内部开辟了一个age变量,这个age变量是栈内存中show()方法内部的局部变量,而想获取堆内存中的age变量,只能通过show()方法内存的this关键字了。  

 

  • 示例2:子类和父类的成员变量不同的时候
package java007;

/**
 * 2017/9/9
 * 说明:
 */
class Fu{
     int age1 = 20;

}
class Zi extends Fu{
    int age2 = 30;
    public void show(){
        System.out.print(age1+" "+age2);
    }
}
public class ExtendsDemo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }

}

    • 解释说明:通过上面的程序貌似可以这样解释,第一,变量名是不一样的,第二,子类是继承了父类,而子类中没有age1成员变量,所以从父类中继承(拷贝)了age1成员变量。  

 

  • 示例3:子父类的成员变量相同的时候
package java007;

/**
 * 2017/9/9
 * 说明:
 */
class Fu{
     int age = 20;

}
class Zi extends Fu{
    int age = 30;
    public void show(){
        System.out.print(age);
    }
}
public class ExtendsDemo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }

}
package java007;

/**
 * 2017/9/9
 * 说明:
 */
class Fu{
     int age = 20;

}
class Zi extends Fu{
    int age = 30;
    public void show(){
        System.out.print(age+" "+super.age);
    }
}
public class ExtendsDemo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }

}
    • 解释说明:通过上面的程序貌似可以这样解释,子类和父类成员变量相同的时候,子类可以将父类相同成员变量覆盖,其实不然,且看下面分解。  

 

4 函数覆盖(重写)

  • 示例:子父类中的方法名不同
package java007;

/**
 * 2017/9/10
 * 说明:
 */
class Fu{
    public void show1(){
        System.out.print("Fu的show1方法");
    }
}
class Zi extends Fu{
    public void show2(){
        System.out.print("Zi的show2方法");
    }
}
public class ExtendsDemo2 {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show1();
        z.show2();
    }
}

 

  • 示例:子父类中的方法名同名
package java007;

/**
 * 2017/9/10
 * 说明:
 */
class Fu{
    public void show(){
        System.out.print("Fu的show方法");
    }
}
class Zi extends Fu{
    public void show(){
        System.out.print("Zi的show方法");
    }
}
public class ExtendsDemo2 {
    public static void main(String[] args) {
        Zi z = new Zi();
       z.show();
    }
}

 

  • 当子类中出现成员函数和父类的一样的时候,会运行子类的成员函数,从表现上看。好像是子类的成员函数“覆盖”了父类的成员函数,这种现象,被称为重写或者覆盖。
  • 函数的两个特性:
    • 重载。同一个类中。
    • 覆盖。子类中,也称为重写。    
  • 重写的注意事项:子类方法覆盖父类方法时,子类方法的权限必须>=父类方法的权限。

 

5 子类的实例化过程

  • 示例:
package java007;

/**
 * 2017/9/10
 * 说明:
 */
class Fu{
   public Fu(){
       System.out.println("Fu的构造方法");
   }
}
class Zi extends Fu{
    public Zi(){
        System.out.println("Zi的构造方法");
    }

}
public class ExtendsDemo2 {
    public static void main(String[] args) {
        Zi z = new Zi();

    }
}

 

  • 在子类构造对象的时候,发现,访问子类构造函数的时候,父类也运行了。这是为什么?因为,在子类构造方法中的第一行有一个默认的隐式语句:super();j如下代码所示。 
package java007;

/**
 * 2017/9/10
 * 说明:
 */
class Fu{
   public Fu(){
       System.out.println("Fu的构造方法");
   }
}
class Zi extends Fu{
    public Zi(){
        super();//调用的是父类的默认的空参数构造函数
        System.out.println("Zi的构造方法");
    }

}
public class ExtendsDemo2 {
    public static void main(String[] args) {
        Zi z = new Zi();

    }
}

  • 示例:
package java007;

/**
 * 2017/9/10
 * 说明:
 */
class Fu{
    public Fu(){
        show();
    }
    public void show(){
        System.out.print("fu show");
    }

}
class Zi extends Fu{
   int num = 8;
   public Zi(){

   }
   public void show(){
       System.out.print("zi show:"+num);
   }


}
public class ExtendsDemo2 {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();

    }
}

    • 解释:先将父类进行初始化,再将子类进行初始化。  

 

6 final关键字

  • final可以修饰类、方法和变量。
  • final修饰的类不可以被继承。
  • final修饰的方法不可以被重写。
  • final修饰的变量是一个常量,只能被赋值一次。
  • 内部类只能访问被final修饰的局部变量。

 

  • 示例:final修饰变量,变为常量
class Person{
    private final int age = 10;
}
  • 示例:final修饰变量,变为常量
class Person{
    private final int age ;
    {
        age = 20;
    }
}
  • 示例:final修饰变量,变为常量
class Person{
    private final int age ;
    public Person(int age){
        this.age = age;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值