在这种情况下,我如何处理 Function 和省略号/可变参数?

2024-05-22

我的项目之一是抛出 lambda 表达式 https://github.com/fge/throwing-lambdas;我的目标是简化潜在的使用@FunctionalInterfaces in Streams,其在流中使用的唯一“缺陷”是它们抛出检查异常(就我而言,我宁愿称其为缺陷,因为您不能从流中抛出检查异常,但这是另一个故事)。

So, for Function<T, R>我这样定义:

@FunctionalInterface
public interface ThrowingFunction<T, R>
    extends Function<T, R>
{
    R doApply(T t)
        throws Throwable;

    default R apply(T t)
    {
        try {
            return doApply(t);
        } catch (Error | RuntimeException e) {
            throw e;
        } catch (Throwable throwable) {
            throw new ThrownByLambdaException(throwable);
        }
    }
}

例如,这允许我定义:

final ThrowingFunction<Path, Path> = Path::toRealPath;

(why Path::toRealPath... 出色地,正是因为它有省略号 http://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html#toRealPath-java.nio.file.LinkOption...-).

我不想在这里停下来,我希望能够写出这样的东西:

Throwing.function(Path::toRealPath).fallbackTo(Path::toAbsolutePath)

上面的内容几乎有效...继续阅读。

我也这样定义:

public abstract class Chainer<N, T extends N, C extends Chainer<N, T, C>>
{
    protected final T throwing;

    protected Chainer(final T throwing)
    {
        this.throwing = throwing;
    }

    public abstract C orTryWith(T other);

    public abstract <E extends RuntimeException> T orThrow(
        final Class<E> exclass);

    public abstract N fallbackTo(N fallback);

    public final <E extends RuntimeException> T as(final Class<E> exclass)
    {
        return orThrow(exclass);
    }
}

这是它的实现Functions:

public final class ThrowingFunctionChain<T, R>
    extends Chainer<Function<T, R>, ThrowingFunction<T, R>, ThrowingFunctionChain<T, R>>
    implements ThrowingFunction<T, R>
{
    public ThrowingFunctionChain(final ThrowingFunction<T, R> function)
    {
        super(function);
    }

    @Override
    public R doApply(final T t)
        throws Throwable
    {
        return throwing.doApply(t);
    }

    @Override
    public ThrowingFunctionChain<T, R> orTryWith(
        final ThrowingFunction<T, R> other)
    {
        final ThrowingFunction<T, R> function = t -> {
            try {
                return throwing.doApply(t);
            } catch (Error | RuntimeException e) {
                throw e;
            } catch (Throwable ignored) {
                return other.doApply(t);
            }
        };

        return new ThrowingFunctionChain<>(function);
    }

    @Override
    public <E extends RuntimeException> ThrowingFunction<T, R> orThrow(
        final Class<E> exclass)
    {

        return t -> {
            try {
                return throwing.doApply(t);
            } catch (Error | RuntimeException e) {
                throw e;
            } catch (Throwable throwable) {
                throw  ThrowablesFactory.INSTANCE.get(exclass, throwable);
            }
        };
    }

    @Override
    public Function<T, R> fallbackTo(final Function<T, R> fallback)
    {
        return t -> {
            try {
                return doApply(t);
            } catch (Error | RuntimeException e) {
                throw e;
            } catch (Throwable ignored) {
                return fallback.apply(t);
            }
        };
    }
}

到目前为止一切顺利(尽管IDEA无法识别代码orTryWith()有效 https://youtrack.jetbrains.com/issue/IDEA-137179,但那是另一个故事了)。

我还定义了一个名为的实用程序类Throwing问题在于main()我作为测试编写的这个类:

public final class Throwing
{
    private Throwing()
    {
        throw new Error("nice try!");
    }

    public static <T, R> ThrowingFunctionChain<T, R> function(
        final ThrowingFunction<T, R> function)
    {
        return new ThrowingFunctionChain<>(function);
    }

    public static void main(final String... args)
    {
        // FAILS TO COMPILE
        final Function<Path, Path> f = function(Path::toRealPath)
            .fallbackTo(Path::toAbsolutePath);
    }
}

现在,上面代码的错误消息是:

Error:(29, 48) java: incompatible types: cannot infer type-variable(s) T,R
    (argument mismatch; invalid method reference
      method toRealPath in interface java.nio.file.Path cannot be applied to given types
        required: java.nio.file.LinkOption[]
        found: java.lang.Object
        reason: varargs mismatch; java.lang.Object cannot be converted to java.nio.file.LinkOption)
Error:(29, 49) java: invalid method reference
  non-static method toRealPath(java.nio.file.LinkOption...) cannot be referenced from a static context
Error:(30, 25) java: invalid method reference
  non-static method toAbsolutePath() cannot be referenced from a static context

我无法在这里诊断错误的确切原因,但对我来说,它只是看起来省略号妨碍了;事实上,如果我这样做:

    final ThrowingFunctionChain<Path, Path> f = function(Path::toRealPath);

    try (
        final Stream<Path> stream = Files.list(Paths.get(""));
    ) {
        stream.map(f.fallbackTo(Path::toAbsolutePath))
            .forEach(System.out::println);
    }

然后它编译:所以这意味着Stream.map()确实承认结果是Function...

那么为什么不呢Throwing.function(Path::toRealPath).fallbackTo(Path::toAbsolutePath)编译?


你的代码片段

Function<Path, Path> f = function(Path::toRealPath).fallbackTo(Path::toAbsolutePath);

遇到了规范中包含的 Java 8 类型推断的限制,因此这不是编译器错误。当您链接方法调用时,目标类型不起作用。由于链中的第一个方法是可变参数方法,因此需要其目标类型来查找预期的调用签名。这种情况类似于你写的时候p->p.toRealPath(),其中调用的参数数量是明确的,但类型p尚不清楚。两者都不能在调用链中工作(除了最后一次调用)

这可以通过明确第一次调用的类型来解决,

Function<Path, Path> f = Throwing.<Path,Path>function(Path::toRealPath)
  .fallbackTo(Path::toAbsolutePath);

or

ThrowingFunctionChain<Path, Path> f0 = function(Path::toRealPath);
Function<Path, Path> f = f0.fallbackTo(Path::toAbsolutePath);

or

Function<Path, Path> f = function((Path p)->p.toRealPath())
    .fallbackTo(Path::toAbsolutePath);

或者将方法调用链转换为非链接方法调用,如下所示此处描述 https://stackoverflow.com/a/26883991/2711488:

public static <T, R> ThrowingFunctionChain<T, R> function(
    final ThrowingFunction<T, R> function)
{
    return new ThrowingFunctionChain<>(function);
}
public static <T, R> Function<T, R> function(
    final ThrowingFunction<T, R> function, Function<T, R> fallBack)
{
    return new ThrowingFunctionChain<>(function).fallbackTo(fallBack);
}
public static void main(final String... args)
{
    Function<Path, Path> f = function(Path::toRealPath, Path::toAbsolutePath);
}

当一个调用以另一个调用的结果为目标时,规范故意拒绝对两个调用进行类型推断,但如果相同的表达式只是另一个调用的参数,则该规范会起作用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在这种情况下,我如何处理 Function 和省略号/可变参数? 的相关文章

随机推荐

  • 在 silverlight 中打开响应流

    我正在尝试使用 Silverlight 3 从服务器返回图像 服务器返回响应流 如下所示 context Response ContentType imageFactory ContentType imgStream WriteTo con
  • Swift 语言中的抽象函数

    我想用 swift 语言创建一个抽象函数 是否可以 class BaseClass func abstractFunction How do I force this function to be overridden class SubC
  • 防止在单元格中更改行时重新格式化字符

    我有一个带有格式化文本的单元格 其中包含我想要用行更改替换的某个子字符串 子字符串是带有方括号的 enterkey 这是这个问题的一个变体在 Excel 中将 HTML 标记 替换为 Alt Enter https stackoverflo
  • SQL Server 端口 445 和 1433

    SQL Server 端口 445 和 1433 之间有什么区别以及每个端口的用途是什么 445不是SQL端口 是SMB端口 仅当您使用命名管道协议时 它才会参与 SQL Server 因为命名管道通过 SMB 进行传输 而这反过来又使用
  • 如何按关系的数量或成员对 Doctrine DQL 查询进行排序?

    我正在尝试创建一个查询 用于从 Doctrine 数据库中检索对象 并按特定一对多关系的成员数量排序 更具体地说 我有两个实体 Person 和 Federation 一个人可以是一个联盟的成员 人具有 联盟 关系 并且一个联盟可以有n人
  • “as”和“is”的真正用法

    我 从未 使用过as or is在 C 或任何支持该关键字的语言中 你用它来做什么 我的意思不是我如何使用它 我的意思是你实际上如何需要它 我也逃脱了做no在一个相当大的 C 项目中进行类型转换 我很自豪 所以考虑到我几乎从不进行类型转换
  • 如何从链表中删除节点?

    将整数添加到列表中工作正常 但删除和打印时出现问题 我对调试器还不友好 但我发现节点指针 first 有错误 它的值为 17891602 我不知道发生了什么事 include
  • 无法从视图转换为按钮

    我在这里遇到非常令人沮丧的问题 我有这个代码 Button b findViewById android R id button1 我收到了这个错误 类型不匹配 无法将表单视图转换为按钮 但是按钮1is一个按钮 在我的 XML 布局文档中
  • Android 上的嵌套滚动

    我们的活动中有一个主要的水平滚动视图 以及嵌套在其中的几个垂直滚动视图 这个想法是水平滚动 直到找到所需的垂直列表 然后上下滚动 理想情况下 一旦开始垂直滚动 我希望垂直滚动具有 锁定 现在会发生什么 如果您非常小心 您可以垂直滚动 但如果
  • 使用 pycharm 进行交互式 shell 调试

    我是 PyCharm 新手 我已经使用 IDLE 很长时间了 在IDLE中执行脚本后使用Python对象非常方便 有没有办法在使用 PyCharm 与交互式 python shell 执行后使用脚本对象 例如 我们有一个 测试 项目 其中包
  • 查找具有不同强度/亮度的相似图像

    假设我有如下图像 我可以选择什么来比较两个图像之间的相似度 显然它们是相同的图像 只是亮度不同 我找不到任何可行的方法 目前我最好的选择是训练 cnn 或自动编码器并比较输出的特征向量 但这似乎有点矫枉过正 任何提示将不胜感激 相当强大的工
  • Aurelia HttpClient 取消请求

    我正在尝试构建一个自动完成组件 并希望使其在键入时取消对服务器的未解析请求 我在 HttpClient 的文档中找不到与此相关的文档 它提到它是可以取消的 与获取不同 但没有提到如何取消 https aurelia io docs plug
  • 使用列中的日期范围扩展 pandas 数据框

    我有一个 pandas 数据框 其日期和字符串与此类似 Start End Note Item 2016 10 22 2016 11 05 Z A 2017 02 11 2017 02 25 W B 我需要将其扩展 转换为以下内容 在之间填
  • 有没有办法从 EntityManager 获取所有托管实体

    我正在设置一个基本的测试数据实用程序 并希望跟踪 EntityManager 处理的所有数据 有没有一种方法可以一次性获取 EntityManager 管理的所有内容 而不是仅仅为每个实体提供一堆列表 所以代替这个 EntityManage
  • ASP.Net 5 RC2 配置节绑定

    我刚刚将示例应用程序从 RC1 升级到 RC2 但我找不到如何将 appSettings json 文件的特定部分绑定到我自己的 POCO 样本位于https github com aspnet live asp net blob rc2
  • didReceiveRemoteNotification 将用户带到正确的视图

    我有一个聊天应用程序 当发送新消息时 我的服务器会发送推送通知 我遇到的问题是如何将用户带到正确的视图 我正在发送一个channelID在推送通知中 但我如何检索它并将用户带入实际对话 我使用此代码来检测何时单击推送通知 void appl
  • Android EditText默认数字键盘和允许文本[重复]

    这个问题在这里已经有答案了 可能的重复 EditText 默认带有数字键盘 但允许字母字符 https stackoverflow com questions 3544214 edittext with number keypad by d
  • 通过 HTML 或 JavaScript 禁用 Web 表单上的自动填充?

    有没有办法通过 HTML 或 JavaScript 禁用 Chrome 和其他浏览器中表单字段的自动填充 我不希望浏览器自动填写该浏览器以前用户的表单上的答案 我知道我可以清除缓存 但我不能依赖重复清除缓存 您可以在 HTML 的输入级别添
  • Android - 如何设置所有屏幕的背景颜色?

    维护字体和颜色样式的最佳实践是什么 我制作了一个 color xml 文件 用于更改按钮等单独元素的颜色 但我不确定 Android 希望开发人员如何组织他们的样式 例如 我希望所有屏幕都具有相同的背景颜色 我怎么做 我需要为每个 Acti
  • 在这种情况下,我如何处理 Function 和省略号/可变参数?

    我的项目之一是抛出 lambda 表达式 https github com fge throwing lambdas 我的目标是简化潜在的使用 FunctionalInterfaces in Streams 其在流中使用的唯一 缺陷 是它们