• Java继承


    超类与子类

    1.概念

    Java用关键字extends表明正在构造的新类派生于一个已经存在的类。已存在的类称为超类(superclass),基类(base class)或父类(parent class);新类称为子类(subclass),派生类(derived)或孩子类(child class)。Java程序员一般使用术语超类和子类。

    超类相比于子类并没有优于子类或拥有比子类更多的功能。相反,子类可能封装了更多的数据或功能。

    一个例子:

    class Employee {
        private int id;
        private String name;
        private double salary;
        public Employee(String name,double salary){
           ...
        }
        public String getName() 
        public double getSalary() {
            return salary;
        }
        public int getId() 

    这样一个公司员工的类。属性有id,名字,薪水。

    公司有经理,经理的待遇与普通员工有一些差异,不过差异不大。比如,经理在干完活后可以领取奖金,普通员工只能领取薪水,其他都一样。此时,面对这样一点小小的差异,我不愿意从头到尾编写一个新的类,那么就要用到继承。

    为经理定义一个新类Manager,增加一点新功能,然后重用Emploee的部分代码即可,将其所有域保留下来。两者之间存在一种明显的关系,is-a关系。即每名经理也是一个员工。

    每个子类也是一个超类。is-a关系是继承的一个明显特征。

    增加奖金域:

    public class Manager extends Emploee{
        private double bonus;
        ....
        public double setBonus(double bonus){
            this.bonus = bonus;
        }
        ....
    }

    这样,子类就可以使用超类一些方法,因为Manager类自动继承了Emploee中的这些方法。但Emploee却不能使用setBonus()方法。

    2.覆盖方法

    事实上,子类继承自父类的方法,有些不太适用于子类,例如,父类的getSalary()方法,返回薪水。经理的薪水是怎样的呢?显然,是原来的薪水加奖金。

    使用下面的方法来覆盖父类的getSalary()方法:

    public double getsalary(){
        double baseSalary = super.getSalary();
        return baseSalary + bonus;
    }

    这里用到了super关键字。直接return salary+bonus;这样的语句是不行的。

    原因:Manager的getSalary()方法不能直接访问超类的私有域。只有Emploee类的方法才能访问。

    因此,借助super调用超类的方法,可帮助我们访问超类中的域。

    3.子类构造器

    同样需要借助super构造器。因为需要访问超类私有域。

    public Manager(String name,double salary,int id){
        super(name,salary,id);
        bonus = 0;    
    }

    这样简写,当超类构造器有对应的参数的构造方法时,即会调用那个构造函数。若无,会产生错误。

    如果子类没有显示的使用super调用超类的构造器,则自动调用超类的默认(无参数)构造器。

    4.多态

    现有一经理,两员工,输出薪水。

    Employee[] staff = new Employee[3];
    Manage boss = new Manager(); 
    staff[0] = boss;
    staff[1] = new Employee();
    staff[2] = new Employee();
    for (Employee e:staff){
      system.out.println(e.getSalary());
    }

    这段代码能够正确的输出薪水。jvm在运行时能够自动的选择调用正确的方法,引用超类时调用超类方法,引用子类时调用子类方法。虚拟机知道e实际引用的对象类型,正确调用方法。

    一个对象变量能够指示不同多种实际类型的现象称为多态。

    在运行时能够自动选择调用哪个方法的现象称为动态绑定。

    如上例子,staff[0]赋值给e,即将一个子类的对象赋值给超类,e即引用了两种实际类型。这里,编译器将staff[0]看做Emploee对象,因而不能这样调用:staff[0].setBonus(5000);可以这样调用:boss.setBonus(5000);

    不能将超类的引用赋值给子类变量,原因是显而易见的,相反的is-a关系。

    5.阻止继承

    有时候,希望阻止某个类定义子类。不允许拓展的类称为final类。如果在定义类时使用了而final修饰符,就表明这个这个类是final类。

    public final class Executive extends Manager{
    ...
    }

    类中的方法也可以定义为final方法,这样做子类就不能覆盖该方法。

    public final String getName()

    6.抽象类和抽象方法

    有时候,希望父类更加通用,派生出多种多样的子类,并且只将父类作为派生其他类的基类,而不作为想使用的特定的实例类。

    这时,即可使用抽象类。

    抽象类中可以有抽象方法,抽象方法只有声明而没有实现。如:

    public abstract class Person{
        ...
        public abstract String getDescription();
    }

    包含一个或多个抽象方法的类必须声明为抽象类

    抽象类的实现在子类中,有以下两种方式:

    1)在抽象类中定义部分抽象方法或不定义抽象方法,那么就必须将子类声明为抽象类。

    2)在抽象类中定义全部抽象方法,子类就不是抽象的了

    抽象类不能被实例化

    可以定义一个抽象类的对象,但它只能引用非抽象类子类的对象。

    Person p = new Student();

    p引用的是子类Student的对象。

    7.可见性控制

    1)仅对本类可见---private

    2)对所有类可见---public

    3)对本包和所有子类可见---protected

    4)对本包可见---默认

    Object:所有类的超类

    Object类是java中所有对象的超类,每个类都继承自Object。

    以下是Object类的一些方法

    1.equals方法

    作用:检测一个对象是否等于另一个对象。实际上是判断两个对象是否具有相同的引用。

    有些情况下,需要重写该方法,即有时检测而两个对象状态的相等性而不是引用。

    覆盖equal方法的一种实现

    1)显示参数命名为otherObject

    2)检测this是否与otherObject引用同一对象,是返回true,否继续

    if(this==otherObject) return true;

    3)检测otherObject是否为null,是返回false,否继续

    if(otherObject==null) return false;

    4)比较this与otherObject是否为同一个类,(如果equals语义在每个子类中有所改变,使用getClass()方法;一致则使用instanceof),不是返回false,是继续

    if(getClass()!=otherObject.getClass()) return false;

    if(!(otherObject instance ClassName)) return false;

    这里是考虑由超类决定相等概念还是由子类决定相等概念。

    5)将otherObject转换成相应的类类型变量,比较所有域。

    ClassName other = (ClassName) otherObject

    .....

    2.hashcode方法

    hashcode是由对象导出的一个整形值。散列码是没有规律的。如果x和y是两个不同的对象,那么它们的散列值基本不会相同。

    相同的字符串拥有相同的散列码。例如:String s ="OK",String t =new String("OK"), s.hashcode()和t.hashcode()返回结果都是2524。这是因为字符串散列码由内容导出。

    如果重写quals方法,那么就需要重写hashcode方法,以便将对象插入到散列表中。

    3.toString方法

    作用:返回表示对象值的字符串

    一般用于获取对象状态

  • 相关阅读:
    Apache Tomcat Ajp CVE-2020-1938漏洞复现
    关于JDK高版本下RMI、LDAP+JNDI bypass的一点笔记
    javaweb-codereview 学习记录-5
    java 动态代理机制
    关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的一些总结-2
    关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的一些总结-1
    javaweb-codereview 学习记录-4
    从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果
    javaweb-codereview 学习记录-2
    javaweb-codereview 学习记录-1
  • 原文地址:https://www.cnblogs.com/lht-record/p/8361430.html
Copyright © 2020-2023  润新知