使用null检查或首选空方法?

时间:2013-12-07 16:54:20

标签: java performance coding-style

方案

我想提供可选在我的工作类中添加回调的可能性。这种回调的界面可能看起来像这样:

public interface Callback<T> {

    void callback(final T data);

}

因为回调是可选的,所以每次调用之前我都需要检查是否在工作类中设置了一个:

public void doWork(final T data) {
    if (callback != null) {
        callback.callback(data);
    }

    // do the actual work
}

所以我想知道是否有一个非操作回调而不是看起来像这样:

@SuppressWarnings("rawtypes")
public class NopCallback implements Callback {

    public static final NopCallback CALLBACK = new NopCallback();

    @Override
    public void callback(final Object data) {
        // do nothing
    }

}

默认情况下,worker会将其回调设置为此NopCallback:

@SuppressWarnings("unchecked")
public Worker() {
    callback = NopCallback.CALLBACK;
}

实际问题

我已经发现Nop变体似乎表现更好(通过调用doWork(...)几次1000并测量每个变体的持续时间)。我并不完全满意的是需要@SuppressWarnings。我知道我可以摆脱它们但是在我的每个工作类中都需要一个自己的NopCallback实例。

长话短说,就是清洁代码可读性性能等意义上使用这种无操作回调的好主意或者还有其他(优雅的)替代方案吗?

2 个答案:

答案 0 :(得分:4)

这看起来很优雅。它与Collections.emptyList()基本相同,它总是返回相同的空的不可变列表。我不会把它变成公共类,但会使用工厂方法来获取它,以确保警告只在一个地方,其余的代码是类型安全的:

@SuppressWarnings("unchecked")
private static final Callback NOP = new Callback() {
    @Override
    public void callback(final Object data) {
        // do nothing
    }
};

@SuppressWarnings("unchecked")
public static final <T> Callback<T> nop() {
    return (Callback<T>) NOP;
}

这就是Collections.emptyList()的实施方式。

答案 1 :(得分:0)

对于未来的读者,我为我的特殊用例找到了另一种解决方案。因为无论如何所有工作类都具有相同的父类(例如Worker),我可以让Worker实现Callback接口本身:

public abstract class Worker<T> implements Callback<T> {

    private Callback<T> callback;

    public Worker() {
        setCallback(this);
    }

    public void doWork(final T data) {
        callback.callback(data);

        doRealWork(data);
    }

    protected abstract void doRealWork(final T data);

    @Override
    public void callback(final T data) {
        // do nothing
    }

    public void setCallback(final Callback<T> callback) {
        if (callback == null) {
            this.callback = this;
            // Or throw some exception (depending on your situation)
        } else {
            this.callback = callback;
        }
    }

}

在我的特殊用例中,回调方法存在并且可以在工作人员自己中访问也没有问题。