首页 > 解决方案 > 你能改变一个不可变的类吗?

问题描述

这是一个实践的理论问题。

问题是

创建一个不可变类Car

创建一些汽车实例来填充类Arraylist<Car>内部Garage

该类MyGarage从以下位置实现这些方法Garage

  • getCar(String reg)– 搜索带有注册号的汽车reg
  • getMake(String make)– 返回与给定匹配的汽车列表make
  • totalValue()– 计算列表中所有汽车的总价值。
  • changeOwner(String reg, String ow)– 将具有注册号的汽车的所有者更改regow

我不明白该changeOwner方法,因为它不应该能够更改我认为的不可变类的实例???

这就是我为解决它所做的工作,但看起来很愚蠢

import java.util.ArrayList;

public class MyGarage implements Garage {
    
    private ArrayList<Car> myGarage;
    
    public MyGarage() {
        myGarage = new ArrayList<Car>();
    }

    @Override
    //Adds a Car if the registration is unique 
    public boolean add(Car c) {
        for(Car car : myGarage) {
            if(car.getRegistration().equals(c.getRegistration())) {                         
                System.out.println("Car has the same Registration as another illegal");
                return false;       
            }   
        }
        myGarage.add(new Car(c.getOwner(),c.getRegistration(),c.getMake(),c.getkilometres(), c.getprice()));
        return true;
    }

    @Override
    public Car getCar(String carID) {
        for(Car car : myGarage) {
            if(carID.equals(car.getRegistration())) {
                System.out.println("Car Found");
                return car;
            }
        }

        System.out.println("No car of that record");
        return null;
    }

    @Override
    public ArrayList<Car> getMake(String make) {
        
        ArrayList<Car> carModel = new ArrayList<Car>();
            for(Car car : myGarage) {
                if (car.getMake().equals(make)) {
                    carModel.add(car);
                }           
            }
        System.out.println(carModel.toString());        
        return carModel;
    }

    @Override
    public  void totalValue() {
        double amount = 0;
        for(Car car : myGarage) {
            amount = car.getprice() + amount;
        }
        System.out.println("The total amount is: " + amount);
    }

    @Override
    public boolean changeOwner(String registration, String ow) {

        for(Car car : myGarage) {
            if(car.getRegistration().equals(registration)) {
                myGarage.remove(car);
                car = new Car(ow, "444","F-50",  4, 4000.99);
                myGarage.add(car);
                return true;
            }
        }
        return false;
    }
}

标签: javaooparraylistimmutability

解决方案


在面向对象和函数式编程中,不可变对象(unchangeable object)是一个对象,其状态在创建后就无法修改。这与可变对象(changeable object)形成对比,可变对象在创建后可以修改。在某些情况下,即使某些内部使用的属性发生变化,对象也被认为是不可变的,但从外部角度来看,对象的状态似乎没有变化。-维基百科

因此,不可变对象是其状态在初始化后不会改变的实例。这些类型的类通常适用于需要实现某种形式的缓存以及您担心多线程环境中的线程安全(不可变对象本质上是线程安全的)的应用程序。

我没有看到您的Car课程,但假设它看起来像这样:

public final class Car { 

  final String registration; 
  final String owner; 

  public Car(String registration, String owner) { 
    this.registration = registration; 
    this.owner= owner; 
  } 

  public String getRegistration() { 
    return registration; 
  } 

  public String getOwner() { 
    return owner; 
  } 
} 

...请注意,此类中没有setter方法。因此 acar只能被初始化(即Car myCar = new Car("abcd", "John");其中的变量(即registrationowner)永远不能更新。

因此,您的changeOwner方法本质上是遍历您的实例,cargarage它找到匹配的注册号时,它会car从您的实例中删除该实例,garage然后添加一个全新的实例。

为了证明这一点,您可以运行以下命令:

public class Garage {

  public static void main(String ... args) {
    List<Car> myGarage = new ArrayList<>();
    myGarage.add(new Car("CG404GH", "John"));
    System.out.println(myGarage);
    for(Car car : myGarage) {
        if("CG404GH".equals(car.getRegistration())) {
            myGarage.remove(car);
            Car updateCar = new Car("DD404GH", "John");
            myGarage.add(updateCar);
        }
    }
    System.out.println(myGarage);
  }

}

这将打印出类似于以下内容的内容(@ 之后的部分在每次运行时都会有所不同):

[Car@4411d970]
[Car@6442b0a6]

这里要注意的重要一点是@后面的值是不同的,因此它们是两个完全不同的类(实例)car


推荐阅读