I have public method add(String) that calls private method inspectSequence(String) to check whether String valid or not.
This method returns array if passed String is valid, if it's invalid then method throws IllegalArgumentException
the code is next
public void add(String sequence) throws IllegalArgumentException{
inspectSequence(sequence);
}
private int[] inspectSequence(String sequence){
int[] array;
//some actions
if(<some condition>) throw new IllegalArgumentException("description");
return array;
}
So in cases, when invalid String were passed to add method output will be next:
java.lang.IllegalArgumentException: description
at inspectSequence
at add
But I don't want user to know about private inspectSequence method because this is realization detail, right?
So what I can do in that case? Is it a good idea to throw unchecked exception here?
And is a good idea to throw exception inside inspectSequence method or I should return null when supplied String isn't valid and then check returned result in add method and depending on it throw or not throw exception?
But I don't want user to know about private inspectSequence method because this is realization detail, right?
I'd say no. It's true that you don't want the user (which in that context means someone calling the code) to "know" about internal methods like inspectSequence(). With "know" I mean be able to call, depend upon etc.
Knowing that the exception might be thrown and under what circumstances is something that a caller should know about, knowing where exactly it is thrown isn't necessary but wouldn't hurt.
Of course you could catch that exception in the calling method and throw another one but that would just lose information and might make the code harder to debug/maintain since the information where the input was not accepted would be lost to the caller.
So what I can do in that case? Is it a good idea to throw unchecked exception here?
That depends on whether that exception should be handled at runtime or be fixed.
Suppose the caller needs to know that the sequence was invalid and should handle that information appropriately, e.g. display some information to the enduser. In that case it would be better to throw a checked exception that describes that case.
On the other hand, if the input violates the contract of the method, i.e. the input sequence should never be invalid (or otherwise it's a programming error) then an IllegalArgumentException would be ok - situations like passing null to a method that doesn't expect null parameters.
And is a good idea to throw exception inside inspectSequence method or I should return null when supplied String isn't valid and then check returned result in add method and depending on it throw or not throw exception?
I'd say no. Returning null and then handling that in the calling method might be a reasonable way in some cases (e.g. if you have different callers that handle null differently) but your case is none of those. It would make code more complex and thus harder to read and maintain, especially since null might have multiple meanings which you'd have to define in that case.
You can catch IllegalArgumentException and throw your own.
public void add(String sequence) throws MyCustomException {
try {
inspectSequence(sequence);
} catch (IllegalArgumentException e) {
throw new MyCustomException("more readable cause that hides internals");
}
}
Related
I am a little unsure about the difference between the try/catch, throw and throws in Java and every website seems to have an inhuman way of explaining it, I have tried the Oracle website but I just could not understand their explanation, is this correct?
Try/catch
With try catch, I want to try a piece of code and if something goes wrong do this.
Throw
With throw, I am throwing an error because I want to?
So if I wanted to validate a users age, say all people over 20 and the user does not meet the requirements, I would throw an error?
Throws
With Throws I am throwing an error but something else handles the exception? Would this be another method/class?
Try / Catch
try
{
// try to do some actions
}
catch(SomeExceptionType exception)
{
// if the above actions throw a SomeExceptionType, do these actions
}
Throw
Correct. We're explicitly throwing an exception. You may do this if, for example, the caller of a method has violated your method's contract. Perhaps an argument cannot be negative.
In this situation, the best way to deal with this is to throw an exception which stops what we're doing and allows callers further up the stack to deal with the problem:
/** Do a thing. myInt must be positive */
void someMethod(Integer myInt)
{
if (myInt < 0)
{
throw new IllegalArgumentException("Can't be negative");
}
// do something
}
void myCaller()
{
someMethod( 1); // won't throw
someMethod(-1); // will throw
}
Throws
throws is used as a keyword when dealing with checked exceptions. It's a way of letting callers know what checked exceptions they can expect they may have to deal with.
Those methods can decide to deal with the problem (i.e. a try-catch) or can themselves declare the same exception type to be thrown to propagate the exception up to their caller (and so on and so on)
You forget a important point : in Java all exceptions are not handled by the compiler in the same way.
The compiler ensures only that the checked exceptions be handled.
These exceptions don't inherit from RuntimeException but from Exception (directly or indirectly).
So whatever you throw in your code or a method of a third class declares throwing a checked exception, you have to explicitly handle it.
And there you have two ways :
catching the exception
letting the exception be propagated to the caller
try/catch addresses the first way while specifying the throws modifier in the method declaration addresses the second.
For no RunTimeExceptions, you don't have this constraint as the compiler doesn't force you to handle it. You may handle them if you want to.
I'm reading J. Bloch's Effective Java and now I'm at the section about checked/unchecked exceptions. He said that (emphasize mine):
By confronting the API user with a checked exception, the API designer
pre- sents a mandate to recover from the condition. The user can
disregard the mandate by catching the exception and ignoring it, but
this is usually a bad idea(Item 65).
Now, consider a method returning a list of all static data members of a class having the same type or a subtype:
public static <T> List<? extends T> getPublicStaticFields(Class<T> clazz){
List<T> fields = new ArrayList<>();
for(Field f : clazz.getDeclaredFields()){
if(Modifier.isStatic(f.getModifiers()) &&
Modifier.isPublic(f.getModifiers())){
Object fieldValue;
try {
fieldValue = f.get(null);
if(clazz.isAssignableFrom(fieldValue.getClass()))
fields.add((T) fieldValue);
} catch (IllegalAccessException e) { } // <------- Ignoring the execption
}
}
return Collections.unmodifiableList(fields);
}
The thing is I have no idea what I should put in the exception handler. I perform the access checking in the if condition:
f(Modifier.isStatic(f.getModifiers()) &&
Modifier.isPublic(f.getModifiers()))
therefore IllegalAccessViolation will never be thrown. Moreover it seems a little confused why IllegalAccessViolation is checked. I think it's a programming error, and judjing by what he said:
use checked exceptions for conditions from which the caller can
reasonably be expected to recover
[...]
Use runtime exceptions to
indicate programming errors
I though it should be an uncheked one.
QUESTION: Is it considered appropriate to leave a hadler of a checked exception empty if we ensured that the expcetion will never be thrown somewhere before?
Instead of ignoring the exception, add
throw new AssertionError("this should never happen");
to the catch block. That way, if you misunderstood the documentation and this IllegalAccessException exception effectively happens, or if someone modifies the code and removes the checks that make this IllegalAccessException exception impossible, you'll have a clear exception, with a stack trace indicating the precise location where the problem is, rather than a problem later, in unrelated code, or worse: a valid but incorrect result.
This is a quote from Effective java.
"Where possible, the best way to deal with exceptions from lower layers is to avoid them, by ensuring that lower-level methods succeed. Sometimes you can do this by checking the validity of the higher-level method’s parameters before passing them on to lower layers."
Consider an object called "AccessControlContext actx" which is propogated from handler to lower levels. We can do a higher level check that "actx != null" but does it need to done in lower level again ?
Eg in psuedocode:
class RestServlet {
void verify Servlet(AccessControlContext actx) {
// check made at higher level according to effective java
if (actx == null) { throw exception; }
// do something
Verify.checkAccessControl(actx); // calling lower leve
// do something
}
}
class Verify {
static checkAccessControl(actx) {
// DO I NEED NULL POINTER CHECK HERE AGAIN ?
}
}
Although question is nested inside the comment, reiterating with elaboration.
A redundant check at lower level ensures defensive coding but - it is redundant.
It may be well spelled out in the javadocs that it does not accept null, but that does not solve the purpose of having a bug free code. Should we dedupe exception checks ?
NOTE: This was a random example. My question is not specific to this example. Its a broader question which seeks to understand how much to duplicate exceptions.
When it comes to validating parameters, in my opinion you can't do it too often. The way I'm used to working, parameters are validated in all layers of the code. If a method can't handle a null value (it would lead to a nullpointer for instance), it should be up to the method itself to make sure that the parameters passed aren't null. The same goes for methods where a bad parameter value would cause and exception further down in the layers.
The way I see it, if a bad parameter would cause an exception, it doesn't matter whether or not it is an exception thrown from a parameter validation at a high level or a parameter validation at low level, it is anyways better than the exception it would cause if there were no validation at all (or even worse, no exception and an erroneous execution.)
By letting each method be responsible for validating its input, even if it is just a passthrough-method, one can make sure that any new method calling an existing method will be prevented from passing along a bad parameter, since it would lead to a validation exception, no matter if the method being called is a high level or low level method.
So, in your example I would validate the input in both methods, with accompanying tests verifying that the validation behaves as it should. Input validation could also be as easy as a one-liner, check out the Validate class of apache commons lang: http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/Validate.html
For instance:
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.StringUtils;
public class Something {
public void doSomething(final Integer someInt, final String someString) {
Validate.notNull(someInt, "Can't proceed when someInt is null!");
Validate.isTrue(!StringUtils.isEmpty(someString, "Can't proceed when someString is null or empty!");
//do stuff
}
}
If the validation fails, an IllegalArgumentException with the message defined as the second parameter will be thrown. Tests could then look like this:
public class SomethingTest {
private Something something;
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Before
public void setup() {
something = new Something();
}
#Test
public void doSomethingShouldFailIfSomeIntIsNull() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("someInt is null");
something.doSomething(null, "hello");
}
#Test
public void doSomethingShouldFailIfSomeStringIsEmpty() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("someString is null or empty");
something.doSomething(123, "");
}
//more tests..
}
I'm not sure that I'd be happy with this approach, what if checkAccessControl is called from many places? You have to rely on each caller doing the null check - it's not a safe way to proceed. I'd be putting the null check in to the checkAccessControl method, probably throwing IllegalArgumentException if a null was detected.
So, my broad approach would be, if your method relies on specific values being presented to it ( eg a parameter can't be null ), I would make it the responsibility of the method to validate it.
You can of course still ask the caller to validate the argument for you ( via javadocs for example ), but you can't enforce it.
I am writing a method which will return if something is true or not. But if the resources needed to test the condition are not available, it will not be able to return true or false.
Earlier, I was just making it a method which returns a boolean. But now, to accommodate exceptions, I am thinking of passing true or false in function arguments and using the return value as success or failure indicator for the test.
Is this the "correct and common" way of doing it in Java? Or is something else prevalent in Java to achieve this?
Your method should return a boolean and throw an Exception if resources are unavailable.
I'd definitely make the method throw an exception if it is not able to calculate the correct answer.
Now you have to decide if the exception thrown will be checked or unchecked. It really depends on the context. Usually, I think like this: if the caller has a way to ensure that the method cannot fail, I'd make it throw an unchecked exception; otherwise, if the caller has no way to be absolutely sure that the method will not fail, then I'd make it a checked exception.
This would be the case where the caller can determine the possibility of failure:
class C1 {
public boolean canCalculateResultNow() { ... }
public boolean calculateResult() {
if (cannot get resource) throw new IllegalStateException("Cannot get resource");
...
}
}
Now, here's what I'd do if the caller cannot be sure that the method will be able to complete normally:
class CannotCalculateResultException extends Exception { ... }
class C2 {
public boolean calculateResult() throws CannotCalculateResultException {
if (cannot calculate result) throw new CannotCalculateResultException();
...
}
}
Another possibility, which I really dislike and strongly discourage, is to make the method return Boolean, which is a nullable version of boolean. A Boolean can be true, false or null. You could then make the method return null if the resource is not available.
The main problem I see on this approach is that the meaning of null may not be clear. Calling code will always have to check if the result is null, and a developer (maybe even yourself some months after having written this code) will have to read the method's documentation to know what does a null result mean. An specific checked exception makes absolutely clear that something might go wrong and what can go wrong. Also, it would force the developer to prepare for the case in which something went wrong. On the approach with unchecked exceptions, the presence of the method canCalculateResult() will also indicated to the developer using the class that something might go wrong, without the need to read the documentation, and it is reasonable to assume that it is something "dangerous" to call calculareResult() without first calling canCalculateResult().
I would propose other approach: return not boolean, but Boolean and return true/false when there're resources and return null when there're no resources
It would be correct, but not a good practice. Instead, your method should return a boolean and handle exceptions if not capable of calculating the answer
This question already has answers here:
When to throw an exception?
(33 answers)
Closed 4 years ago.
Is it a good practice to make the constructor throw an exception?
For example I have a class Person and I have age as its only attribute. Now
I provide the class as
class Person{
int age;
Person(int age) throws Exception{
if (age<0)
throw new Exception("invalid age");
this.age = age;
}
public void setAge(int age) throws Exception{
if (age<0)
throw new Exception("invalid age");
this.age = age;
}
}
Throwing exceptions in a constructor is not bad practice. In fact, it is the only reasonable way for a constructor to indicate that there is a problem; e.g. that the parameters are invalid.
I also think that throwing checked exceptions can be OK1, assuming that the checked exception is 1) declared, 2) specific to the problem you are reporting, and 3) it is reasonable to expect the caller to deal with a checked exception for this2.
However explicitly declaring or throwing java.lang.Exception is almost always bad practice.
You should pick an exception class that matches the exceptional condition that has occurred. If you throw Exception it is difficult for the caller to separate this exception from any number of other possible declared and undeclared exceptions. This makes error recovery difficult, and if the caller chooses to propagate the Exception, the problem just spreads.
1 - Some people may disagree, but IMO there is no substantive difference between this case and the case of throwing exceptions in methods. The standard checked vs unchecked advice applies equally to both cases.
2 - For example, the existing FileInputStream constructors will throw FileNotFoundException if you try to open a file that does not exist. Assuming that it is reasonable for FileNotFoundException to be a checked exception3, then the constructor is the most appropriate place for that exception to be thrown. If we threw the FileNotFoundException the first time that (say) a read or write call was made, that is liable to make application logic more complicated.
3 - Given that this is one of the motivating examples for checked exceptions, if you don't accept this you are basically saying that all exceptions should be unchecked. That is not practical ... if you are going to use Java.
Someone suggested using assert for checking arguments. The problem with this is that checking of assert assertions can be turned on and off via a JVM command-line setting. Using assertions to check internal invariants is OK, but using them to implement argument checking that is specified in your javadoc is not a good idea ... because it means your method will only strictly implement the specification when assertion checking is enabled.
The second problem with assert is that if an assertion fails, then AssertionError will be thrown, and received wisdom is that it is a bad idea to attempt to catch Error and any of its subtypes.
I've always considered throwing checked exceptions in the constructor to be bad practice, or at least something that should be avoided.
The reason for this is that you cannot do this :
private SomeObject foo = new SomeObject();
Instead you must do this :
private SomeObject foo;
public MyObject() {
try {
foo = new SomeObject()
} Catch(PointlessCheckedException e) {
throw new RuntimeException("ahhg",e);
}
}
At the point when I'm constructing SomeObject I know what it's parameters are
so why should I be expected to wrap it in a try catch?
Ahh you say but if I'm constructing an object from dynamic parameters I don't know if they're valid or not.
Well, you could... validate the parameters before passing them to the constructor. That would be good practice.
And if all you're concerned about is whether the parameters are valid then you can use IllegalArgumentException.
So instead of throwing checked exceptions just do
public SomeObject(final String param) {
if (param==null) throw new NullPointerException("please stop");
if (param.length()==0) throw new IllegalArgumentException("no really, please stop");
}
Of course there are cases where it might just be reasonable to throw a checked exception
public SomeObject() {
if (todayIsWednesday) throw new YouKnowYouCannotDoThisOnAWednesday();
}
But how often is that likely?
As mentioned in another answer here, in Guideline 7-3 of the Java Secure Coding Guidelines, throwing an exception in the constructor of a non-final class opens a potential attack vector:
Guideline 7-3 / OBJECT-3: Defend against partially initialized
instances of non-final classes When a constructor in a non-final class
throws an exception, attackers can attempt to gain access to partially
initialized instances of that class. Ensure that a non-final class
remains totally unusable until its constructor completes successfully.
From JDK 6 on, construction of a subclassable class can be prevented
by throwing an exception before the Object constructor completes. To
do this, perform the checks in an expression that is evaluated in a
call to this() or super().
// non-final java.lang.ClassLoader
public abstract class ClassLoader {
protected ClassLoader() {
this(securityManagerCheck());
}
private ClassLoader(Void ignored) {
// ... continue initialization ...
}
private static Void securityManagerCheck() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
return null;
}
}
For compatibility with older releases, a potential solution involves
the use of an initialized flag. Set the flag as the last operation in
a constructor before returning successfully. All methods providing a
gateway to sensitive operations must first consult the flag before
proceeding:
public abstract class ClassLoader {
private volatile boolean initialized;
protected ClassLoader() {
// permission needed to create ClassLoader
securityManagerCheck();
init();
// Last action of constructor.
this.initialized = true;
}
protected final Class defineClass(...) {
checkInitialized();
// regular logic follows
...
}
private void checkInitialized() {
if (!initialized) {
throw new SecurityException(
"NonFinal not initialized"
);
}
}
}
Furthermore, any security-sensitive uses of such classes should check
the state of the initialization flag. In the case of ClassLoader
construction, it should check that its parent class loader is
initialized.
Partially initialized instances of a non-final class can be accessed
via a finalizer attack. The attacker overrides the protected finalize
method in a subclass and attempts to create a new instance of that
subclass. This attempt fails (in the above example, the
SecurityManager check in ClassLoader's constructor throws a security
exception), but the attacker simply ignores any exception and waits
for the virtual machine to perform finalization on the partially
initialized object. When that occurs the malicious finalize method
implementation is invoked, giving the attacker access to this, a
reference to the object being finalized. Although the object is only
partially initialized, the attacker can still invoke methods on it,
thereby circumventing the SecurityManager check. While the initialized
flag does not prevent access to the partially initialized object, it
does prevent methods on that object from doing anything useful for the
attacker.
Use of an initialized flag, while secure, can be cumbersome. Simply
ensuring that all fields in a public non-final class contain a safe
value (such as null) until object initialization completes
successfully can represent a reasonable alternative in classes that
are not security-sensitive.
A more robust, but also more verbose, approach is to use a "pointer to
implementation" (or "pimpl"). The core of the class is moved into a
non-public class with the interface class forwarding method calls. Any
attempts to use the class before it is fully initialized will result
in a NullPointerException. This approach is also good for dealing with
clone and deserialization attacks.
public abstract class ClassLoader {
private final ClassLoaderImpl impl;
protected ClassLoader() {
this.impl = new ClassLoaderImpl();
}
protected final Class defineClass(...) {
return impl.defineClass(...);
}
}
/* pp */ class ClassLoaderImpl {
/* pp */ ClassLoaderImpl() {
// permission needed to create ClassLoader
securityManagerCheck();
init();
}
/* pp */ Class defineClass(...) {
// regular logic follows
...
}
}
You do not need to throw a checked exception. This is a bug within the control of the program, so you want to throw an unchecked exception. Use one of the unchecked exceptions already provided by the Java language, such as IllegalArgumentException, IllegalStateException or NullPointerException.
You may also want to get rid of the setter. You've already provided a way to initiate age through the constructor. Does it need to be updated once instantiated? If not, skip the setter. A good rule, do not make things more public than necessary. Start with private or default, and secure your data with final. Now everyone knows that Person has been constructed properly, and is immutable. It can be used with confidence.
Most likely this is what you really need:
class Person {
private final int age;
Person(int age) {
if (age < 0)
throw new IllegalArgumentException("age less than zero: " + age);
this.age = age;
}
// setter removed
This is totally valid, I do it all the time. I usually use IllegalArguemntException if it is a result of parameter checking.
In this case I wouldn't suggest asserts because they are turned off in a deployment build and you always want to stop this from happening, but they are valid if your group does ALL it's testing with asserts turned on and you think the chance of missing a parameter problem at runtime is more acceptable than throwing an exception that is maybe more likely to cause a runtime crash.
Also, an assert would be more difficult for the caller to trap, this is easy.
You probably want to list it as a "throws" in your method's javadocs along with the reason so that callers aren't surprised.
I have never considered it to be a bad practice to throw an exception in the constructor. When the class is designed, you have a certain idea in mind of what the structure for that class should be. If someone else has a different idea and tries to execute that idea, then you should error accordingly, giving the user feedback on what the error is. In your case, you might consider something like
if (age < 0) throw new NegativeAgeException("The person you attempted " +
"to construct must be given a positive age.");
where NegativeAgeException is an exception class that you constructed yourself, possibly extending another exception like IndexOutOfBoundsException or something similar.
Assertions don't exactly seem to be the way to go, either, since you're not trying to discover bugs in your code. I would say terminating with an exception is absolutely the right thing to do here.
I am not for throwing Exceptions in the constructor since I am considering this as non-clean. There are several reasons for my opinion.
As Richard mentioned you cannot initialize an instance in an easy manner. Especially in tests it is really annoying to build a test-wide object only by surrounding it in a try-catch during initialization.
Constructors should be logic-free. There is no reason at all to encapsulate logic in a constructor, since you are always aiming for the Separation of Concerns and Single Responsibility Principle. Since the concern of the constructor is to "construct an object" it should not encapsulate any exception handling if following this approach.
It smells like bad design. Imho if I am forced to do exception handling in the constructor I am at first asking myself if I have any design frauds in my class. It is necessary sometimes, but then I outsource this to a builder or factory to keep the constructor as simple as possible.
So if it is necessary to do some exception handling in the constructor, why would you not outsource this logic to a Builder of Factory? It might be a few more lines of code but gives you the freedom to implement a far more robust and well suited exception handling since you can outsource the logic for the exception handling even more and are not sticked to the constructor, which will encapsulate too much logic. And the client does not need to know anything about your constructing logic if you delegate the exception handling properly.
It is bad practice to throw Exception, as that requires anyone who calls your constructor to catch Exception which is a bad practice.
It is a good idea to have a constructor (or any method) throw an exception, generally speaking IllegalArgumentException, which is unchecked, and thus the compiler doesn't force you to catch it.
You should throw checked exceptions (things that extend from Exception, but not RuntimeException) if you want the caller to catch it.