#java #object #static-variables
#java #объект #статические переменные
Вопрос:
Я хочу иметь переменную, которая подсчитывает все количество сотрудников во всех созданных объектах в 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
.
Ответ №1:
Отказ от ответственности: Я постараюсь сделать все как можно проще. Нет необходимости в инкапсуляции данных, шаблонах, параллелизме или чем-то еще. Сделайте это как можно более простым при изучении основ.
Прежде всего, вам нужно понимать, что вы делаете.
наш учитель хочет, чтобы у нас была переменная, которая подсчитывает все количество сотрудников…
Здесь я вижу Department
класс с setEmp
методом, который, похоже, увеличивает количество сотрудников при каждом вызове. Я не думаю, что это то, что имел в виду ваш учитель с
…во всех созданных объектах в main.
Скорее всего, ваш учитель хочет, чтобы у вас было два класса (я предполагаю, что вы создали Department
по какой-то причине):
Employee
которая назначается
Department
Снова
…подсчитывает все количество сотрудников во всех созданных объектах в main
Мы можем интерпретировать это двумя способами
- Ваш учитель хочет, чтобы вы подсчитали все созданные
Employee
файлы (как следует из названия вопроса) - Ваш учитель хочет, чтобы вы посчитали все
Employee
s заDepartment
Давайте начнем с варианта 1
Я пропущу Department
класс, поскольку он на самом деле не входит в область видимости, и перейду непосредственно к количеству созданных сотрудников.
Что скажет назначенная задача, так это просто подсчитать созданные объекты, что означает созданные Employee
s.
Вот как может выглядеть 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
s для каждого Department
, вам нужно увеличить своего рода количество внутри 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;
}
Я не включил объекты или разделы о синхронизации или параллелизме, поскольку я думаю, что вы все еще в начале и не нужно путаться с этим материалом.
Комментарии:
1. Спасибо, ваш ответ очень помог!
2. @AidanHigginbotham Нет проблем 🙂 Вы можете настроить мой код в соответствии со своими конкретными потребностями уже сейчас, но у вас есть надежная отправная точка.
Ответ №2:
System.out.println(dep1.totalNumEmp) печатает 30, потому что переменная totalNumEmp является статической в отделе моделей.
Почему вы хотите, чтобы общее количество сотрудников всех отделов составляло dep1.totalNumEmp? На мой взгляд, вы не можете сохранить общее количество сотрудников всех отделов в одном экземпляре модели отдела, потому что каждая модель должна содержать ваши собственные данные.
Чтобы подсчитать общее количество сотрудников, вы должны сделать что-то вроде:
Integer totalEmployees = dept1.totalNumEmp dept2.totalNumEmp;
Obs: Я рекомендую вам использовать шаблон Get для доступа к данным в моделях и не сохранять закрытые поля с модификатором «public».
Пример:
Integer totalEmployees = dept1.getTotalNumEmp() dept2.getTotalNumEmp();
Ответ №3:
Избавьтесь от переменной 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();
}
Ответ №4:
Проблема заключается в том, как вы структурировали свой код: вы изменяете значение totalNumEmp
в setEmp()
установщике, а статическое поле и установщик принадлежат одному классу.
Из-за этого следующее:
dep1 = dep2; // here dep1 starts referencing dep2
dep1.setEmp(10);
фактически установщик будет выполнен один раз (вероятно, это то, что вы хотели), но totalNumEmp
также будет изменен только один раз (и вы исключаете, что его нужно изменить дважды, чтобы правильно установить totalNumEmp
значение 20).
Я бы рекомендовал изменить следующее в вашем дизайне:
- Сохраняйте
totalNumEmp
в отдельном классе или генерируйте его на лету. - Не делайте этого, так как это плохая практика:
dep1 = dep2
. Вместо этого используйте copying constructor (public Department(Department other)
). - Подумайте о параллелизме, например, рассмотрите возможность использования
AtomicInteger
вместоint
или синхронизации.