0
点赞
收藏
分享

微信扫一扫

【Java高级程序设计学习笔记】类型信息应用-运行时类型识别

仲秋花似锦 2022-03-24 阅读 63
java

1.1概述

运行时类型识别,就是在程序运行时,动态地识别对象和类的信息。例如,从容器中获取了一个对象,那么判断这个对象所属的类的过程,就是类型识别的过程。

考虑如下这个问题:公司现在要发奖金,但是不同职位的人获得的奖金不同,把公司员工对象全放到List容器中,从容器中一个一个取出员工,并且向他发放工资。公司管理系统人员组织如图:   

如果能对获取的对象进行类型识别,那么问题就解决了。但是类型识别的意义不仅仅在于此,还有类型转换、泛型约束等都有应用。

1.2 如何进行运行时类型识别

1.2.1. 关键字 instanceof

  instanceof是Java的一个二元关键字,表示某个对象是否是指定类的实例。如果想知道employee是不是Employee类的一个实例,就可以通过instanceof,语法:employee instanceof Employee。表达式返回一个boolean值 。实例如下:

 

public abstract class Employee {
    protected int salary=0;
    public void addSalary(int amount){
        this.salary+=amount;
    }
    public abstract String toString();
}


public class Manager extends Employee{
    @Override
    public String toString(){
        return "Manger's salary:    "+this.salary;
    }
}


public class Worker extends Employee{
    @Override
    public String toString(){
        return "Worker's salary:    "+this.salary;
    }
}

public class Company {
    //随机生成一个Employee列表,包括Manager和Worker
    public static List<Employee> getEmployees(){
        List<Employee> employees=new ArrayList<Employee>();
        Random random=new Random();
        for (int i=0;i<5;i++){
            if (random.nextInt(5)>3)
                employees.add(new Manager());
            else
                employees.add(new Worker());
        }
        return employees;
    }
}

public class Bootstrap {
    public static void main(String[] args) {
        List<Employee> employees=Company.getEmployees();
        for (Employee employee:employees){
            if (employee instanceof Manager){
                employee.addSalary(5000);
            }
            else
                employee.addSalary(1000);
            System.out.println(employee.toString());
        }
    }
}

运行结果:

Worker's salary:    1000
Manger's salary:    5000
Worker's salary:    1000
Manger's salary:    5000
Worker's salary:    1000

   上面的代码定义了五个类,其中Worker和Manager是Employee的子类,在Employee类中定义了两个方法,一个是addSalary(int amount)用于增加员工工资,另一个是抽象的toString()方法.Company类声明了一个获取员工列表的方法,Bootstrap类中,首先获取员工列表,接着一个一个把员工取出,并判断员工类型。

  考虑这样一个问题,现有一个Manger实例的manger,那么manager是Employee吗?当然,即使是经理也是员工。

1.2.2 Class.isInstance()

  现有这样一个问题:员工对象被封存在一个List容器之中,要统计每类员工的人数。因为公司经常有人员变动,所以员工类型经常变化。如果仍使用instanceof关键字,那么每次员工类型变动都要重新写一遍统计代码,很繁琐且扩展性不足。每个Class对象,都有一个方法isInstance(),这个方法用于判断指定对象是不是类的一个实例。这样可以解决上述问题了,用一个Map存放员工类型以及员工数量。初始时数量为0.由于每个类型都有一个isInstance()方法,那么只要把具体的员工对象传给它,让Map进行判断和统计。以后员工类型有变动,只需要修改员工类型Map即可。

 

public class Counter {
    public static Map<Class,Integer> employeeTypes=new HashMap<>();
    public static void count(Employee employee){
        for (Class clazz: employeeTypes.keySet()){//Set keySet():获取集合中所有键的集合
            if (clazz.isInstance(employee)){
                int acount=employeeTypes.get(clazz)+1;
                employeeTypes.put(clazz,acount);
            }
        }
    }
    public static void addEmployeeType(Class clazz){
        employeeTypes.put(clazz,0);
    }
    public static void removeEmployeeType(Class clazz){
        employeeTypes.remove(clazz);
    }
}

   Counter类负责统计各种类型员工的类型,可以通过此类来增加或移除员工类型达到修改的目的。员工的类型以及人数存储在一个Map<Class,Integer>中。当传入一个Employee类时,统计方法首先在键值表中找到该种类型的员工,然后修改员工数量。

  

public class Bootstrap {
    public static void main(String[] args) {
        List<Employee> employees= Company.getEmployees();
        Counter.addEmployeeType(Manager.class);
        Counter.addEmployeeType(Worker.class);
        for (Employee employee:employees)
            Counter.count(employee);
        for (Class clazz:Counter.employeeTypes.keySet()){
            System.out.println(clazz.getCanonicalName()+":"+Counter.employeeTypes.get(clazz));
        }
    }
}

运行结果:

practice.Chapter3.Section1.Worker:4
practice.Chapter3.Section1.Manager:1

  上例首先从公司获取了员工列表,然后在统计器中加入两种员工类型,Manager和Worker,让统计器统计这两类员工的数量,接着把员工一个一个的传给统计器,最后打印出统计结果,员工4人,管理者1人 

 

举报

相关推荐

0 条评论