面试题答案
一键面试引用传递可能带来的问题
- 数据意外修改:当通过引用传递对象时,被调用方法可能会意外修改对象的状态,这会影响到调用者的业务逻辑。例如,在公司 - 部门 - 员工的结构中,如果一个方法本意只是读取员工信息,但不小心修改了员工的工资等信息,这可能导致调用者的业务出现错误。
- 内存共享问题:多个引用指向同一对象,可能导致内存管理上的困惑。比如当一个对象应该被销毁,但由于其他地方还持有其引用,导致对象无法正常释放内存。
避免这些问题的方法
- 使用不可变对象:将对象设计为不可变,一旦创建,其状态就不能被修改。例如,员工类中的属性可以在构造函数中初始化,并且不提供修改属性的方法。
- 深度拷贝:在传递对象前,对对象进行深度拷贝,这样被调用方法操作的是拷贝后的对象,不会影响原始对象。
代码示例
import java.util.ArrayList;
import java.util.List;
// 员工类
class Employee {
private String name;
private int salary;
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
// 这里不提供修改 salary 的方法,保证不可变
public String getName() {
return name;
}
public int getSalary() {
return salary;
}
}
// 部门类
class Department {
private String departmentName;
private List<Employee> employees;
public Department(String departmentName) {
this.departmentName = departmentName;
this.employees = new ArrayList<>();
}
public void addEmployee(Employee employee) {
employees.add(employee);
}
public List<Employee> getEmployees() {
// 返回不可变的拷贝
return List.copyOf(employees);
}
}
// 公司类
class Company {
private String companyName;
private List<Department> departments;
public Company(String companyName) {
this.companyName = companyName;
this.departments = new ArrayList<>();
}
public void addDepartment(Department department) {
departments.add(department);
}
public List<Department> getDepartments() {
// 返回不可变的拷贝
List<Department> copy = new ArrayList<>();
for (Department department : departments) {
Department copiedDepartment = new Department(department.departmentName);
for (Employee employee : department.getEmployees()) {
copiedDepartment.addEmployee(new Employee(employee.getName(), employee.getSalary()));
}
copy.add(copiedDepartment);
}
return copy;
}
}
public class Main {
public static void main(String[] args) {
Company company = new Company("示例公司");
Department department = new Department("技术部");
department.addEmployee(new Employee("张三", 5000));
company.addDepartment(department);
List<Department> departments = company.getDepartments();
// 这里获取的 departments 是拷贝后的,对其修改不会影响原始的 company 对象
}
}
在上述代码中,Employee
类设计为不可变,Department
类和Company
类通过返回不可变的拷贝(List.copyOf
或手动深度拷贝)来避免引用传递带来的问题。