标签: method-reference

Java 8:方法引用Bound Receiver和UnBound Receiver之间的区别

我试图在我的代码中使用Java 8方法引用.有四种类型的方法参考可用.

  1. 静态方法参考.
  2. 实例方法(绑定接收器).
  3. 实例方法(UnBound接收器).
  4. 构造函数引用.

随着Static method referenceConstructor reference我有没有问题,但Instance Method (Bound receiver)Instance Method (UnBound receiver)真搞糊涂了.在Bound接收器中,我们使用Object引用变量来调用方法,如:

objectRef::Instance Method
Run Code Online (Sandbox Code Playgroud)

UnBound接收器中,我们使用类名来调用方法,如:

ClassName::Instance Method.
Run Code Online (Sandbox Code Playgroud)

我有以下问题:

  1. 实例方法的不同类型的方法引用需要什么?
  2. BoundUnbound接收方法引用有什么区别?
  3. 我们应该Bound在哪里使用Unbound接收器?我们应该在哪里使

我还从Java 8语言特性书中找到了解释BoundUnbound接收器,但仍然与实际概念混淆.

java lambda java-8 method-reference

10
推荐指数
2
解决办法
4034
查看次数

通过Java 8中的方法引用调用toString

我错过了什么?为什么我必须在Object::toString下面使用而不是Integer::toString?它与带有泛型的类型擦除有什么关系吗?

Arrays.asList(1,2,3).stream().map(Integer::toString).forEach(System.out::println); //Won't compile

Arrays.asList(1,2,3).stream().map(Object::toString).forEach(System.out::println); //Compiles and runs fine
Run Code Online (Sandbox Code Playgroud)

java java-8 method-reference

9
推荐指数
1
解决办法
4442
查看次数

Java 8如何知道在排序时使用哪个String :: compareTo方法引用?

Java如何知道String::compareTo调用时使用哪个方法引用Collections.sort(someListOfStrings, String::compareTo);compareTo不是静态的,它需要知道value比较的"左手边".

java-8 method-reference

9
推荐指数
1
解决办法
2000
查看次数

混合方法引用和泛型时的LambdaConversionException

下面的代码编译正常但在运行时抛出异常.这是预期的行为吗?为什么?

码:

public static void main(String[] args) {
  A<Integer> a = new A<> ();
  System.out.println(a.min()); //prints null as expected
  System.out.println(a.max()); //throws exception
}

static class A<T extends Number & Comparable<? super T>> {
  Stream<T> s = Stream.empty();
  public T min() { return s.min((t1, t2) -> t1.compareTo(t2)).orElse(null); }
  public T max() { return s.max(T::compareTo).orElse(null); }
}
Run Code Online (Sandbox Code Playgroud)

输出:

null
Exception in thread "main" java.lang.BootstrapMethodError: call site initialization exception
    at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
    at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
    at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
    at abc$A.max(abc.java:19)
    at abc.main(abc.java:8)
Caused by: java.lang.invoke.LambdaConversionException: Invalid …
Run Code Online (Sandbox Code Playgroud)

java generics java-8 method-reference

9
推荐指数
2
解决办法
655
查看次数

Java 8方法引用和重写方法

我已经在Java 8中使用lambdas和方法引用了一段时间,有一件事我不明白.这是示例代码:

    Set<Integer> first = Collections.singleton(1);
    Set<Integer> second = Collections.singleton(2);
    Set<Integer> third = Collections.singleton(3);

    Stream.of(first, second, third)
            .flatMap(Collection::stream)
            .map(String::valueOf)
            .forEach(System.out::println);

    Stream.of(first, second, third)
            .flatMap(Set::stream)
            .map(String::valueOf)
            .forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

两个流管道做同样的事情,他们打印出三个数字,每行一个.不同之处在于它们的第二行,似乎只要它具有方法就可以简单地替换继承层次结构中的类名(Collection接口具有默认方法"stream",而未在Set接口中重新定义).我尝试了如果使用这些类一次又一次地重新定义方法会发生什么:

private static class CustomHashSet<E> extends HashSet<E> {
    @Override
    public Stream<E> stream() {
        System.out.println("Changed method!");
        return StreamSupport.stream(spliterator(), false);
    }
}

private static class CustomCustomHashSet<E> extends CustomHashSet<E> {
    @Override
    public Stream<E> stream() {
        System.out.println("Changed method again!");
        return StreamSupport.stream(spliterator(), false);
    }
}
Run Code Online (Sandbox Code Playgroud)

在更改第一,第二和第三个赋值以使用这些类之后,我可以替换方法引用(CustomCustomHashSet :: stream),并且毫不奇怪它们在所有情况下都打印出调试消息,即使我使用Collection :: stream也是如此.看来你不能用方法引用调用super,overriden方法.

运行时间有差异吗?什么是更好的做法,请参考顶级接口/类或使用具体的已知类型(Set)?谢谢!

编辑:为了清楚,我知道继承和LSP,我的困惑与Java 8中方法引用的设计有关.我首先想到的是,在方法引用中更改类会改变行为,它会调用它来自所选类的超级方法,但正如测试所示,它没有任何区别.更改创建的实例类型确实会改变行为.

java java-8 method-reference

9
推荐指数
1
解决办法
1641
查看次数

LambdaMetaFactory中的类型

我打电话时遇到异常metafactory.它说:

java.lang.invoke.LambdaConversionException:
    Incorrect number of parameters for instance method
        invokeVirtual my.ExecuteTest$AProcess.step_1:()Boolean;
    0 captured parameters, 
    0 functional interface method parameters, 
    0 implementation parameters
Run Code Online (Sandbox Code Playgroud)

我不明白所有的文件LambdaMetafactory.metafactory.我在确定正确的参数时遇到了问题:

  • MethodHandles.Lookup调用者 - 这很容易
  • 字符串invokedName - 我在这里相当肯定
  • MethodType invokedType - 这是什么?
  • MethodType samMethodType - 错误...... 不确定这里
  • MethodHandle implMethod - 没关系
  • MethodType instantiatedMethodType - 这又是什么?第二次?

所以它归结为以下两者之间的区别:

  • MethodType invokedType
  • MethodType samMethodType
  • MethodType instantiatedMethodType

我的代码是这样的:

package my;

import java.lang.invoke.*;
import java.lang.reflect.Method;

public class Execute {

  public interface ProcessBase {};

  @FunctionalInterface
  public interface Step {
    Boolean apply(); …
Run Code Online (Sandbox Code Playgroud)

java reflection lambda java-8 method-reference

9
推荐指数
1
解决办法
685
查看次数

如何使用Groovy生成Java方法引用以进行测试

我正在使用GroovyJUnit来测试我的Java代码.

我需要测试的方法foo()这需要在java.util.function.Function

public void foo(Function<Foo,Bar> func){
    return null; 
}
Run Code Online (Sandbox Code Playgroud)

在我的正常代码中,我foo通过传入方法的方法引用来调用,bar即.

foo(mybar::bar)
Run Code Online (Sandbox Code Playgroud)

我怎样才能Groovy优雅地测试这个功能?

使用:

mybar.&bar
Run Code Online (Sandbox Code Playgroud)

产生groovy.lang.Closure<...>与之不相容的java.util.function.Function.

我怎么能做到这一点?

java groovy java-8 method-reference

9
推荐指数
1
解决办法
3108
查看次数

Comparator.comparing(...)在使用String :: compareTo时抛出非静态引用异常

以下是我的代码段的两行:

List<String> listDevs = Arrays.asList("alvin", "Alchemist", "brutus", "larsen", "jason", "Kevin");

listDevs.sort(Comparator.comparing(String::length)); //This works fine
listDevs.sort(String::compareToIgnoreCase); //This works fine
Run Code Online (Sandbox Code Playgroud)

但是(当expermient)当我尝试写

listDevs.sort(Comparator.comparing(String::compareToIgnoreCase));
Run Code Online (Sandbox Code Playgroud)

编译器抛出错误

无法从类型String中对非静态方法compareToIgnoreCase(String)进行静态引用

类似的情况发生在下面的代码中

listDevs.sort(Comparator.comparing(String::compareTo));
Run Code Online (Sandbox Code Playgroud)

我理解错误,如果我删除Comparator.comparing(如上所示)它工作正常.

但我的观点是,这条线如何运作?

listDevs.sort(Comparator.comparing(字符串::长度));

我相信我错过了一些东西.我已经读过这个帖子了.这是同样的情况吗?

java static-methods comparator java-8 method-reference

9
推荐指数
3
解决办法
3853
查看次数

如何使用:: operator作为此引用

转换对象的列表Foo具有id,向Map<Integer,Foo>与该id关键,是容易使用流API:

public class Foo{
    private Integer id;
    private ....
    getters and setters...
}

Map<Integer,Foo> myMap = 
fooList.stream().collect(Collectors.toMap(Foo::getId, (foo) -> foo));
Run Code Online (Sandbox Code Playgroud)

有没有办法替换lambda表达式:(foo) -> foo使用::运算符的东西?就像是Foo::this

java lambda java-8 method-reference

9
推荐指数
2
解决办法
576
查看次数

所选方法引用的内联调用方法

我有以下无法编译的程序:

只是块1编译正常并按预期工作 - 我可以有条件地选择一个对象并在其上内联调用一个方法.

只是块2也编译好并按预期工作 - 我可以有条件地为Supplier<String>变量分配方法引用并调用.get()该变量.

但是块3无法编译:

Lambda.java:31: error: method reference not expected here
    String res = ((Supplier<String>) (args.length > 0 ? Lambda::foo : Lambda::bar)).get();
                                                        ^
Lambda.java:31: error: method reference not expected here
    String res = ((Supplier<String>) (args.length > 0 ? Lambda::foo : Lambda::bar)).get();
Run Code Online (Sandbox Code Playgroud)

我认为该想法在块1组合和2 I将能够为一体的类型执行块3 ((Supplier<String>) (args.length > 0 ? Lambda::foo : Lambda::bar))Supplier<String>.

import java.util.function.Supplier;

class Lambda {

  private final String s;

  private Lambda(String s) {
    this.s = s;
  }

  private …
Run Code Online (Sandbox Code Playgroud)

java language-lawyer method-reference

9
推荐指数
1
解决办法
129
查看次数