Java 8,Lambda:用lambda替换Anonymous内部类

use*_*519 31 java lambda java-8

我有一个包含以下内容的类:

List roles = ldapTemplate.search(baseDn, replaceFilter, sc,
            new AttributesMapper() {
                public Object mapFromAttributes(Attributes attrs)
                        throws NamingException {
                    return attrs.get("cn").get();
                }
            });
Run Code Online (Sandbox Code Playgroud)

IntelliJ告诉我用lambda替换匿名内部类.所以我尝试过:

List roles = ldapTemplate.search(
    baseDn, replaceFilter, sc,
    (Attributes a)  -> { return a.get("cn").get(); };
);
Run Code Online (Sandbox Code Playgroud)

但是,我收到编译错误:

Error:(46, 50) java: incompatible types: inference variable T has incompatible bounds
    equality constraints: java.lang.String
    lower bounds: java.lang.Object
Run Code Online (Sandbox Code Playgroud)

我找不到解决这个问题的方法.你有什么想法?

Tri*_*vda 17

一个简单的azure存储实体解析器接口及其实现方法:

EntityResolver<String> orderNumberResolver = new EntityResolver<String>() {
    @Override
    public String resolve(String partitionKey, String rowKey, Date timeStamp,
        HashMap<String, EntityProperty> properties, String etag) {
      return properties.get("SomeColumnName").getValueAsString();
    }
  };
Run Code Online (Sandbox Code Playgroud)

上述方法的Lambda将是:

 EntityResolver<String> orderNumberResolver = (
          partitionKey, rowKey, timeStamp, properties, etag
      ) -> properties.get("SomeColumnName").getValueAsString();
Run Code Online (Sandbox Code Playgroud)

从上面的例子中可以清楚地看出,lambda足够聪明,可以根据它们的匿名内部类来处理方法参数的类型,因此它使得重写方法的实现变得容易.希望这会有所帮助.


sna*_*kar 15

试试这个(删除额外的半结肠)

List roles = ldapTemplate.search(
    baseDn, replaceFilter, sc,
    (Attributes a)  -> { return a.get("cn").get(); }            
);
Run Code Online (Sandbox Code Playgroud)


Hol*_*ger 5

我有一种强烈的感觉,你没有在你的问题中发布确切的代码。像Bart一样,我无法用您发布的代码重现错误。

然而,让我印象深刻的是你对raw types的使用。如果您的原始代码如下所示:

List<String> roles = ldapTemplate.search(baseDn, replaceFilter, sc,
    new AttributesMapper() {
        public Object mapFromAttributes(Attributes attrs)
                throws NamingException {
            return attrs.get("cn").get();
        }
    });
Run Code Online (Sandbox Code Playgroud)

(注意roles变量的更改类型)当你在没有类型参数的情况下实现时,你只会得到一个原始类型警告,AttributesMapper并且不会检查返回的值是否Object作为 a 的元素有效List<String>

将该代码转换为 lambda 时,您再也无法摆脱它了:

List<String> roles = ldapTemplate.search(baseDn, replaceFilter, sc,
  (Attributes a)  -> { return a.get("cn").get(); }            
);
Run Code Online (Sandbox Code Playgroud)

现在,编译器将为您推断类型AttributesMapper<String>并产生错误,因为您的 lambda 表达式返回Object而不是,String因此不满足AttributesMapper<String>接口。

您可以通过插入类型转换来实现AttributesMapper<String>接口或通过在问题中已经做过的声明roles原始类型List来解决这个问题。但是,使用类型转换将是更简洁的方法(并且应该是唯一一种不会产生编译器警告的方法):

List<String> roles = ldapTemplate.search(baseDn, replaceFilter, sc,
    a -> (String)a.get("cn").get());
Run Code Online (Sandbox Code Playgroud)

(我简化了表达式以补偿包含的类型转换,看起来好多了,不是吗?)