保持静态变量在整个对象中正确更新的问题

问题描述 投票:1回答:4

我想要一个变量来计算main中所有创建对象的所有员工数量。这是我有多远:

public class test {

    public static void main(String[] args) {
        Department dep1 = new Department();
        Department dep2 = new Department("CSTI", 30);
        dep1.setEmp(20);
        dep2.setEmp(40);
        System.out.println(dep1.totalNumEmp);
        // Outputs 60
        dep1 = dep2; // here is where I get lost
        dep1.setEmp(10);
        System.out.println(dep1.numEmp + " " + dep2.numEmp);// outputs 10 10
        System.out.println(dep1.totalNumEmp);// Outputs 30. When it needs to output 20, because dep1 and dep2 are now
                                                // both 10
    }
}

class Department {

    String name;
    int numEmp;

    public static int totalNumEmp;

    Department() {
    }

    Department(String newName, int newNum) {
        name = newName;
        numEmp = newNum;
        totalNumEmp += numEmp;
    }

    public void setEmp(int newNum) {
        totalNumEmp -= numEmp;
        numEmp = newNum;
        totalNumEmp += numEmp;
    }
}

我的问题是,我不知道我应该如何保持totalNumEmp一旦dep1 = dep2正确更新。在totalNumEmp指向dep1的参考之后,我必须找到一种方法来保持dep2正确更新。我知道我可以很容易地做dep1.setEmp(dep2.numEmp)并避免它弄乱totalNumEmp,但我必须知道如何用dep1指向dep2

java object static-variables
4个回答
0
投票

免责声明:我会尽可能简化事情。不需要数据封装,模式,并发或其他任何东西。在学习基础知识的同时尽量保持简单。

首先,您需要了解自己在做什么。

我们的老师希望我们有一个可以计算所有员工人数的变量......

在这里,我看到一个Department类,使用setEmp方法,似乎它会增加每次通话时员工的数量。我不认为这是你老师的意思

...遍布main中的所有创建对象。

你的老师最想要你做的是有两个班级(我假设你出于某种原因创建了Department):

Employee

分配给a

Department

再次

...计算main中所有已创建对象的所有员工数

我们可以用两种方式解释这一点

  1. 你的老师希望你统计所有创建的Employees(问题标题建议)
  2. 你的老师希望你计算每个Employee的所有Departments

让我们从选项1开始

我将跳过Department类,因为它不在范围内,我将直接转到创建的员工数量。 分配的任务所说的只是计算创建的对象,这意味着创建的Employees。

以下是Employee类的外观

public class Employee {
   // Count of the created employees
   public static int count = 0;

   // ... Class fields

   public Employee(
       final Department department,
       final String name,
       final String surname) {
      // ... Assign arguments to class fields

      // A new employee has been created. Increment the counter!
      ++count;    
   }

   ... 
}

这个静态字段

public static int count = 0;

每次创建新的Employee时都会递增。 您将能够通过它访问它

final int total = Employee.count;

现在,选项2

由于你需要根据Employee计算Departments,你需要在Department类中增加一些计数。这就是Department类可能会是什么样子

public class Department {
   private final List<Employee> employees;
   private final String name;

   public Department(final String name) {
      this.employees = new ArrayList<Employee>();
      this.name = name;
   }

   public String getName() {
      return name;
   }

   public List<Employee> getEmployees() {
      return employees;
   }

   public int getEmployeeCount() {
      return employees.size();
   }

   public void addEmployee(final Employee employee) {
      employees.add(employee);
   }
}

你可以看到这个类拥有

  • 一个名字
  • 分配的员工名单(private final List<Employee> employees

然后,我们有Employee类,就像我上面描述的那样,但要注意这些变化

public class Employee {
   // ... Class fields

   public Employee(
       final String name,
       final String surname) {
      // ... Assign arguments to class fields
   }

   ... 
}

这里我们只有一个普通的类(Pojo)。我们如何使用它?遵循代码内注释

public static void main(final String[] args) {
   final Department dep1 = new Department("dep1");
   dep1.addEmployee(new Employee("Name1", "Surname1"));
   dep1.addEmployee(new Employee("Name2", "Surname2"));

   final Department dep2 = new Department("dep2");
   dep2.addEmployee(new Employee("Name3", "Surname3"));

   // Now we have two departments.
   // We can retrieve the count of employees for each using
   final int dep1Count = dep1.getEmployeeCount();
   final int dep2Count = dep2.getEmployeeCount();

   // And we can have the total
   final int total = dep1Count + dep2Count;
}

我没有包含有关同步或并发性的对象或主题,因为我认为你仍处于开始状态,不需要对这些东西感到困惑。


0
投票

System.out.println(dep1.totalNumEmp)正在打印30,因为变量totalNumEmp在模型部门是静态的。

您为什么要在dep1.totalNumEmp中拥有所有部门的总成员?简而言之,您不能将所有部门的总体员工保留在部门模型的一个实例中,因为每个模型都应包含您自己的数据。

要计算员工总数,您应该做出类似的事情:

Integer totalEmployees = dept1.totalNumEmp + dept2.totalNumEmp;

Obs:我建议你使用Get模式访问模型中的数据,不要使用“public”修饰符保留私有字段。例如:

Integer totalEmployees = dept1.getTotalNumEmp() + dept2.getTotalNumEmp();

0
投票

摆脱totalNumEmp变量,它没用,并且不属于面向对象编程中的部门,因为它不是每个部分的属性。

在您的主体中,创建部门的arraylist

ArrayList<Departments> allDepartments = new ArrayList<>();
allDepartments.add(dep1);
allDepartments.add(dep2);
//...

然后创建一个静态方法,它将计算您的员工总数:

private static int countTotalNum(ArrayList<Departments> allDepartments) {
    AtomicInteger sum = new AtomicInteger();
    allDepartments.forEach(department -> sum.addAndGet(department.numEmp));
    return sum.get();
}

0
投票

问题在于如何构建代码:在totalNumEmp setter中更改setEmp()的值,静态字段和setter都属于同一个类。

因此,以下内容:

dep1 = dep2;     // here dep1 starts referencing dep2
dep1.setEmp(10);

实际上会执行一次setter(这可能就是你想要的)但是totalNumEmp也只会被改变一次(除了你要更改两次,以正确设置totalNumEmp为20)。

我建议您在设计中更改以下内容:

  1. totalNumEmp保留在一个单独的类中或动态生成它。
  2. 不要这样做,因为这是不好的做法:qazxsw poi。请改用复制构造函数(qazxsw poi)。
  3. 考虑并发性,例如考虑使用dep1 = dep2而不是public Department(Department other)或同步。
© www.soinside.com 2019 - 2024. All rights reserved.