Java 序列化后在ArrayList上调用equals
我遇到了一个奇怪的问题,关于通过RMI传输的对象上的等式。 这几天来一直困扰着我,我想知道是否有人能帮我解释一下这个问题 我有一个Garage类(如果相关的话,它也是一个JPA实体),我将它推送到一个名为X over RMI的java进程(因此这个对象正在被序列化)。车库对象存储一个名为Car的对象列表(也称为JPA实体),这些对象也是可序列化的 Garage上的equals方法基本上是在其汽车列表(ArrayList)上调用equals 当我在java进程中调用equals时,它不会出于某种原因调用列表中的equals,就像我期望的那样,我希望它调用列表中所有汽车的equals来检查列表是否相等,但它不会这样做 奇怪的是,当单元测试时,它确实对Cars数组列表的所有成员调用了equals。作为单元测试的一部分,我甚至序列化了这些对象,这也起到了作用。有什么想法吗?我希望我能把问题说清楚,请随时询问任何信息以澄清任何问题 编辑:我几乎可以肯定它的ArrayList很奇怪,因为当我在我的对象中手动执行equals,而不是在汽车列表中调用equals时,我在汽车列表上执行了foreach循环,并在每辆汽车上调用了equals(就像我期望ArrayList无论如何都会执行equals一样,它按预期工作)Java 序列化后在ArrayList上调用equals,java,serialization,jpa,arraylist,rmi,Java,Serialization,Jpa,Arraylist,Rmi,我遇到了一个奇怪的问题,关于通过RMI传输的对象上的等式。 这几天来一直困扰着我,我想知道是否有人能帮我解释一下这个问题 我有一个Garage类(如果相关的话,它也是一个JPA实体),我将它推送到一个名为X over RMI的java进程(因此这个对象正在被序列化)。车库对象存储一个名为Car的对象列表(也称为JPA实体),这些对象也是可序列化的 Garage上的equals方法基本上是在其汽车列表(ArrayList)上调用equals 当我在java进程中调用equals时,它不会出于某种原
@实体
@表(schema=“pdw”,name=“garage”)
公共级车库
实现可比性,
可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私有字符串id;
私有字符串名称;
@OneToMany(级联=级联类型.ALL)
@JoinTable(schema=“pdw”)
私家车列表=新的ArrayList();
公共字符串getId(){
返回id;
}
公共无效集合id(字符串id){
this.id=id;
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共列表getCars(){
返回车辆;
}
公共车辆(列出车辆){
这个。汽车=汽车;
}
@凌驾
公共字符串toString(){
StringBuffer=新的StringBuffer();
缓冲区。追加(“[”);
buffer.append(“Garage:”);
buffer.append(“[id:+id+]”);
缓冲区。追加(“[Cars:+Cars+]”);
缓冲区。追加(“]”);
返回buffer.toString();
}
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(!(车库的obj实例))
返回false;
车库其他=(车库)obj;
if(name==null){
if(other.name!=null)
返回false;
}如果(!name.equals(other.name))
返回false;
if(cars==null){
if(other.cars!=null)
返回false;
}如果(!cars.equals(other.cars))
返回false;
返回true;
}
@凌驾
公共内部比较(车库其他){
返回这个.getName().compareTo(other.getName());
}
}
@实体
@表(schema=“pdw”,name=“car”)
公车
实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私有字符串id;
私有字符串名称;
@OneToOne(fetch=FetchType.LAZY)
私人车库;
公共字符串getId(){
返回id;
}
公共无效集合id(字符串id){
this.id=id;
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共车库{
返回车库;
}
公共车库(车库){
这个车库=车库;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(getClass()!=obj.getClass())
返回false;
汽车其他=(汽车)obj;
if(name==null){
if(other.name!=null)
返回false;
}如果(!name.equals(other.name))
返回false;
返回true;
}
@凌驾
公共字符串toString(){
StringBuffer=新的StringBuffer();
缓冲区。追加(“[”);
buffer.append(“Car:”);
buffer.append(“[id:+id+]”);
buffer.append(“[name:+name+]”);
append(“[garage:+garage.getName()+”]);
缓冲区。追加(“]”);
返回buffer.toString();
}
}
- 请确保您的
列表在反序列化后不为空
- 在
方法中放置一个断点,看看是否没有发生任何错误equals
- 确保在
上执行的Car
是正确的equals
- 检查是否没有
瞬态
字段
- 检查您期望成为
数组列表的内容是否实际上不是
。因为它的持久性包
等于
不会做你想做的事。如果它是
,则可以在通过线路发送之前将其传输到PersistentBag
(从而防止潜在的ArrayList
),或者对每个元素而不是LazyInitializationException
列表本身调用equals。Hibernate使用
包装您的集合,以提供延迟加载PersistentBag
- 检查两侧的类是否具有相同的
(即具有完全相同的编译版本)。我serialVersionUID
@Entity @Table(schema="pdw", name="garage") public class Garage implements Comparable<Garage> , Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private String id; private String name; @OneToMany(cascade = CascadeType.ALL) @JoinTable(schema="pdw") private List<Car> cars = new ArrayList<Car>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } @Override public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("["); buffer.append("Garage:"); buffer.append("[id:" + id + "]"); buffer.append("[Cars:" + cars + "]"); buffer.append("]"); return buffer.toString(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof Garage)) return false; Garage other = (Garage) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (cars == null) { if (other.cars != null) return false; } else if (!cars.equals(other.cars)) return false; return true; } @Override public int compareTo(Garage other) { return this.getName().compareTo(other.getName()); } } @Entity @Table(schema="pdw", name="car") public class Car implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private String id; private String name; @OneToOne(fetch = FetchType.LAZY) private Garage garage; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Garage getGarage() { return garage; } public void setGarage(Garage garage) { this.garage = garage; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Car other = (Car) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("["); buffer.append("Car:"); buffer.append("[id:" + id + "]"); buffer.append("[name:" + name + "]"); buffer.append("[garage:" + garage.getName() + "]"); buffer.append("]"); return buffer.toString(); } }
public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof List)) return false; ListIterator<E> e1 = listIterator(); ListIterator e2 = ((List) o).listIterator(); while(e1.hasNext() && e2.hasNext()) { E o1 = e1.next(); Object o2 = e2.next(); if (!(o1==null ? o2==null : o1.equals(o2))) return false; } return !(e1.hasNext() || e2.hasNext()); }
if (obj == null) return false; if (getClass() != obj.getClass()) return false;
if (!(obj instanceof Car)){ return false; }
/** * Bag does not respect the collection API and do an * JVM instance comparison to do the equals. * The semantic is broken not to have to initialize a * collection for a simple equals() operation. * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { return super.equals(obj); }
public static boolean areEqualNonNullLists(List thisList, List thatList) { if(thisList.size() != thatList.size()) return false; for(int i=0; i<thisList.size(); i++) { if(!thisList.get(i).equals( thatList.get(i) ) ) return false; } return true; }