我有这个实现Cloneable的类。我这里只需要一份浅色的副本。任何人都可以在这里指出java兼容性有什么问题。
public class EventSystem implements Cloneable{
private String enrollmentId;
private String requestId;
private String tokenId;
private Date eventAt;
private Date loggedAt;
private String appCardId;
private String fieldKey;
private String fieldValue;
private String trsDimCardIssuerId;
private String trsDimCardProductId;
private String trsDimAppEventLocationId;
private String trsDimPaymentNetworkId;
private String trsDimAppCardTypeId;
private String trsTempLogId;
public Date getEventAt() {
return eventAt;
}
public void setEventAt(Date eventAt) {
this.eventAt = eventAt;
}
public Date getLoggedAt() {
return loggedAt;
}
public void setLoggedAt(Date loggedAt) {
this.loggedAt = loggedAt;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public String getEnrollmentId() {
return enrollmentId;
}
public void setEnrollmentId(String enrollemntId) {
this.enrollmentId = enrollemntId;
}
public String getTokenId() {
return tokenId;
}
public void setTokenId(String tokenId) {
this.tokenId = tokenId;
}
public String getTrsDimCardIssuerId() {
return trsDimCardIssuerId;
}
public void setTrsDimCardIssuerId(String trsDimCardIssuerId) {
this.trsDimCardIssuerId = trsDimCardIssuerId;
}
public String getTrsDimCardProductId() {
return trsDimCardProductId;
}
public void setTrsDimCardProductId(String trsDimCardProductId) {
this.trsDimCardProductId = trsDimCardProductId;
}
public String getTrsDimAppEventLocationId() {
return trsDimAppEventLocationId;
}
public void setTrsDimAppEventLocationId(String trsDimAppEventLocationId) {
this.trsDimAppEventLocationId = trsDimAppEventLocationId;
}
public String getTrsDimPaymentNetworkId() {
return trsDimPaymentNetworkId;
}
public void setTrsDimPaymentNetworkId(String trsDimPaymentNewtorkId) {
this.trsDimPaymentNetworkId = trsDimPaymentNewtorkId;
}
public String getTrsDimAppCardTypeId() {
return trsDimAppCardTypeId;
}
public void setTrsDimAppCardTypeId(String trsDimAppCardTypeId) {
this.trsDimAppCardTypeId = trsDimAppCardTypeId;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getTrsTempLogId() {
return trsTempLogId;
}
public void setTrsTempLogId(String trsTempLogId) {
this.trsTempLogId = trsTempLogId;
}
public String getAppCardId() {
return appCardId;
}
public void setAppCardId(String appCardId) {
this.appCardId = appCardId;
}
public String getFieldKey() {
return fieldKey;
}
public void setFieldKey(String fieldKey) {
this.fieldKey = fieldKey;
}
public String getFieldValue() {
return fieldValue;
}
public void setFieldValue(String fieldValue) {
this.fieldValue = fieldValue;
}
}
此处是否存在String copy问题。
答案 0 :(得分:1)
您的字符串字段不是问题。您的日期字段是。
当您克隆EventSystem实例时,其每个字段都指向与源对象的相应字段完全相同的对象。因此,克隆实例的enrollmentId
字段指向与原始实例的enrollmentId
相同的String对象。
但那完全没问题。您可以安全地共享String对象,因为它们是不可变的。无法更改String对象。您可以更改包含String的字段的值,但String对象本身永远不会更改。
但是,可以更改日期对象 。这意味着克隆不是真正独立于源实例。它们都引用相同的可变对象,因此如果只为两个EventSystem实例中的一个更改了该对象,则两个实例都将看到这些更改,这可能会导致一些潜在的错误。请考虑以下代码:
Calendar calendar = Calendar.getInstance();
calendar.set(1969, Calendar.JULY, 20, 22, 56, 0);
Date moonLanding = calendar.getTime();
EventSystem e1 = new EventSystem();
e1.setEventAt(moonLanding);
// Prints Sun Jul 20 22:56:00 EDT 1969
System.out.println(e1.getEventAt());
EventSystem e2 = (EventSystem) e1.clone();
// Both e1 and e2 have references to the same Date object, so changes
// to that Date object are seen in both objects!
e2.getEventAt().setTime(System.currentTimeMillis());
// You might expect these to be different, since we only changed
// e2.getEventAt(), but they're the same.
System.out.println(e1.getEventAt());
System.out.println(e2.getEventAt());
解决此问题的一种方法是使用一种常见的面向对象技术,称为防御性复制:
public Date getEventAt() {
return (eventAt != null ? (Date) eventAt.clone() : null);
}
public void setEventAt(Date eventAt) {
this.eventAt = (eventAt != null ? (Date) eventAt.clone() : null);
}
public Date getLoggedAt() {
return (loggedAt != null ? (Date) loggedAt.clone() : null)
}
public void setLoggedAt(Date loggedAt) {
this.loggedAt = (loggedAt != null ? (Date) loggedAt.clone() : null);
}
这可以防止任何其他类直接修改内部日期字段。
另一个不太安全的选择是克隆克隆方法中的日期字段:
@Override
public Object clone() throws CloneNotSupportedException {
EventSystem newInstance = (EventSystem) super.clone();
if (newInstance.eventAt != null) {
newInstance.eventAt = (Date) newInstance.eventAt.clone();
}
if (newInstance.loggedAt != null) {
newInstance.loggedAt = (Date) newInstance.loggedAt.clone();
}
return newInstance;
}