Kotlin has a require function which can be used like so (copied from the reference documentation):
fun getIndices(count: Int): List<Int> {
require(count >= 0) { "Count must be non-negative, was $count" }
// ...
return List(count) { it + 1 }
}
// getIndices(-1) // will fail with IllegalArgumentException
println(getIndices(3)) // [1, 2, 3]
The function essentially throws an IllegalArgumentException if the value is false.
Obviously this could very easily be implemented in Java - but I was wondering is there something already in the JDK or apache libraries (or any other ubiquitous libraries) which offers a function which does this?
You can use assert function that is equivalent to the Kotlin require method.
assert count >= 0 : "Count must be non-negative, was " + count;
Programming With Assertions
JDK disables assert operations by default. If you want to enable assert operations you must define enabled package or class locations with VM options like -ea:com.example.demo...
Enabling and Disabling Assertions
I prefer Spring Framework's org.springframework.util.Assert class, because there are lots of method for validating parameters.
Simpler way:
Assert.isTrue(count >= 0, "Count must be non-negative, was " + count);
Lazy way (For better performance and same flow like kotlin require function):
Assert.isTrue(count >= 0, () -> "Count must be non-negative, was " + count);
Spring Assert Statements
For Unit tests, you can use, Junit (org.junit.Assert) or Jupiter (org.junit.jupiter.api.Assertions) assertion functions.
There is a method requireNonNull() in java.util.Objects that takes an object reference and checks that for being null.
See the Javadoc here!
But obviously, that is less flexible as the Kotlin version …
Basically, you can write your own version of require() like this:
public static final void require( final boolean predicate, final Supplier<String> messageSupplier )
{
if( !predicate ) throw new IllegalArgumentException( messageSupplier.get() );
}
(Error handling omitted …)
You can use it like this:
…
require( count > 0, () -> String.format( "Count must be non-negative, was %d", count );
…
But this requires that count is effectively final (or constant), otherwise it will not compile.
This can be circumvented when creating require() like this:
public static final void require( final boolean predicate, final Object messageArgument, final Function<Object,String> messageSupplier )
{
if( !predicate ) throw new IllegalArgumentException( messageSupplier.apply( Objects.toString( messageArgument ) );
}
You can use it like this:
…
require( count > 0, count, arg -> String.format( "Count must be non-negative, was %s", arg );
…
But in case of a primitive type, you have to pay the price for the boxing when calling require().
That in turn can be avoided by having a whole family of require() methods, one for each primitive type …
If the main goal is to avoid temporary objects that are not used when the condition of predicate is met, I would assume, you should not use inline closures (() -> …) but method references (this::getMessage) as the Supplier/Function arguments … but I also think that we are here already on the path of premature optimisations.
public class TestAsserts {
public static void main(String[] argv) {
int count = -2;
testCount(count);
}
public static void testCount(int count) {
assert(count >= 0): "Count must be non-negative, was " + count;
}
}
would work the same way. You get to decide if assertions are enabled or not at runtime. To run this you'd need to pass -ea as a Java command line option.
Note the the exception is a bit different too:
Exception in thread "main" java.lang.AssertionError: Count must be non-negative, was -2
at TestAsserts.testCount(TestAsserts.java:12)
at TestAsserts.main(TestAsserts.java:8)
Since Java 1.4 there is the assert Keyword in the JDK, which could be used to do something pretty similar. Oin this case an AsserrionError is thrown.
Related
I have a class with the following field and method:
private final Map<Character, String> charMap = new LinkedHashMap<>();
public Character charOf(String s) {
assert this.charMap.containsValue(s);
for (Character c : this.charMap.keySet()) {
if (this.charMap.get(c).equals(s)) return c;
}
}
The compiler doesn't like this, giving me a "missing return statement" error, whereas this compiles fine:
private final Map<Character, String> charMap = new LinkedHashMap<>();
public Character charOf(String s) {
for (Character c : this.charMap.keySet()) {
if (this.charMap.get(c).equals(s)) return c;
}
throw new IllegalArgumentException("There is no mapping for \"" + s + "\"");
}
As far as I can tell, these two methods should function exactly the same and do the exact same thing with the former being slighly more readable (at the expense of a less detailed error message). It will always either return a value or throw an exception. Why does the compiler not realize this?
There are two reasons:
The complier is not 'smart' enough to figure out that this.charMap.containsValue(s) being true means this.charMap.get(c).equals(s) must be true for some c. It only does simpler analysis, like checking if both branches of an if-statement have a return in them.
Even if it were smart enough, Java is a language with mutable objects and threads - even if the map contains the key at the time of the assert, it may be removed from the map by another thread before the loop starts.
If you want a language with a sufficiently 'smart' compiler, you might want to look at dependently-typed languages like Idris.
Because of two things:
Firstly, assertions only throw exceptions if they are enabled at run-time using the jvm argument -ea. This means there is a possibility that is skipped.
Secondly, you throw the exception at the end while you run the assertion before the code. Theoretically, the assertion could be true without the loop returning as the Map content could theoretically change between the assertion and the loop or containsValue could do something the compiler doesn't expect. The compiler just checks for sytax, not for logical impossibilities.
This has more to do with JLS: https://docs.oracle.com/javase/specs/jls/se10/html/jls-8.html#jls-8.4.7 than with assert:
If a method is declared to have a return type (§8.4.5), then a
compile-time error occurs if the body of the method can complete
normally (§14.1).
In other words, a method with a return type must return only by using
a return statement that provides a value return; the method is not
allowed to "drop off the end of its body". See §14.17 for the precise
rules about return statements in a method body.
Since your method must return a value (not void), only return or throw return the execution flow to the caller.
This rule ensure you avoid such case (this is a C example):
#define N = 10;
const char* CHAR_MAP[N] = ...;
const char CHAR_VALUE[N] = ...;
char charOf(const char* s) {
for (int i = 0; i < N; ++i) {
if (strcmp(s, CHAR_MAP[i]) == 0) {
return CHAR_VALUE[i];
}
}
// not return value
}
My C is a bit rusty, this might not compile but the point is: in C - at least in C99 - the value returned in this case is undefined which may lead to several nasty problems, especially with pointers.
The rule in Java ensure that you always:
Return a value, eg: null.
Throw an exception, meaning an error.
This does not means the returned value will make thing works: returning null here may produce NullPointerException.
Beside, on a side note:
public Character charOf(String s) {
for (Map.Entry<Character,String> entry : this.charMap.entrySet()) {
if (s.equals(entry.getValue()) {
return entry.getKey();
}
}
throw new IllegalArgumentException("There is no mapping for \"" + s + "\"");
}
You should avoid mixing keySet() and get() when you can use entrySet().
The doc says
Conceptually, it is a union of Single and Completable providing the
means to capture an emission pattern where there could be 0 or 1 item
or an error signalled by some reactive source.
But I am not sure what it truly means. It seems it is java8's Optional.
The following two codes have the same result , but I don't know what Maybe can do and Optional cannot (or cumbersome) do.
#Test
public void testMaybe1() {
Observable.just(3, 2, 1, 0, -1)
.map(i -> {
try {
int result = 6 / i;
return Maybe.just(result);
} catch (Exception e) {
return Maybe.empty();
}
})
.blockingForEach(maybe -> {
logger.info("result = {}", maybe.blockingGet());
}
);
}
#Test
public void testMaybe2() {
Observable.just(3, 2, 1, 0, -1)
.map(i -> {
try {
int result = 6 / i;
return Optional.of(result);
} catch (Exception e) {
return Optional.empty();
}
})
.blockingForEach(opt -> {
logger.info("result = {}", opt.orElse(null));
}
);
}
The results are the same :
result = 2
result = 3
result = 6
result = null
result = -6
In rxJava1 , My API used to return Observable<Optional<T>> , Is it a bad smell ? Should I change to Observable<Maybe<T>> ?
Maybe is a wrapper around an operation/event that may have either
A single result
No result
Error result
However Optional is a wrapper around a value that may either be
Present
Absent
In your example, in the map operation, the computation is synchronous (i.e. 6/i is synchronous and can result in a value immediately) and you want to propagate a value (if division is possible) or empty value (if division is not possible). Hence using Optional makes more sense.
There are however other options also:
If you want to propagate why division is not possible then you would want to report the exception that occurred. In such a case using Maybe will make more sense.
If you are not interested in both empty value and reason of error, then you simply want to skip propagating those results. In such a scenario I would use a flatMap instead of map. I will then not have to use any of Optional or Maybe.
.flatMap(i -> {
try {
int result = 6 / i;
return Observable.just(result);
} catch (Exception e) {
return Observable.empty();
}
})
Maybe is also useful when you have an Observable that can emit multiple values but you are interested in, let's say, only the first one and hence you use the firstElement() operator on the Observable. This returns a Maybe because either there is a single value, or there is no value (if source Observable does not emit any value before completing) or there is an error (if source Observable errors before emitting any value).
Maybe is a lazy stream of zero or one things (and being a stream can result in an error). Optional is not lazy, it it is either present or absent. There is no sense of deferred calculation with an Optional whereas there is with Maybe.
The difference relevant to your question is that Maybe can propagate error while Optional cannot - in your example one cannot distinguish between error and empty result. If error handling is important, Optional is useless, while Maybe has Maybe.error(Throwable). API-wise, for your use case I would prefer Single to Maybe - because it yields either Error or single Result, so return type would be Observable<Single<T>>
RxJava 2 targets Java 6. This means there is no builtin Optional support guaranteed, and they have to bring their own. Similar to how they have to bring their own Function types.
If your application/library only supports Java >= 8 you can use whatever suits you better.
Since Java's assert keyword is fundamentally broken on Android, I am about to implement an assertion class that can be configured to check assertions in release builds as well.
Now I can do something like:
MyAssertion.assert(a != 2)
which throws an AssertionException when the expression is false. But how can I get a String representation of the expression to pass to the error message?
The only way is to add a String parameter to your assert method:
MyAssertion.assert(a != 2, "a must not be equal to 2");
What you get as input for assert is either true or false so you can't build a representative String from that.
Otherwise, you could implement assert like this:
MyAssertion.assertNotEquals(a, 2);
When this fails, you know that it is because what you tested was equal to 2 and you can build an informative message (though you won't know what specifically was equal to 2).
If you want to somehow be able to construct a meaningful message from an assertion, the only way I see it possible is to construct an String expression, ask the JavaScript engine to evaluate it and build a message if the expression evaluates to false. Note that will degrade a lot performance as launching the JavaScript engine takes a lot of time. This could be solved with a mechanism of disabling assertions in production.
The following is an example of that. Note that I'm using the new Java 8 Nashorn JavaScript engine but this should work with the older Rhino.
Usage example:
int value = 3;
String str = "test";
Assertions.assertTrue("$1 == 3", value);
Assertions.assertTrue("$1 == 3 && $2 == 'test'", value, str);
Assertions.assertTrue("$1 == 4 && $2 == 'test'", value, str);
This will throw for the 3rd assertion:
An assertion has failed: 3 == 4 && 'test' == 'test'
The idea is that you can write any JavaScript-friendly expression that can be evaluated to a boolean. The placeholders $i will be replaced by what's given as a parameter to the method ($1 will be replaced by the first parameter, etc.).
This is the class. It could be improved (handle error conditions like not enough parameters, etc.) but this should be enough to get you started.
public final class Assertions {
private static final ScriptEngine ENGINE = new ScriptEngineManager().getEngineByName("nashorn");
private Assertions() { }
public static void assertTrue(String expression, Object... values) {
for (int i = 0; i < values.length; i++) {
ENGINE.put("$" + (i+1), values[i]);
}
try {
boolean pass = (Boolean) ENGINE.eval(expression);
if (!pass) {
for (int i = 0; i < values.length; i++) {
expression = expression.replace("$" + (i+1), stringRepresentation(values[i]));
}
throw new AssertionError("An assertion has failed: " + expression);
}
} catch (ScriptException e) {
throw new InternalError(e);
} finally {
for (int i = 0; i < values.length; i++) {
ENGINE.getBindings(ScriptContext.ENGINE_SCOPE).remove("$" + (i+1));
}
}
}
private static String stringRepresentation(Object o) {
if (o instanceof String) {
return "'" + o + "'";
}
return o.toString();
}
}
Annotation processing can do this. You'd create an annotation e.g. #InlineAssertExpressions. Then write a processor that parses your source file and creates a string representing the expression and adds it to the call to your assert method, which you could overload to take an optional String argument. This way is quite optimal performance-wise, since the inlining happens compile-time. Annotation processing is a bit overlooked, but I think this is a great use for it.
(1) Simple to use, but hard to implement. Java 8 required. You can use lambda expressions:
Assert.isTrue(() => a != 2)
On evaluation failure your implementation of Assert.isTrue method should repeat all steps as IDEs do - (a) discover bytecode of lambda class, (b) decompile e.g. with JAD, (c) discover sources if available
(2) Simple to use, simple to implement, but does not fully cover your requirements. You can use CodeStyle rules to check & force correct assertions usage. One regexp will check there is no single-argument assertions, the second (using regexp back refs) will check code and text description are similar.
(3) Simple to use, simple to implement, but relies on your build system. You can automatically check and fix source code during project build.
E.g. for Maven build system you can create your own plugin to check and fix assertions usage in sources on process-sources stage.
I think you cannot access the internal java expression, which was passed to method call.
You can, however, use some expression language libraries and do a custom expression handling for your assertion implementation.
Here is a list of some expression language libraries:
http://java-source.net/open-source/expression-languages
Hope that helps :)
I have a little method that amongst other things also converts a string into an integer. Since the string is a parameter of the method I want to make sure that that string is convertable. So I was just wondering what would be the safest and / or fastest way.
Version A: Just leave it as it is and take the risks (which I'm trying to avoid)
public static int stringToInt(String param) {
return Integer.valueOf(param);
}
(in terms of speed, what kind of difference would it make to version B and C?)
Version B: Catch the exception
public static int stringToInt(String param) {
try {
return Integer.valueOf(param);
} catch(NumberFormatException e) {
return -1;
}
}
Version C: Check each letter of the string to see, if it's a digit number or not
public static int stringToInt(String param) {
for(char c : param.toCharArray()) {
if(!Character.isDigit(c))
return -1;
}
return Integer.valueOf(param);
}
Note that the parameter has to be a positive number and the -1 is supposed to be the "error value" in my little program, in other words, all three versions of methods would work perfectally fine in my program.
I'm very open to any other suggestion you can give me, so feel free to create your own version, if you think yours is better.
Thank you very much for your support in advance.
Guava offers a utility method for this which returns null in case your String can't be parsed.
https://google.github.io/guava/releases/19.0/api/docs/com/google/common/primitives/Ints.html#tryParse(java.lang.String)
Integer result = Ints.tryParse("1"); //returns 1
Integer result = Ints.tryParse("-1"); //returns -1
Integer result = Ints.tryParse("a"); //returns null
First, note that version C is not bulletproof: it would reject negative numbers, and would not catch numbers that are too large.
Version B is OK, yet it makes the caller change the coding style: rather than catching an error and processing it together with other errors, the caller would need to check for -1 all the time. This may be suboptimal in situations where you read multiple integers, but the error processing does not depend on which particular one has failed. In addition, new coders using your API may forget to check for -1, and use the error code inadvertently.
That's why I would stay with the first option: the code using version A would look instantly familiar to anyone who knows Java API, without the need to learn what happens inside your function.
I believe a modified B to throw an exception rather than returning -1 will be the best choice. It is good to throw the exception up to the level, where it can be processed to send the proper response to the user. Returning a value like -1 will make your code error prone. Assume that a different programmer is consuming your method and he/she just have the signature of your method. So it is not clear from the signature what he/she should code to handle an exception or error scenario. But if you throw the exception and add it to your method declaration then it will enable the other programmer to consume your method properly alongwith the required exception handling. For me this looks the best:
public static int stringToInt(String param) throws NumberFormatException {
try {
return Integer.valueOf(param);
} catch(NumberFormatException e) {
// return -1;
throw e;
}
}
Java 8 without any API:
Optional.ofNullable(strNum)
.map(Integer::valueOf).orElse(null);
public int stringToInt(String param) throws NumberFormatException {
Optional.ofNullable(param.replaceAll("\\s+", ""))
.map(Integer::valueOf).orElse(null);
/*
or
Optional.ofNullable(param.replaceAll(" ", ""))
.map(Integer::valueOf).orElse(null);
*/
}
use the replaceAll to replace white spaces the plus is cpu friendly even though seems not needed.
I used a combination of 2 answers to have it safe for nulls, empty or blank strings, and non numeric characters:
public static Integer safeStringToInt(String param) {
return Optional.ofNullable(param).map(Ints::tryParse).orElse(null);
}
What are the best practices if you have a class which accepts some parameters but none of them are allowed to be null?
The following is obvious but the exception is a little unspecific:
public class SomeClass
{
public SomeClass(Object one, Object two)
{
if (one == null || two == null)
{
throw new IllegalArgumentException("Parameters can't be null");
}
//...
}
}
Here the exceptions let you know which parameter is null, but the constructor is now pretty ugly:
public class SomeClass
{
public SomeClass(Object one, Object two)
{
if (one == null)
{
throw new IllegalArgumentException("one can't be null");
}
if (two == null)
{
throw new IllegalArgumentException("two can't be null");
}
//...
}
Here the constructor is neater, but now the constructor code isn't really in the constructor:
public class SomeClass
{
public SomeClass(Object one, Object two)
{
setOne(one);
setTwo(two);
}
public void setOne(Object one)
{
if (one == null)
{
throw new IllegalArgumentException("one can't be null");
}
//...
}
public void setTwo(Object two)
{
if (two == null)
{
throw new IllegalArgumentException("two can't be null");
}
//...
}
}
Which of these styles is best?
Or is there an alternative which is more widely accepted?
The second or the third.
Because it tells the user of your API what exactly went wrong.
For less verbosity use Validate.notNull(obj, message) from commons-lang. Thus your constructor will look like:
public SomeClass(Object one, Object two) {
Validate.notNull(one, "one can't be null");
Validate.notNull(two, "two can't be null");
...
}
Placing the check in the setter is also acceptable, with the same verbosity comment. If your setters also have the role of preserving object consistency, you can choose the third as well.
Java 7 added java.util.Objects.requireNonNull() to the APIs everybody can use. So checking all arguments for null boils down to a short list like:
this.arg1 = Objects.requireNonNull(arg1, "arg1 must not be null");
this.arg2 = Objects.requireNonNull(arg2, "arg2 must not be null");
Side notes:
make sure to not reverse the two arguments - the second one is the message that will be used for the NPE which is thrown if the first argument is null (if you reverse them, well, then your check will never fail)
another best practice: if possible, make all your class members final (so you can be sure: when some object has been created successfully, all its members are not null; and they won't change over time)
You can use one of the many libraries designed to facilitate precondition checks. Many code in Google Guava uses com.google.common.base.Preconditions
Simple static methods to be called at the start of your own methods to verify correct arguments and state. This allows constructs such as
if (count <= 0) {
throw new IllegalArgumentException("must be positive: " + count);
}
to be replaced with the more compact
checkArgument(count > 0, "must be positive: %s", count);
It has checkNotNull that is used extensively within Guava. You can then write:
import static com.google.common.base.Preconditions.checkNotNull;
//...
public SomeClass(Object one, Object two) {
this.one = checkNotNull(one);
this.two = checkNotNull(two, "two can't be null!");
//...
}
Most methods are overloaded to either take no error message, a fixed error message, or a templatized error message with varargs.
On IllegalArgumentException vs NullPointerException
While your original code throws IllegalArgumentException on null arguments, Guava's Preconditions.checkNotNull throws NullPointerException instead.
Here's a quote from Effective Java 2nd Edition: Item 60: Favor the use of standard exceptions:
Arguably, all erroneous method invocations boil down to an illegal argument or an illegal state, but other exceptions are standardly used for certain kinds of illegal argument and states. If a caller passes null in some parameter for which null values are prohibited, convention dictates NullPointerException be thrown rather than IllegalArgumentException.
A NullPointerException isn't reserved for just when you access members of a null reference; it's pretty standard to throw them when an argument is null when that's an illegal value.
System.out.println("some string".split(null));
// throws NullPointerException
I would have a utility method:
public static <T> T checkNull(String message, T object) {
if(object == null) {
throw new NullPointerException(message);
}
return object;
}
I would have it return the object so that you can use it in assignments like this:
public Constructor(Object param) {
this.param = checkNull("Param not allowed to be null", param);
}
EDIT: Regarding the suggestions to use a third party library, the Google Preconditions in particular does the above even better than my code. However, if this is the only reasons to include the library in your project, I'd be hesitant. The method is too simple.
Apart from the answers given above which are all valid and reasonable, I think it's good to point out that maybe checking for null isn't necessary "good practice". (Assuming readers other than the OP might take the question as dogmatic)
From Misko Hevery blog on testability:
To Assert or Not To Assert
An alternative to throwing an unchecked exception would be the usage of assert. Otherwise I´d throw checked exceptions to make the caller aware of the fact, that the constructor will not work with illegal values.
The difference between your first two solutions - do you need a detailed error message, do you need to know which parameter failed or is it enough to know, that the instance couldn't have been created due to illegal arguments?
Note, that the second and third example can't report correctly that both parameters have been null.
BTW - I vote for a variation of (1):
if (one == null || two == null) {
throw new IllegalArgumentException(
String.format("Parameters can't be null: one=%s, two=%s", one, two));
}
Comparison of Ways to Check Preconditions in Java - Guava vs. Apache Commons vs. Spring Framework vs. Plain Java Asserts
public static void fooSpringFrameworkAssert(String name, int start, int end) {
// Preconditions
Assert.notNull(name, "Name must not be null");
Assert.isTrue(start < end, "Start (" + start + ") must be smaller than end (" + end + ")");
// Do something here ...
}
public static void fooApacheCommonsValidate(String name, int start, int end) {
// Preconditions
Validate.notNull(name, "Name must not be null");
Validate.isTrue(start < end, "Start (%s) must be smaller than end (%s)", start, end);
// Do something here ...
}
public static void fooGuavaPreconditions(String name, int start, int end) {
// Preconditions
Preconditions.checkNotNull(name, "Name must not be null");
Preconditions.checkArgument(start < end, "Start (%s) must be smaller than end (%s)", start, end);
// Do something here ...
}
public static void fooPlainJavaAsserts(String name, int start, int end) {
// Preconditions
assert null != name : "Name must not be null";
assert start < end : "Start (" + start + ") must be smaller than end (" + end + ")";
// Do something here ...
}
this is summary of this article:
http://www.sw-engineering-candies.com/blog-1/comparison-of-ways-to-check-preconditions-in-java
Annotations for static analysis are also useful, either in-addition-to or in-place-of the run-time checks.
FindBugs, for example, provides an #NonNull annotation.
public SomeClass( #NonNull Object one, #NonNull Object two) {
You can simply have a method which takes all the constructor arguments that you need to validate. This method throws exception with specific message depending on which argument is not valid.
Your constructor calls this method, and if it passes, it initialize values.
I assume that you talk about the built in assert in Java. In my opinion it's not a really good idea to use it. Since it can be turned on/off using command line parameters. Therefore some says it is only acceptable to use in private methods.
My mentors are telling me not to re-invent the wheel! Their advice is to use libraries. They are (probably) well designed and tested. Of course it is your responsibility to make sure you grab a good-quality library.
Others are telling me that Enterprise ppl - in some terms - are wrong and you introduce more dependency - for simple tasks - than required. I can accept that point too... But here is my latest experience:
First I wrote my own private method to check null parameters. It's boring and redundant. I know I should put it into a Utility class. But why should I write it at the first place, when someone has already has done it? I can save time not writing unit test and design an existing stuff. Unless you want to exercise or learn I wouldn't recommend to do so.
I recently started to use google's guava and I find that - along with apache commons - once you start to use them, you won't use just for that one single method. You'll discover and use it more and more. At the end, this'll make your code shorter, more readable, more consistent and more maintainable.
BTW.: Depending on your aims I would go with 2 or 3 using one of the mentioned library above...