Java - Defensive copies
12th November 2021
Making defensive copies of objects helps us ensure that bad clients, malicious actors or other developers don't accidentally/deliberately cause problems with our code's execution. If your API takes in mutable data then you should make a defensive copy of that to safeguard your code.
Example: No defense
Client Bridge
public static void main(String[] args) {
DefendEvent event = new DefendEvent("Delivery", 1);
ClientBridge clientBridge = new ClientBridge(event);
clientBridge.printDetails();
//Event: Delivery of type: 1
event.setEventName("Dispatch");
event.setEventType(2);
clientBridge.printDetails();
//Event: Delivery of type: 2 => Our bridge's object has been interfered with
}
public class ClientBridge {
private DefendEvent defendEvent;
public ClientBridge(DefendEvent defendEvent) {
this.defendEvent = defendEvent;
//...validate inputs...
}
public void printDetails() {
System.out.println("Event: " + defendEvent.getEventName() + " of type: " + defendEvent.getEventType());
}
}
Below we create a new object using the value provided. This keeps the value safe and we can now validate the input knowing it can't be interfered with.
Example: Defensive
Client Bridge
public static void main(String[] args) {
DefendEvent event = new DefendEvent("Delivery", 1);
ClientBridge clientBridge = new ClientBridge(event);
clientBridge.printDetails();
//Event: Delivery of type: 1
event.setEventName("Dispatch");
event.setEventType(2);
clientBridge.printDetails();
//Event: Delivery of type: 1
}
public class ClientBridge {
private DefendEvent defendEvent;
public ClientBridge(DefendEvent defendEvent) {
this.defendEvent = new DefendEvent(defendEvent.getEventName(), defendEvent.getEventType());
//...validate inputs...
}
public DefendEvent getDefendEvent() {
return new DefendEvent(defendEvent.getEventName(), defendEvent.getEventType());
}
}