Avoid null checks?

I wonder if it would be possible to 'avoid' null checks in Java, take an example from this code:

@Override
public List<AccountBean> search(AccountConstraint... c) {
    if (c.length == 0) {
        throw new IllegalArgumentException("dao.AccountDAO.search: c.length == 0");
    }
    try {
        List<AccountBean> beans = new ArrayList<>();
        for (AccountConstraint ac : c) {
            Builder builder = new QueryBuilder.Builder("SELECT * FROM accounts");
            if (ac.getAccountId() != null) {
                builder.clause("accountId >= " + ac.getAccountId().getMin() + " AND accountId <= " + ac.getAccountId().getMax());
            }
            if (ac.getUsername() != null) {
                builder.clause("username = "" + ac.getUsername() + """);
            }
            if (ac.getPassword() != null) {
                builder.clause("password = "" + ac.getPassword() + """);
            }
            if (ac.getEmail() != null) {
                builder.clause("email = "" + ac.getEmail() + """);
            }
            PreparedStatement ps = connection.prepareStatement(builder.build().getQuery());
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                beans.add(new AccountBean(rs));
            }
        }
        return beans;
    } catch (SQLException ex) {
        throw new RuntimeException(ex);
    }
}

It has to check 4 times for the != null because else the code would fail.

Is it possible to turn the if (object != null) statements into one-liners that only execute if there is no NullPointerException? When there is an exception, the line should just be ignored.

I am not talking about a general language feature here, I am talking about a feature that would only be turned in when you explicitely decide to do so.

For example: NullCheck(builder.clause("username = "" + ac.getUsername() + """)); would be a snippet of the suggested code.

Is something like that possible in Java?

Also if it is not possible, might it be possible in Java 8 to use methods (voids) directly in methods?

So then code like this could actually work?

public static NullCheck(Void void) {
    try {
        void.execute();
    }
    catch (NullPointerException e) {
        //ignore
    }
}

I know I could put the method inside it's own class that extends an interface that has method execute() and then pass that class around, but that would defeat the purpose of getting rid of the null checks or anything that would be even more complicated.

Regards.

WARNING: The way I used PreparedStatement here is prone to SQL Injection. Do not reuse this code.


Yes and No.

There are two approaches to tackle the null problem:

Special Operators like the Safe Navigation Operator in Groovy. If xy throws a NullPointerException x?.y returns just null . Since Java does not allow creation of new operators, you can't do this in Java. Operators like this where considered for JDK8 but where dropped. If you want have something like this, switch to Groovy or one of the many other languages having this feature.

Special Class many languages have a special interface for representing a value that might be null . In Scala it is called Option. Option has two implementations: None + Some . None replaces null . Whenever you want to do something with the value, you don't use it directly, but you call map on the Option with a function as an argument. If it is actually a None, nothing happens, you just get back None. If it is a Some, the function gets executed on the value and you get an Option with the result. That way you can work with Options all the time, without worrying about null s.

Actually it is in now way special, so you can create such a class yourself with Java. The problem is only, that Java doesn't have functions, so you have to use anonymous classes. This makes the whole thing really cumbersome and only a theoretical option.

JDK8 has a Option class. As far as I know it is missing the map method which makes the whole thing a bad joke in my opinion. But since the most important tool (anonymous functions) are there will be a proper Option implementation provided by one of the usual suspects (Google, Apache ...)


You can avoid these checks by assuming that these methods do not return null values.

How can you assume this? By having the specification for the AccountConstraint say so. The code in AccountConstraint is then responsible for ensuring the values are not null, rather than your search method being responsible for handling null values. You might have to change the design of AccountConstraint to do this.

And what happens if your assumption is wrong? That is, if AccountConstraint is buggy. An exception will be thrown, which you were not expecting. But that is what can happen when you have a bug: an unexpected exception is thrown. Debugging the code will be easy, because the stacktrace will show you which method of AccountConstraint is returning an invalid null value.


As it stands, you could probably write a method like

public void clauseIfNotNull(Builder builder, String format, Object o) {
  if (o != null) {
    builder.clause(String.format(format, o));
  }
}

and then that'd look like clauseIfNotNull(builder, "username = "%s"", ac.getUsername());

Other than that, there's not much you can do with Java 7.

链接地址: http://www.djcxy.com/p/76152.html

上一篇: 获取NullPointerException对由JAXB解组的空值调用方法

下一篇: 避免空检查?