@Contract for methods that validate their arguments

How do you say "this method will throw or return not-null" in a @Contract annotation?

For example, given the following method:

public void foo(Integer price, Integer markup) {
    if (price == null) {
        return null;
    if (markup < 0 || markup > 100) {
        throw new IllegalArgumentException("Markup must be a percentage less than 1");
    return price.intValue() + ((price.intValue() * markup.intValue())  / 100);

With a contract of:

@Contract("null, _ -> null; !null, _ -> !null")

IntelliJ complains that throw breaks the contract.

@Contract("null, _ -> null; !null, _ -> !null; !null, _ -> fail")

IntelliJ seems to treats the contract as a succession of constraints, so !null, _ -> !null; is still violated by the contract.

@Contract("null, _ -> null; !null, _ -> fail")

Initially, IntelliJ does not complain about this, but it's wrong as fail is for methods that will throw an exception if the conditions are met. It also complains in the calling code that the method throws an exception.

Is there any way to enforce the rule that the method will return null if passed null and only if it is passed null, if the method may throw an exception?

Message was edited by: Robert Lee to fix typo

1 comment
Comment actions Permalink

Thanks for the detailed question!
Unfortunately, this doesn't seem to be possible with the current contract language. Do you have any suggestions how it could be expanded?


Please sign in to leave a comment.