【问题标题】:Using lambda to execute a void: Is this correct?使用 lambda 执行 void:这是正确的吗?
【发布时间】:2014-02-02 13:10:20
【问题描述】:

我做的对吗?我基本上是想执行某个void方法。

public abstract class Uniforms {
    public static void setUniformMatrix4(final UniformLocation uniformLocation, final boolean transpose, final Matrix4f matrix4f) {
        setUniformImpl(uniformLocation, u -> GL20.glUniformMatrix4(uniformLocation.getLocation(), transpose, matrix4f.asFloatBuffer()));
    }

    public static void setUniformMatrix4(final UniformLocation uniformLocation, final boolean transpose, final FloatBuffer matrix4fFloatBuffer) {
        setUniformImpl(uniformLocation, u -> GL20.glUniformMatrix4(uniformLocation.getLocation(), transpose, matrix4fFloatBuffer));
    }

    public static void setUniform(final UniformLocation uniformLocation, final float value) {
        setUniformImpl(uniformLocation, u -> GL20.glUniform1f(uniformLocation.getLocation(), value));
    }

    public static void setUniform(final UniformLocation uniformLocation, final int value) {
        setUniformImpl(uniformLocation, u -> GL20.glUniform1i(uniformLocation.getLocation(), value));
    }

    private static void setUniformImpl(final UniformLocation uniformLocation, final Consumer<UniformLocation> consumer) {
        Program oldProgram = Program.getUsing();
        for (Program program : Program.getPrograms()) {
            if (program.usesUniform(uniformLocation)) {
                program.use();
                consumer.accept(uniformLocation);
            }
        }
        if (oldProgram != null) {
            oldProgram.use();
        }        
    }
}

【问题讨论】:

  • 是的,它看起来不错,您为什么认为有问题?
  • @assylias 因为我不确定是否应该这样使用 lambda,所以 Consumer&lt;T&gt; 通常会消耗 T。但是在我的情况下,我正在传递的u 没有被使用。我可能认为我需要什么不消耗也不产生什么的东西?
  • @Downvoter:请说明原因。
  • 也许反对票是因为不清楚您的问题是什么。但他们应该留下评论。不过,您之前的评论确实澄清了这个问题。

标签: java lambda java-8


【解决方案1】:

如果您的程序编译并给出了您期望的输出,那么从这个意义上说它是正确的。不过可以稍微澄清一下。

四个公共重载都采用UniformLocation 参数,然后将其传递给setUniformImpl 方法。然后,此方法调用消费者并将 uniformLocation ... 传递给它,然后将其忽略。 lambdas 中对GL2.glUniform* 方法的调用全部capture uniformLocation,而不是使用u 参数。您可以将Consumer 替换为Runnable。

或者,您可以将Consumer 的类型更改为Uniform.getLocation() 的返回值,并将这些调用中的每一个提取到setUniformImpl 并将结果作为arg 传递给consumer.accept。这会简化一些事情。你最终会得到类似的东西,

public static void setUniform(final UniformLocation uniformLocation, final int value) {
    setUniformImpl(uniformLocation, u -> GL20.glUniform1i(u, value));
}

private static void setUniformImpl(final UniformLocation uniformLocation, final Consumer<Location> consumer) {
    ...
    consumer.accept(uniformLocation.getLocation());
    ...
}

【讨论】:

  • 我也在想Runnable这个接口,在这个意义上使用是否正确?据我所知,它是唯一可以执行“方法”的界面。
  • 当然,Runnable 会起作用。要点是函数的“形状”,就参数和返回值的数量而言。选择函数式接口时,首先看参数和返回值的个数,选择匹配的函数式接口。 (可能专门用于原语或布尔值。)Runnable 接受零参数并返回 void,所以如果这与您想要的匹配,Runnable 非常好。
【解决方案2】:

如果它编译,那么没有问题。

假设一个方法期望:

void m(Consumer<SomeEvent> e);

那么在 Java 7 中你可以这样写:

m(new Consumer<SomeEvent> () { void accept(SomeEvent e) { /* do nothing */ } });

您提供的消费者忽略参数e。

同样,使用 lambdas,您可以忽略参数并编写:

m(e -> { /* do nothing */ });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 2019-10-23
    • 2018-08-13
    • 2015-12-19
    • 1970-01-01
    相关资源
    最近更新 更多