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

时间:2014-08-12 17:27:04

标签: 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();
                }
            });

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

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

但是,我收到了编译错误:

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

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

4 个答案:

答案 0 :(得分:15)

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

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

答案 1 :(得分:15)

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

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

上述方法的Lambda将是:

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="panel panel-default">
    <div class="panel-heading">
        <div class="panel-title">
            <a style="display: block" data-toggle="collapse" data-parent="#accordion" href="#panelBody<%=trimmedKennzeichen%>">
                <div class="col-xs-4">
                    <h4>t1</h4>
                </div>
                <div class="col-xs-4 text-center">
                    <h4>t2</h4>
                </div>
                <div class="col-xs-4">
                    <h4>t3</h4>
                </div>
            </a>
        </div>
    </div>
</div>

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

答案 2 :(得分:4)

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

然而,令我印象深刻的是您使用原始类型。如果您的原始代码如下所示:

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

(请注意roles变量的更改类型)当您使用没有类型参数的AttributesMapper实现时,只需原始类型警告即可获得更改检查返回的Object是否有效作为List<String>的元素。

将该代码转换为lambda时,您无法再使用它了:

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

现在,编译器将为您推断类型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());

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

答案 3 :(得分:0)

下面的代码显示使用匿名内部类获取学生比较器。

private static final Comparator<StudentDto> studentScoreComparator = new Comparator<StudentDto>() {
            @Override
            public int compare(StudentDto s1, StudentDto s2) {
              if (s2.getScore() < s1.getScore()) {
                return 1;
              }
              return s2.getScore() == s1.getScore() ? 0 : 1;
            }
          };

将Java8 amd Sonar建议用于仅包含一种方法的匿名内部类应变为lambdas 可以如下转换。

private static final Comparator<StudentDto> studentScoreComparator = (s1, s2) -> {
        if (s2.getScore() < s1.getScore()) {
          return 1;
        }
        return s2.getScore() == s1.getScore() ? 0 : 1;
      };

只有一个方法实现的匿名内部类可以是 考虑作为功能接口,可以轻松地视为Lambda 表达。