如何在java中创建不可变类
如何在java中创建不可变类。 如果学生类有关系(地址),如何创建不可变类。 我想使下面的类不可变如何在java中创建不可变类,java,Java,如何在java中创建不可变类。 如果学生类有关系(地址),如何创建不可变类。 我想使下面的类不可变 final public class Student { private final Address add; private final int sid; public Student(int sid, String name, Address add) { super();
final public class Student {
private final Address add;
private final int sid;
public Student(int sid, String name, Address add) {
super();
this.sid = sid;
this.name = name;
this.add = add;
}
private final String name;
public int getSid() {
return sid;
}
public final String getName() {
return name;
}
@Override
public String toString() {
return "Student [add=" + add + ", name=" + name + ", sid=" + sid + "]";
}
public Address getAdd() {
return add;
}
}
//I want to make the class below immutable
public class Address {
public int getAid() {
return aid;
}
public String getStreet() {
return street;
}
@Override
public String toString() {
return "Address [aid=" + aid + ", street=" + street + "]";
}
int aid;
String street;
public Address(int aid, String street) {
super();
this.aid = aid;
this.street = street;
}
}
public class First {
public static void main(String[] args) {
Address myAdd=new Address(179,"Maihill");
Student st=new Student(99,"anoj",myAdd);
System.out.println(st.toString());
myAdd.aid=2376;
System.out.println(st);
System.out.println("***************");
Address pAdd=st.getAdd();
//Here modified address instance then how we can make immutable.
pAdd.aid=788;
System.out.println(st);
}
}
这里我们可以修改地址实例。
请给我一个想法不可变的关键点是:
- 无设置器方法
- 使变量成为私有的和最终的
- 使用Collections.unmodifiableList返回列表-从不返回任何可变字段;始终返回字段的副本(如果合适,请返回深度)或不可变版本
- 期末考试
- 如果变量在类内部更改,则此更改不可见,并且在类外部没有影响(包括影响
和equals()
)hashcode()
地址中
您应该将字段设置为私有
(应该)和最终
(必须),如下所示-
public final class Address { // so no sub-classes can be made.
private final int aid; // private and final.
private final String street; // private and final.
// as before.
}
您也不能使用setter方法,但当字段是最终字段时,这不是什么大问题(因为任何setter方法都会产生编译器错误)。您使Student半不可变:
- 它的属性是最终的
- 它们是不可变的类型(地址除外)
- 它们在构造函数中初始化
地址
类,使其成为不可变的,然后学生
的所有状态都将是不可变的。因此,它将是:
public final class Address {
private final int aid;
private final String street;
public Address(int aid, String street) {
this.aid = aid;
this.street = street;
}
public int getAid() {
return aid;
}
public String getStreet() {
return street;
}
....
}
幸运的是,你没有任何可修改的类型(一些最有名的是“代码>日期<代码>,<代码>集合> <代码> s和<代码>地图< /代码>),否则你也应该考虑它们。
若你们有任何可变属性,你们应该在构造函数中复制保护它,并且你们应该返回一个不可修改的或者状态泄露的副本
例如,如果您的学生
班级具有生日
属性,您应该执行以下操作:
public final class Student {
private final Date birthDate;
public Student(int sid, String name, Address address, Date birthDate) {
this.sid = sid;
this.name = name;
this.address = address;
this.birthDate = (birthDate == null) ? null : new Date(birthDate.getTime());
}
public Date getBirthDate() {
return (birthDate == null) ? null : new Date(birthDate.getTime());
}
....
}
够了<声明的code>final不能进行变异,因为构造函数中有必需的参数,所以getter是多余的
final public class Student {
public final Address add;
public final int sid;
public final String name;
public Student(int sid, String name, Address add) {
super();
this.sid = sid;
this.name = name;
this.add = add;
}
@Override
public String toString() {
return "Student [add=" + add + ", name=" + name + ", sid=" + sid + "]";
}
}
address
和studentId/id
将是更好的字段名称。要使类不可变,请遵循以下五条规则:
摘自有效Java-第三版-第4章
readObject
方法中制作防御性副本(第50项)首先,我们需要讨论java中什么是不可变的。
在Java中,immutable意味着您的状态在初始化后不会改变。不可变类的最好例子是字符串 我们也可以创建自己的不可变类,您必须执行以下步骤
- 将该类声明为最终类:
Why? : As per the java final class can not be extended.
- 将所有字段声明为私有字段
Why? : Because private member have not direct access out side of the class
- 不要为该私有字段提供setter方法
Why? : If you provide the setter method for the private members so you can access it out side of the class.
- 将所有字段设为最终字段
Why?: As per the java final variable can be assigned only once.
- 使用深度复制通过构造函数初始化所有字段
import java.util.HashMap; import java.util.Iterator; public final class ImmutableClassExample { private final int id; private final String name; private final HashMap<String,String> testMap; public int getId() { return id; } public String getName() { return name; } /** * Accessor function for mutable objects */ public HashMap<String, String> getTestMap() { //return testMap; return (HashMap<String, String>) testMap.clone(); } /** * Constructor performing Deep Copy * @param i * @param n * @param hm */ public ImmutableClassExample(int i, String n, HashMap<String,String> hm){ System.out.println("Performing Deep Copy for Object initialization"); this.id=i; this.name=n; HashMap<String,String> tempMap=new HashMap<String,String>(); String key; Iterator<String> it = hm.keySet().iterator(); while(it.hasNext()){ key=it.next(); tempMap.put(key, hm.get(key)); } this.testMap=tempMap; } /** * Constructor performing Shallow Copy * @param i * @param n * @param hm */ /** public ImmutableClassExample(int i, String n, HashMap<String,String> hm){ System.out.println("Performing Shallow Copy for Object initialization"); this.id=i; this.name=n; this.testMap=hm; } */ /** * To test the consequences of Shallow Copy and how to avoid it with Deep Copy for creating immutable classes * @param args */ public static void main(String[] args) { HashMap<String, String> h1 = new HashMap<String,String>(); h1.put("1", "first"); h1.put("2", "second"); String s = "original"; int i=10; ImmutableClassExample ce = new ImmutableClassExample(i,s,h1); //Lets see whether its copy by field or reference System.out.println(s==ce.getName()); System.out.println(h1 == ce.getTestMap()); //print the ce values System.out.println("ce id:"+ce.getId()); System.out.println("ce name:"+ce.getName()); System.out.println("ce testMap:"+ce.getTestMap()); //change the local variable values i=20; s="modified"; h1.put("3", "third"); //print the values again System.out.println("ce id after local variable change:"+ce.getId()); System.out.println("ce name after local variable change:"+ce.getName()); System.out.println("ce testMap after local variable change:"+ce.getTestMap()); HashMap<String, String> hmTest = ce.getTestMap(); hmTest.put("4", "new"); System.out.println("ce testMap after changing variable from accessor methods:"+ce.getTestMap()); } }
import java.util.HashMap; 导入java.util.Iterator; 公共最终类ImmutableClassExample{ 私有最终int id; 私有最终字符串名; 私有最终HashMap testMap; 公共int getId(){ 返回id; } 公共字符串getName(){ 返回名称; } /** *可变对象的访问器函数 */ 公共HashMap getTestMap(){ //返回testMap; return(HashMap)testMap.clone(); } /** *正在执行深度复制的构造函数 *@param i *@param n *@param-hm */ 公共ImmutableClassExample(int i、字符串n、HashMap hm){ System.out.println(“为对象初始化执行深度复制”); 这个.id=i; this.name=n; HashMap tempMap=新的HashMap(); 字符串键; 迭代器it=hm.keySet().Iterator(); while(it.hasNext()){ key=it.next(); tempMap.put(key,hm.get(key)); } this.testMap=tempMap; } /** *执行浅复制的构造函数 *@param i *@param n *@param-hm */ /** 公共ImmutableClassExample(int i、字符串n、HashMap hm){ System.out.println(“为对象初始化执行浅拷贝”); 这个.id=i; this.name=n; testMap=hm; } */ /** *测试浅拷贝的后果,以及如何通过创建不可变类的深拷贝来避免浅拷贝 *@param args */ 公共静态void main(字符串[])
import java.util.HashMap; import java.util.Iterator; public final class ImmutableClassExample { private final int id; private final String name; private final HashMap<String,String> testMap; public int getId() { return id; } public String getName() { return name; } /** * Accessor function for mutable objects */ public HashMap<String, String> getTestMap() { //return testMap; return (HashMap<String, String>) testMap.clone(); } /** * Constructor performing Deep Copy * @param i * @param n * @param hm */ public ImmutableClassExample(int i, String n, HashMap<String,String> hm){ System.out.println("Performing Deep Copy for Object initialization"); this.id=i; this.name=n; HashMap<String,String> tempMap=new HashMap<String,String>(); String key; Iterator<String> it = hm.keySet().iterator(); while(it.hasNext()){ key=it.next(); tempMap.put(key, hm.get(key)); } this.testMap=tempMap; } /** * Constructor performing Shallow Copy * @param i * @param n * @param hm */ /** public ImmutableClassExample(int i, String n, HashMap<String,String> hm){ System.out.println("Performing Shallow Copy for Object initialization"); this.id=i; this.name=n; this.testMap=hm; } */ /** * To test the consequences of Shallow Copy and how to avoid it with Deep Copy for creating immutable classes * @param args */ public static void main(String[] args) { HashMap<String, String> h1 = new HashMap<String,String>(); h1.put("1", "first"); h1.put("2", "second"); String s = "original"; int i=10; ImmutableClassExample ce = new ImmutableClassExample(i,s,h1); //Lets see whether its copy by field or reference System.out.println(s==ce.getName()); System.out.println(h1 == ce.getTestMap()); //print the ce values System.out.println("ce id:"+ce.getId()); System.out.println("ce name:"+ce.getName()); System.out.println("ce testMap:"+ce.getTestMap()); //change the local variable values i=20; s="modified"; h1.put("3", "third"); //print the values again System.out.println("ce id after local variable change:"+ce.getId()); System.out.println("ce name after local variable change:"+ce.getName()); System.out.println("ce testMap after local variable change:"+ce.getTestMap()); HashMap<String, String> hmTest = ce.getTestMap(); hmTest.put("4", "new"); System.out.println("ce testMap after changing variable from accessor methods:"+ce.getTestMap()); } }
record Rectangle(double length, double width) {}
var rectangle = new Rectangle(7.1, 8.9); System.out.print(rectangle.length()); // prints 7.1
public Rectangle { if (length <= 0.0) { throw new IllegalArgumentException(); } }
record Rectangle(double length, double width) { public double area() { return this.length * this.width; } }
record Rectangle(double length, double width) { static double aStaticField; static void printRectanglesIntersect(Rectangle rectangleA, Rectangle rectangleB) { System.out.println("Checking Rectangle intersection.."); } }
@Value @Builder public class Immutable { private String str; private int value; private List<String> strings; }