所以我花了 2 个小时试图找到一个对我来说真正有意义的 Java 8 构造函数引用的实际示例。并不是我不理解构造函数引用的语法或语义。但我无法想出一个可以/将使用它们的用例。我发现的示例基本上只是引入了一个相当无意义的函数接口和一个匹配的类/构造函数,只是为了能够使用构造函数引用。但归根结底只是以一种new...()非常复杂的方式做简单的事情。除了通过构造函数引用之外,函数式接口从未以任何其他方式使用过,那么有什么意义呢?
有人可以给我一个实际的例子,您可以使用构造函数引用来实现函数式接口,但是函数式接口不仅仅用于传递此构造函数引用,而且实际上有一个存在的理由,因为它与其他实现一起使用还有?
我期待将外部参数传递给方法引用:
String prefix = "The number is :";
numbers.forEach(Main::printWithPrefix);
private static void printWithPrefix(Integer number) {
System.out.println(number);
}
Run Code Online (Sandbox Code Playgroud)
我不知道怎么做.我能用lambda做到这一点:
String prefix = "The number is :";
numbers.forEach(number -> {
System.out.println(prefix + number);
});
Run Code Online (Sandbox Code Playgroud)
是否可以将外部参数传递给方法引用?
我最近使用了很多方法引用和 lambda,并且想知道在运行时是否可以打印以屏幕 lambda 的源(即它的名称),只是出于调试原因。我认为可以使用反射,通过在 getName() 中调用 getClass() 来实现,但我找不到用于查找原始源引用名称的方法。
我有一个功能界面,例如:
@FunctionalInterface
public interface FooInterface {
// function etc etc irrelevant
public void method();
public default String getName() {
// returns the name of the method reference which this is used to define
}
}
Run Code Online (Sandbox Code Playgroud)
然后假设我希望测试运行该界面,并将功能界面的源代码打印到屏幕上。
public static void doStuff(FooInterface f) {
// prints the lambda name that is used to create f
System.out.println(f.getName());
// runs the method itself
f.method();
}
Run Code Online (Sandbox Code Playgroud)
所以如果我这样做:
doStuff(Foo::aMethodReference);
Run Code Online (Sandbox Code Playgroud)
它应该在屏幕上打印类似:“aMethodReference”的内容,这样我就可以知道在运行时正在运行哪些方法,以什么顺序运行等。
考虑到 lambda 不完全是对象,我很怀疑这是可能的,但是嘿,我想可能有一个解决方法。此外,eclipse调试工具只是说它是一个lambda,没有任何其他信息,lambda是否保留任何这些信息?或者在运行时全部丢失?
干杯。(如果有什么区别的话,我正在使用 JDK 11)
我正在尝试通过 LambdaMetafactory 动态创建 BiConsumer 类型的方法引用。我试图应用在https://www.cuba-platform.com/blog/think-twice-before-using-reflection/上找到的两种方法 - createVoidHandlerLambda 和这里Create BiConsumer as Field setter 而不反映Holger 的答案。
但是在这两种情况下我都遇到以下错误:
Exception in thread "main" java.lang.AbstractMethodError: Receiver class org.home.ref.App$$Lambda$15/0x0000000800066040 does not define or inherit an implementation of the resolved method abstract accept(Ljava/lang/Object;Ljava/lang/Object;)V of interface java.util.function.BiConsumer.
at org.home.ref.App.main(App.java:20)
Run Code Online (Sandbox Code Playgroud)
我的代码是这样的:
public class App {
public static void main(String[] args) throws Throwable {
MyClass myClass = new MyClass();
BiConsumer<MyClass, Boolean> setValid = MyClass::setValid;
setValid.accept(myClass, true);
BiConsumer<MyClass, Boolean> mappingMethodReferences = createHandlerLambda(MyClass.class);
mappingMethodReferences.accept(myClass, true);
}
@SuppressWarnings("unchecked")
public …Run Code Online (Sandbox Code Playgroud) 为什么这段代码不能编译?无法完全掌握 java 方法参考的细微差别:(
public class TestClass {
static void println() {}
public static void main(String[] args) {
Runnable r1 = () -> System.out::println; // compilation error
Runnable r2 = () -> TestClass::println; // compilation error
Runnable r2 = () -> System.out.println("Hello World"); // This is fine !!
}
}
Run Code Online (Sandbox Code Playgroud) 代码:
@FunctionalInterface
interface VoidSupplier {
void apply() throws Exception;
}
void execute(VoidSupplier voidSupplier) {
if (voidSupplier != null) {
try {
voidSupplier.apply();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
调用execute使用lambda:
@Test
public void testLambda() {
InputStream i = null;
execute(() -> i.close()); // use lambda
System.out.println("output some message"); // will be executed
}
Run Code Online (Sandbox Code Playgroud)
调用execute使用方法参考:
@Test
void testMethodReference() {
InputStream i = null;
execute(i::close); // use method reference
System.out.println("output some message"); …Run Code Online (Sandbox Code Playgroud) 我对以下行感到困惑:
Seq<String> s1 = seq.zip(split, Function::apply);
Run Code Online (Sandbox Code Playgroud)
在这个片段中:
static String underscoreToCamel(String str) {
UnaryOperator<String> capitalize = s -> s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
Seq<UnaryOperator<String>> seq = c -> {
c.accept(String::toLowerCase);
while (true) {
c.accept(capitalize);
}
};
List<String> split = Arrays.asList(str.split("_"));
Seq<String> s1 = seq.zip(split, Function::apply);
String a = s1.join("");
return a;
}
public interface Seq<T> {
void consume(Consumer<T> consumer);
static <T> Seq<T> unit(T t) {
return consumer -> consumer.accept(t);
}
default <E> Seq<E> map(Function<T, E> function) {
return consumer -> consume(t -> …Run Code Online (Sandbox Code Playgroud) 我正在尝试用方法引用来压缩我的代码.这是我要改进的一条线:
assertThat("only true & false strings allowed",
records.stream().map(Record::getType)
.allMatch(s -> "true".equals(s) || "false".equals(s)));
Run Code Online (Sandbox Code Playgroud)
使用方法参考,它可以更好:
assertThat("only true & false strings allowed",
records.stream().map(Record::getType).allMatch("true"::equals));
Run Code Online (Sandbox Code Playgroud)
但是,无论如何我可以在谓词中添加"false"吗?
我没有GUI(我的课程是Minecraft Mod的一部分)。我希望能够模仿C#事件框架:一个类声明事件并让其他人订阅它们。
我的第一种方法是创建一个名为的类EventArgs,然后执行以下操作:
public class EventArgs
{
public boolean handled;
}
@FunctionalInterface
public interface IEventHandler<TEvtArgs extends EventArgs>
{
public void handle(Object source, TEvtArgs args);
}
public class Event<TEvtArgs extends EventArgs>
{
private final Object owner;
private final LinkedList<IEventHandler<TEvtArgs>> handlers = new LinkedList<>();
public Event(Object owner)
{
this.owner = owner;
}
public void subscribe(IEventHandler<TEvtArgs> handler)
{
handlers.add(handler);
}
public void unsubscribe(IEventHandler<TEvtArgs> handler)
{
while(handlers.remove(handler));
}
public void raise(TEvtArgs args)
{
for(IEventHandler<TEvtArgs> handler : handlers)
{
handler.handle(owner, args);
if(args.handled)
break; …Run Code Online (Sandbox Code Playgroud) 我不明白之间的区别
this::myMethod
Run Code Online (Sandbox Code Playgroud)
和
ClassName::myMethod
Run Code Online (Sandbox Code Playgroud)
当这是ClassName类的实例时.
我认为在这两种情况下我都会调用该方法myMethod并将myObject其作为myMethod方法的参数运行,但我认为存在差异.它是什么?
java ×10
method-reference ×10
java-8 ×6
lambda ×5
reflection ×2
closures ×1
constructor ×1
events ×1
java-stream ×1
predicate ×1