3

How can I test whether a given method will throw an exception or not (depending on the passed object) without invoking it?

For example:

public static boolean isAllowed(SomeObject obj)
{
    try
    {
        myMethod(obj);
        return true;
    }
    catch(Exception ex)
    {
        return false;
    }
}

but the above method will perform MyMethod(), how can I achieve this in java?

EDIT:

Actually, I want to do this to validate a filename. see this: Validate a file name on Windows

Community
  • 1
  • 1
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • You can inspect the source code if you have it, and look at documentation if you don't. If you have neither, you'll have to run it. – dlev Jul 21 '11 at 15:33
  • You can't in Java or in any other programming language I can think of. Maybe in C/C++ with preprocessor directives. – Marcelo Jul 21 '11 at 15:34

7 Answers7

6

As others have said, it is in general impossible to tell whether an exception will be thrown based on the input without actually computing it. Java is turing complete, so this is reducible to the halting problem. However, you can find all exceptions that a method can throw at runtime:

try {
    Method myMethod = this.getClass().getMethod("myMethod");
    System.out.println(Arrays.toString(myMethod.getExceptionTypes()));
} catch (NoSuchMethodException e) {}
DimaSan
  • 12,264
  • 11
  • 65
  • 75
stefan
  • 1,511
  • 9
  • 13
  • Does this include `RuntimeException` and subclasses? Propably not, as there's no `throws` for them. –  Jul 21 '11 at 15:57
  • @delnan it indeed will only report checked exceptions as declared in the method's signature. That's about as good as the OP can do, though. Consider this code: `void foo() { if ([condition requiring solution of the halting problem]) throw new Exception(); }` Does such a method throw an exception? (See http://blogs.msdn.com/b/ericlippert/archive/2009/10/12/absence-of-evidence-is-not-evidence-of-absence.aspx for some related info.) – dlev Jul 21 '11 at 15:59
  • I'm not doubting your conclusing that it's not possible in general - that's without doubt. I'm just saying that "listed in `throws`" isn't equivalent to "can actually be thrown". –  Jul 21 '11 at 16:01
3

You can provide a sibling method isAllowed() that tests explicitly for the conditions that result in the exception.

Risk of error exists. The two methods need to keep synchronized the conditions leading to an exception. However, frequently it is feasible to write the test method correctly.

From Joshua Bloch's "Effective Java":

A class with a "state-dependent" method that can be invoked only under certain unpredictable conditions should generally have a separate "state-testing" method indicating whether it is appropriate to invoke the state-dependent method.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
2

In the general case, you can't. For example, the method in question might use a random number generator to decide whether to throw an exception or not. Or for a more realistic example, if the method in question tries to open a file, then you can't know in advance whether some other process might delete that file just before you try to open it (which would cause an exception).

Java tells you whether it might throw an exception at compile time (w/ throws declarations), but you can't determine whether it actually will throw an exception without executing it.

Edward Loper
  • 15,374
  • 7
  • 43
  • 52
1

You cannot know at compile time if the method will throw an exception at runtime or not.

If you want to know if the method can throw exception; just don't enclose that method in try-catch block. Editor like ecliple will clearly show a compilation error, if the method was throwing an exception.

This is what you want; or I misunderstood your question.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • You can't know at compile time if a method will thrown an exception at run time. Only uncaught checked exceptions will raise compiler errors; unchecked exceptions won't. – Paul Jul 21 '11 at 15:37
1

Clearly if you don't want to invoke but need to understand behavior if invoked, then you need to read the method byte codes.

Another option is to provide a mock-classloader and load mock classes (and thus no-op method implementations).

In a fully functional universe, the above would be a reasonable approach. Given it is Java, the question of how you guarantee and measure side-effects remains to be answered. Perhaps the above will work for your specific case, but for the general case you are effectively asking for static analysis of Java bytecodes and that is probably an entire domain of study in its own right.

alphazero
  • 27,094
  • 3
  • 30
  • 26
1

It's better to understand the methods and the valid parameters than to blindly test methods before calling (which is not possible).

Validate your parameters before passing them to the method. Here's a trivial illustration where passing null would cause an exception:

int getLength(String s)
{
  return s.length();
}

void someMethod()
{
  int len = -1;
  if (myString != null)
    len = getLength(myString);
}
Paul
  • 19,704
  • 14
  • 78
  • 96
0

Create a jUnit test

http://www.junit.org/

ben
  • 472
  • 1
  • 3
  • 10