继承、多态与泛型数组列表特性

继承

先贴上实验用的父类

class Employee{
    private String name;
    private int salary;

    public Employee(String name,int salary){
        this.name=name;
        this.salary=salary;
    }

    public void setName(String name) {        this.name = name;    }

    public void setSalary(int salary) {        this.salary = salary;    }

    public String getName() {        return name;    }

    public int getSalary() {        return salary;    }
}

定义子类

使用extends关键字,表面正在构造的新类派生于一个已经存在的类,这个已经存在的类通常称为 超类(superclass)、基类(base class) 或者父类(parent class);新类成为子类(subclass) 或者孩子类(child class)、派生类(derived class)。

尽管称之为超类或者父类,并不是因为功能更多,恰恰相反,子类比超类拥有更多的功能。子类是在超类的基础上扩展一些功能:

class Manager extends Employee {	
    private int bonus;
    ...
    public void setBonus(int Bonus){} ...

}

这个代码中只是多了一个bonus字段和一些方法,超类中的方法和字段子类都会继承下来

覆盖方法

超类中的方法不一定适用于子类,所以要对超类一些功能进行改造,也就是覆盖方法

class Manager extends Employee {
    private int bonus;

   ...
       
    @Override
    public int getSalary() {
        return super.getSalary()+this.bonus;
    }

}

super 关键字:

覆盖方法 getSalary 中需要调用超类的getSalary 方法,直接写成 getSalary 就会调用当前类中的getSalary方法

所以写成 super.getSalary() 即调用父类的getSalary 方法

代码中覆盖了超类的 getSalary() 方法,因为经理还有奖金。也就是说,子类就是根据需要,在超类的基础上扩展一些字段、方法,或者更改超类原有方法的功能,来实现新的功能。

所以当我们用Manager 的对象调用getSalary 方法时:

Manager boss=new Manager("BOSS",50000);
boss.setBonus(10000);
System.out.println(boss.getSalary());		//60000

注意 覆盖方法时,子类的方法不能低于超类方法的可见性。假如超类方法定义为public ,而子类覆盖时却写成了 protect 或者 private,那么就会报错。但是如果超类方法是private,那么子类可以是 private、protect或者public。也就是说子类覆盖的方法的可见性只能大于等于超类方法的可见性。

子类构造器

如果子类没有定义构造器,而且超类中有无参构造器,那么子类会自动调用超类的无参构造器。但是如果超类中没有无参构造器,而子类又没有定义构造器来调用超类的构造器,那么就会报错。

补充一点构造器的知识:如果没有定义任何构造器,那么Java会自动定义一个无参构造器,并且设置所有字段为默认值。一旦写了一个构造器,那么这个机制就不会执行。也就是说假如定义了一个有参的构造器,那么无参的构造器必须要手动写一个才会有,Java不会自动加一个无参构造器了。)

Employee中只有一个有参构造器,那么子类继承的时候必须有构造器调用超类的构造器

class Manager extends Employee {
    private int bonus;

    public Manager(String name,int salary){
        super(name, salary);		//调用超类构造器
    }
	...

}

多态

非专业术语通俗的讲:

在Java中,可以将子类的对象赋给超类变量,这就称之为多态

Employee staff;
staff = new Employee("Helen", 50000);
staff = new Manager("Helen", 50000);

这两种赋值都是合法的,第二种将子类对象赋给超类,那么此时调用的方法是子类覆盖过的方法

举个栗子:

Manager boss=new Manager("Helen",50000);
boss.setBonus(10000);
Employee staff=boss;		//子类对象赋给超类
System.out.println(staff.getSalary());		//60000,这是调用子类的getSalary方法

将 boss 赋给超类Employee 变量staff 时,staff不能调用boss特有的方法,因为staff 本质上还是一个Employee的对象

boss.setBonus(100);		//非法,setBonus Employee对象没有

多态是一个接口,通过不同的实例实现不同的操作(官方)

比如说上面的Employee类,子类Manager覆盖了getSalary();
现在定义一个Employee staff=new Manager() (将子类实例赋值给超类的实例,别奇怪,这就是多态的赋值方法),那么调用staff.getSalary 实际上是调用Manager覆盖后的getSalary。

阻止继承:final 类和方法

有时一个类不希望被子类继承,就可以用final 关键字修饰,那么这个类就无法产生派生类了,也就是说无法被继承:

final class A{			//A类无法被继承
    private int a;
    ...
    public void setA(){}
    ...
}

类中的方法也可以用final 修饰,如果这样做,子类就无法覆盖这个方法(final 类中的所有方法自动成为final 方法,但是其中的字段不会变成 final)

泛型数组列表

很多语言中必须在编译时确定数组的大小,这样很可能导致空间浪费或者空间不够,所以就有了ArrayList

声明数组列表
  • ArrayList

    创建一个数组列表(E为指定的泛型类型,如果不懂则要先了解一下泛型)

  • ArrayList(int initialCapacity)

    创建一个数组列表,初始化大小为initialCapacity

构造一个保存Employee对象的数组列表:

ArrayList<Employee> staff=new ArrayList<>(10);
添加元素和访问元素
  • boolean add(E obj) 添加一个元素
  • E set(int index,E obj) 用obj替换第index个元素,返回之前的内容
  • E get(int index) 访问第index个元素
staff.add(new Employee("HACKER",50000));
staff.add(new Employee("Helen",50000));
//在末尾添加两个元素

Employee temp=new Employee("HH",50);
staff.set(1,temp);
//将索引为 1 的元素替换为 temp,相当于 staff[1]=temp

System.out.println(staff.get(1).getName() + " " + staff.get(1).getSalary());
//获得索引为 1 的元素
删除元素、获取元素个数
  • int size()

    获取元素个数

  • E remove(int index)

    删除第index个元素,并将后面的元素往前移,返回删除的元素

    System.out.println(staff.size());staff.remove(1);System.out.println(staff.size());
    
确定大小
  • void ensureCapacity(int size)

    将分配size个空间,使用这些空间时不会花费重新分配的时间

  • void trimToSize()

    将容量削减到当前大小。当确定了容量不会改变后,使用这个方法将多余的空间回收掉

这两个都是为了优化用的,第一个节省时间,第二个节省空间

参数数量可变的方法

对于一些方法,有时需要的参数数量可能不一样,例如:

public int add(int a,int b){    return a+b;}

这个方法会返回两个数之和,可如果我需要三个数、四个数或者更多数之和怎么办

所以可变参数的作用就体现在这里

public int add(int... num){    int sum=0;    for(int i:num){        sum+=i;    }    return sum;}

参数 num 是一个数组,可以接收任意多个参数。这里的类型可以是基本数据类型,也可以是类

在调用的时候可以写成 add(1) 也可以写成 add(1,2,3,4,5),你想写多少个就写多少个

注意 :可变参数在参数列表的末尾,也就是说可变参数前面可以有参数,但后面不能有

public int add(String name,int... num){}	//OKpublic int add(int... num,String name){}	//ERROR
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值