java - 你能改变一个不可变的类吗?
问题描述
这是一个实践的理论问题。
问题是
创建一个不可变类
Car
。创建一些汽车实例来填充类
Arraylist<Car>
内部Garage
。该类
MyGarage
从以下位置实现这些方法Garage
:
getCar(String reg)
– 搜索带有注册号的汽车reg
。getMake(String make)
– 返回与给定匹配的汽车列表make
。totalValue()
– 计算列表中所有汽车的总价值。changeOwner(String reg, String ow)
– 将具有注册号的汽车的所有者更改reg
为ow
。
我不明白该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;
}
}
解决方案
在面向对象和函数式编程中,不可变对象(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");
其中的变量(即registration
和owner
)永远不能更新。
因此,您的changeOwner
方法本质上是遍历您的实例,car
当garage
它找到匹配的注册号时,它会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
推荐阅读
- r - 安装 devtools 包失败
- python - 如果您不介意使用方法访问属性,是否值得使用 Python 的 @property 装饰器?
- python - Rust trait 在链式继承中扩展和覆盖
- reference - 如何操作基于 xml 数据生成的行的单个实例?
- amazon-web-services - 如何通过 Apache Nifi 在 AWS 托管的 ElasticSearch(使用 IAM 角色策略)上索引文档?
- javascript - 在 JavaScript 中使用 map 获取数组值
- ios - 使用 Facebook 凭据的 Firebase 身份验证不起作用
- c++ - 为什么 for(){} 中函数 strcmp() 的返回值不同且不断增加?
- jq - 将 jq 的输出转换为数组
- sql-server - 计算表中的特定行