RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1118565
Accepted
Andrew Kachalin
Andrew Kachalin
Asked:2020-05-01 15:25:15 +0000 UTC2020-05-01 15:25:15 +0000 UTC 2020-05-01 15:25:15 +0000 UTC

在默认接口方法中,返回值可能与方法签名不匹配?

  • 772

主题 - lambda 表达式,在模式的上下文中,责任链。我在网上遇到了这段代码:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@FunctionalInterface
interface RequestHandler {
    public abstract Request handle(Request r);

    default RequestHandler setSuccessor(RequestHandler other) {
        return (req) -> { //req -  it's request            
            System.out.println("req instance of: " +req.getClass().getName());
            return other.handle(this.handle(req));
        };        
    }
}

public class Request {
    String data;

    public String getData() {
        return data;
    }

    public Request(String data) {
        this.data = data;
    }
}

更详细地说——有一个类Request——它只包含一行,带有一个构造函数和一个 getter。有一个接口RequestHandler——它是一个请求处理程序。它有一个抽象方法handle——用于 lambda 表达式。还有一种方法setSuccessor——进行更深层次的操作。这是setSuccessor我想知道的方法。为什么它会编译?通过签名,它应该返回 RequestHandler,但在第一个返回 (req) 中 - 我发现 req 只是请求。(这行代码 System.out.println("req instance of: " +req.getClass().getName());说的是 Request 的 req 实例) 第二个return other.handle(this.handle(req));,不管怎么说,返回值也是 Request,而不是 RequestHandler!例如,表达式 RequestHandler r = other.handle(this.handle(req));- 表示类型不兼容。

摘要问题:该方法在哪里和哪一行setSuccessor设法返回了一个接口对象RequestHandler?

java
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Дмитрий Никифоров
    2020-05-01T15:37:34Z2020-05-01T15:37:34Z

    了解什么是功能接口。要成为RequestHandler,您需要提供一个带有类型参数Request和类型返回值的方法Request。这来自签名handle。一个 lambda 表达式(req) -> {...},粗略地说,用这种方法定义了一个匿名对象。正如您正确指出的那样,参数req是 type Request,花括号内的返回值也是 type Request。事实证明,这个对象满足要求RequestHandler。

    • 1
  2. Best Answer
    Andrew Kachalin
    2020-05-03T10:52:41Z2020-05-03T10:52:41Z

    是的,确实java可以返回一个“接口对象”,即使这样的“对象”没有在返回方法的任何地方显式创建。“接口对象”——我用引号括起来,因为我们仍然指的是由接口引用控制的特定(通常是匿名)类的对象。

    在 java 8 之前,方法可以返回接口的“对象”,如下所示:

    public interface Marker { //Интерфейс
       public int doSomething(int x);
    }
    
    
    public Marker m(){ //Метод возвращающий "объект" интерфейса
        return    new Marker(){ //создание объекта и реализация его на базе анонимного класса
            public int doSomething(int x){ //создание конкретной реализации абстрактного метода
                return 25;
            };
        };
    }
    

    在 java 8 发布之后,为了创建一个“接口对象”,我们仍然需要声明某种方法实现。但如果接口中只有一个抽象,则可以使用 lambda 表达式来完成:

     public Marker m(){ //Тот же метод, c возможностями Java 8
            return x-> 25; //Этой строчкой мы задали конкретную реализацию метода doSomething
        }
    

    发生了什么魔法x-> 25?就 lambda 表达式而言,我们给出了 f(x) = 25;f(x) 是抽象方法的具体实现doSomething(int x);编程语言将其理解为“从方法m()返回一个具体的实现Marker,这样它的唯一抽象方法 doSomething(int x)将返回一个常量{return 25;}; 。也就是说,事实上,要创建一个“功能接口对象”,只需实现它的抽象 lambda 方法就足够了用表达式:

    Marker m = re->re*2; //Это полностью валидный код. Сказал что реализация метода doSomething(int x){return x*2}
    

    回到方法:

     default RequestHandler setSuccessor(RequestHandler other) {
            return (req) -> { //req -  это Request компилятор вывел из контекста           
                System.out.println("req instance of: " +req.getClass().getName());
                return other.handle(this.handle(req));
            };        
        }
    

    这里有人说“抽象句柄方法的实现(取决于请求参数)是这样的”:

    handle(Request r){
     System.out.println("r instance of: " +r.getClass().getName());
                    return other.handle(this.handle(r));
    } 
    

    此外,该方法安全地返回了一个带有该方法特定实现的“接口对象”RequestHandler。

    • 0

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5