I just wanted to recapitulate the options mentioned before, throwing some new ones in:
- return null
- throw an Exception
- use the null object pattern
- provide a boolean parameter to you method, so the caller can chose if he wants you to throw an exception
- provide an extra parameter, so the caller can set a value which he gets back if no value is found
Or you might combine these options:
Provide several overloaded versions of your getter, so the caller can decide which way to go. In most cases, only the first one has an implementation of the search algorithm, and the other ones just wrap around the first one:
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
Even if you choose to provide only one implementation, you might want to use a naming convention like that to clarify your contract, and it helps you should you ever decide to add other implementations as well.
You should not overuse it, but it may be helpfull, espeacially when writing a helper Class which you will use in hundreds of different applications with many different error handling conventions.