Hoinzey

Javascript. Kotlin. Android. Java

Java - Defensive copies

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());
        }
    }