8

I always check the arguments of public functions and throw exceptions when something's wrong. (For private helpers I use assertions).

Like this:

if( a < 0 || a >= b )
    throw new IllegalArgumentException("'a' must be greater or equal to 0 and 
        smaller than b ");

But it always annoys me to write these error messages. The message seems redundant to me, as the message is just the negation of the statement

a < 0 || a >= b

.

It also often happens that I rename the variable with refactoring (in eclipse) and then the message does not reflect the changes. Or I change the conditions and forget to change the messages.

It would be great, if I could write something like:

assertArgument(a >= 0 && a < b);

This should raise an IllegalArgumentException with a message like

"violated argument assertion: a >= 0 && a < b."

In C you could write a macro (actually in C assert is just a macro). Is there a simple way to do something like this in java?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Dario Seidl
  • 4,140
  • 1
  • 39
  • 55
  • You could generate Java code during build ... but the pain is not worth it. Your problem is not deadly - as long as you can id a line, you will be ok. You could also write Python script to go through code and check for inconsistencies. – Hamish Grubijan Jul 25 '10 at 20:20
  • 1
    How about creating a helper function `checkParam(param, paramName)`? Then, even after you rename variables, you can still fie up a quick Python script to look for all instances of checkParam, and make sure that they are kosher. Perhaps someone else can expand on this idea. – Hamish Grubijan Jul 25 '10 at 21:39
  • You could even use reflection in Debug mode. – Hamish Grubijan Jul 26 '10 at 00:50
  • I also thought about such helper functions, maybe that's the best way to go. What do you mean by "reflection in Debug mode"? – Dario Seidl Jul 26 '10 at 10:09
  • I just came across Guava's [Preconditions](http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/Preconditions.html). This class provides such helper methods. – Dario Seidl Sep 24 '11 at 15:03
  • 1
    See the `Objects.requireNonNull` method added to the JRE subsequent to this question being asked. – Raedwald Sep 16 '21 at 06:29

1 Answers1

2

In the C language you cannot use macros to do this, but in cpp (the C preprocessor) you can :-) If you really want to do so there is nothing that restricts you from running cpp on your java source before it gets compiled. That would let you use cpp style macros (you might need to strip the lines starting with #line from the cp output.)

To reproduce the conditional in the exception is IMHO including too much implementation detail. If your exception message describes the violation in the contract in terms of the contract (for instance "no parent object given", "amount cannot be negative") you don't need to change it every time the condition changes.

rsp
  • 23,135
  • 6
  • 55
  • 69
  • You're right about the preprocessor, but I would consider the C preprocessor as a part of C programming. Preprosessor statements are maybe not really part of the C language, as the C compiler never gets to see them, but they are really essential in writing C programs. – Dario Seidl Jul 26 '10 at 09:56
  • And thanks for the suggestions: Using a Preprocessor or runnning a Scipt (as Hamish Grubijan suggested) to change or check the code, could solve my (really not so deadly) problem. Altough I thought more of a simple and native Java solution, as it is also important that other people clearly understand whats happening. Then again I could share only the generated code... Could maybe Design by Contract help? I have no experience with DbC so far. – Dario Seidl Jul 26 '10 at 10:05
  • If are looking into preprocessors, you might want to look into M4 (http://www.gnu.org/software/m4/) DbC can help, but you would not normally run the instrumented code in production. Because your requirement is one-of a perl or python script that fixes up your exception argument is probably the quickest way to go. – rsp Jul 26 '10 at 10:41