为什么在 Java 中修改创建的对象是错误的?
Why a modification of the created object is bad in Java?
我们都知道Java中的对象是可以修改的
我想在处理一个对象时提出三个选项并指出它们的优点和缺点。
public class SetterApplication {
public static void main(String[] args) {
User john = new User("John", 22);
increaseAge(john, 2);
System.out.println(john); // User{name='John', age=24}
User johnUpper = upperName(john);
System.out.println(johnUpper); // User{name='JOHN', age=24}
System.out.println(john); // User{name='JOHN', age=24}
User johnLower = lowerName(john);
System.out.println(johnLower); // User{name='john', age=24}
System.out.println(johnUpper); // User{name='JOHN', age=24}
}
/**
* Case #1
* change the object passed in and return nothing
* @param user user
* @param inc inc
*/
public static void increaseAge(User user, Integer inc) {
user.setAge(user.getAge() + inc);
}
/**
* Case #2
* change the passed object and return the changed object
* @param user user
* @return User
*/
public static User upperName(User user) {
user.setName(user.getName().toUpperCase());
return user;
}
/**
* Case #3
* do not change the passed object and return a completely new object
* @param user user
* @return User
*/
public static User lowerName(final User user) {
return new User(user.getName().toLowerCase(), user.getAge());
}
}
class User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append('}');
return sb.toString();
}
}
"Case #1" - 最常见的方式,但要包含相应的缺点,即修改现有对象。但这种行为是可以预见的,因为我们没有 return 任何东西。
"Case #2" - 也经常出现在代码中。但这种情况具有误导性 - 因为它 return 是一个修改后的传输对象,这可能会误导我们正在 return 一个新对象,但事实并非如此。
"Case #3" - 这种方法是最时髦的方法。这里我们不修改传输对象和return一个新对象。但是这种方法有一个很大的缺点,在Java中不容易实现(深度)克隆,其次是它可能非常耗费资源,对象可能非常大。
我的问题是三个选项中哪个更可取?你喜欢用什么?您认为哪个选项最差?
这是一个广泛的话题。无论如何,不变性总是更受欢迎。
由于编写不可变 classes 通常很乏味(您可能想提供一个复制构造函数或复制方法。如果我只想复制其属性的某个子集怎么办?)我使用 Immutables图书馆。
只是不要让 class 实现 Cloneable
因为你想使用 clone
方法。
避免那个。您还需要一个显式转换。
我们都知道Java中的对象是可以修改的
我想在处理一个对象时提出三个选项并指出它们的优点和缺点。
public class SetterApplication {
public static void main(String[] args) {
User john = new User("John", 22);
increaseAge(john, 2);
System.out.println(john); // User{name='John', age=24}
User johnUpper = upperName(john);
System.out.println(johnUpper); // User{name='JOHN', age=24}
System.out.println(john); // User{name='JOHN', age=24}
User johnLower = lowerName(john);
System.out.println(johnLower); // User{name='john', age=24}
System.out.println(johnUpper); // User{name='JOHN', age=24}
}
/**
* Case #1
* change the object passed in and return nothing
* @param user user
* @param inc inc
*/
public static void increaseAge(User user, Integer inc) {
user.setAge(user.getAge() + inc);
}
/**
* Case #2
* change the passed object and return the changed object
* @param user user
* @return User
*/
public static User upperName(User user) {
user.setName(user.getName().toUpperCase());
return user;
}
/**
* Case #3
* do not change the passed object and return a completely new object
* @param user user
* @return User
*/
public static User lowerName(final User user) {
return new User(user.getName().toLowerCase(), user.getAge());
}
}
class User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append('}');
return sb.toString();
}
}
"Case #1" - 最常见的方式,但要包含相应的缺点,即修改现有对象。但这种行为是可以预见的,因为我们没有 return 任何东西。
"Case #2" - 也经常出现在代码中。但这种情况具有误导性 - 因为它 return 是一个修改后的传输对象,这可能会误导我们正在 return 一个新对象,但事实并非如此。
"Case #3" - 这种方法是最时髦的方法。这里我们不修改传输对象和return一个新对象。但是这种方法有一个很大的缺点,在Java中不容易实现(深度)克隆,其次是它可能非常耗费资源,对象可能非常大。
我的问题是三个选项中哪个更可取?你喜欢用什么?您认为哪个选项最差?
这是一个广泛的话题。无论如何,不变性总是更受欢迎。
由于编写不可变 classes 通常很乏味(您可能想提供一个复制构造函数或复制方法。如果我只想复制其属性的某个子集怎么办?)我使用 Immutables图书馆。
只是不要让 class 实现 Cloneable
因为你想使用 clone
方法。
避免那个。您还需要一个显式转换。