fuhgeddaboutit
fuhgeddaboutit

Reputation:

java: How to make defensive copy when you only have an interface

If an object takes a reference to another object, I know it can be a good idea to make a copy of the passed-in object to preserve encapsulation. But, what if all the object knows about the object passed in is that it implements an interface?

For example, if I have an object that takes an implementation of FilenameFilter in its constructor, how can I make a defensive copy of it when all I know about it is that it implements FilenameFilter? Would I have to resort to using reflection?

Upvotes: 4

Views: 1640

Answers (3)

Stephen C
Stephen C

Reputation: 718886

I'd start by thinking carefully about whether the defensive copy is really necessary. If this is not a security related issue, then it sounds like the defensive copy is not strictly necessary in this case.

Then assuming that the copy is strictly necessary, I'd define an subinterface of FileFilter that defines a copy method with appropriate semantics. Use that interface instead of FileFilter in the constructor you mentioned, pass FileFilters that implement the interface, and arrange for the afore-mentioned constructor to call the copy method at the appropriate time.

(Alternatively, you might be able to use Object.clone() depending on your app's package structure.)

Upvotes: 0

Bill K
Bill K

Reputation: 62769

First of all, it's not always a good idea to make a defensive copy. You only want to do that with mutable classes that cannot enforce the contract that your business logic requires (such as collections).

Yours is a perfect example. FilenameFilter is immutable--nothing can change it through that interface. Feel free to pass it around at will. The only potential problem is threading, and that's pretty rarely a problem.

The more general solution (For classes that are actually an issue like collections) would be to wrap the collection in a class rather than copy it. If you wrap it in a business logic class, you can restrict access until you are sure it won't break your business logic rules, then feel free to pass it everywhere.

You'll notice that the JDK pretty much never passes collections. This is on purpose, and the exact reason for the "Copying" pattern you are considering. Usually the JDK will pass an array, and most collections have a fairly easy way to generate a copy of their contents to pass on.

Copying an object is actually extremely rare--collections and arrays are the primary ones to be concerned with. Most other objects can defend themselves pretty well if they are even half-decently designed.

Upvotes: 2

cletus
cletus

Reputation: 625097

Your best bet when dealing with this kind of problem is to make as many of your objects as possible immutable, meaning they can't be modified after creation. If you need to modify them you make a new one leaving the original untouched.

This is also better for multithreading as well.

Mutable objects aren't considered "best practice" as a general rule. You can't completely eliminate them but, as Josh Bloch says, favour immutability.

That being said, there's no real way of making a deep copy (which is what you'd need) in any kind of guaranteed way. If you're simply passed in an interface, then your only options are really reflection of some form or making a copy to another object that implements the same interface (if thats possible).

Upvotes: 6

Related Questions