热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ApacheFlink中的Java泛型与Lambda表达式

  在使用Java编写apache-flink程序的时候相信很多新手都遇到下面这样的异常;org.apache.flink.api.common.functions.Invalid

  在使用Java编写apache-flink程序的时候相信很多新手都遇到下面这样的异常;

org.apache.flink.api.common.functions.InvalidTypesException: The return type of function 'main(DemoApp.java:29)' could not be determined automatically, due to type erasure. You can give type information hints by using the returns(...) method on the result of the transformation call, or by letting your function implement the 'ResultTypeQueryable' interface.
at org.apache.flink.api.dag.Transformation.getOutputType(Transformation.java:45

函数返回类型由于类型删除,无法自动确定类型;可使用returns方法或使用函数实现ResultTypeQueryable接口;

org.apache.flink.api.common.functions.InvalidTypesException: The generic type parameters of 'Collector' are missing. In many cases lambda methods don't provide enough information for automatic type extraction when Java generics are involved. An easy workaround is to use an (anonymous) class instead that implements the 'org.apache.flink.api.common.functions.FlatMapFunction' interface. Otherwise the type has to be specified explicitly using type information.

  Collector泛型类型参数丢失。在使用Java泛型时lambda方法无法提供足够的信息来进行自动进行类型提取。一个简单的解决方案是使用匿名内部类代替来实现FlatMapFunction接口,不然只能使用类型信息显式指定类型;

  抛出的上面这两个异常描述的内容其实很明确了,简单来说就是:在实现FlatMapFunction时使用lambda表达式导致了Collector变量的泛型类型参数丢(由于类型删除),简单的解决方案是把lambda表达式换成匿名内部类或者显式指定类型(使用returns方法或实现ResultTypeQueryable接口)
下面简单谈谈Java的类型擦除与flink的显式指定类型;  

Java类型擦除

  Java的泛型被很多人诟病称为“伪泛型”,也是因为类型擦除这个原因,泛型在Java中就是属于语法糖;
  在Java中JVM虚拟机层面并不存在泛型的概念,Java在编译阶段把泛型的类型参数给擦除掉了,在运行阶段并没有泛型的概念;

public class Data {
private T obj;

public T getObj() {
    return obj;
}

public void setObj(T obj) {
    this.obj = obj;
 }
}

  如上类,在经过Java编译成为class文件后其中的类型参数T将被擦除,字段obj变成了Object类型,两个get、set方法中的T也都换成了Object类型;

Apache-Flink中的Java泛型与Lambda表达式

泛型实现主要有两种:
  Code sharing:一个原始类的泛型类型只有一份目标代码。
  Code specialization:对每个泛型类型都生成不同的代码。
  Java属于第一种,C#与C++属于第二种,两种实现各有春秋吧,这里不讨论;
  为了保证Java的多态特性编译器在进行类型擦除时还可能会生成桥接方法用于保证类型擦除所导致子类与父类方法实现不一致问题;

Flink中的泛型与lambda

stream.flatMap(new FlatMapFunction() {
        @Override
        public void flatMap(Integer value, Collector out) throws Exception {
            System.out.println(value);
        }
    });

  在Flink中使用各种算子的时候可能会有类似上面面这种用法,上面这种方式使用并没有什么问题,这里的FlatMapFunction就是一个泛型接口,使用了匿名内部类实现了该接口并传递给了flatMap算子;

stream.flatMap((FlatMapFunction) (value, out) -> {
        System.out.println(value);
})

  也有的人直接使用lambda表达式实现FlatMapFunction接口传递给flatMap算子,但这时候很多新手估计会发现程序运行的时候报错了,抛出了本文最开始的那两个异常;
  为什么使用匿名内部类就没问题,而使用lambda表达式就不行报错了,其实异常信息已经描述很清楚了。这里简单看看为什么匿名内部类可以,lambda表达式不可以,使用returns方法或实现ResultTypeQueryable接口也可以;

  上面介绍了在Java中会对泛型信息进行类型参数擦除,但在这里为啥使用匿名内部类实现FlatMapFunction时却还是可以获取得到泛型参数?
  其实Java中编译时的泛型类型擦除并不是把所以泛型相关的信息全部擦干干净净,Javac编译时擦除的只是结构化之外(程序执行流)的信息这部分信息存储在字节码的Code属性中,类、字段、方法的泛型类型参数元数据都会被保留下来,这些存储在Signature属性中;可通过反射得到相关的泛型参数信息;

s.flatMap(new FlatMapFunction() {
        @Override
        public void flatMap(String value, List out) {
            System.out.println("stu");
        }
    });

Apache-Flink中的Java泛型与Lambda表达式

  而lambda表达式实现FlatMapFunction却获取不到泛型参数,是的。
  匿名内部类会编译成相关的类字节码存储在class文件中,而lambda表达式却也只是Java的语法糖并不会存在相关的类字节码,只会在lambda表达式运行时调用invokedynamic指令执行逻辑。lambda表达式丢失了更多的类型信息,也就导致了使用lambda表达式获取不到泛型类型参数;

s.flatMap((FlatMapFunction) (value, out) -> 
System.out.println("stu"));

Apache-Flink中的Java泛型与Lambda表达式

Flink中使用lambda后的写法
  其实上面异常信息已经说得非常清楚了,调用returns方法或实现ResultTypeQueryable接口,这里就简单说这两种用法;

returns方法
  调用该方法的用法也比较简单,就是返回的Collector需要哪个泛型类型参数你就调用returns方法注册哪种类型,调用returns方法一定是要在某个算子之后紧接着第一个调用,简单理解就是未某个算子注册返回类型;

 stream.flatMap((FlatMapFunction) (value, out) -> {
        System.out.println(value);
    })
    .returns(String.class)  

ResultTypeQueryable接口
  实现此接口就可以告诉系统此算子的返回值类型,实现了此接口的优先级最高,不会再通过反射去获取返回值类型。还可以根据类型参数的不同使用不同的返回值类型;实现此接口可定制化程度很高、灵活。Flink kafka相关的连接器中就是用了这种模式。

public class FlatFun implements ResultTypeQueryable, FlatMapFunction {
@Override
public TypeInformation getProducedType() {
    return TypeInformation.of(String.class);
}
@Override
public void flatMap(Integer value, Collector out) {
    out.collect(String.valueOf(value));
    System.out.println("flatFun");
}
}
stream.flatMap(new FlatFun())
            .print();

推荐阅读
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • c# – UWP:BrightnessOverride StartOverride逻辑 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • 本文详细介绍了macOS系统的核心组件,包括如何管理其安全特性——系统完整性保护(SIP),并探讨了不同版本的更新亮点。对于使用macOS系统的用户来说,了解这些信息有助于更好地管理和优化系统性能。 ... [详细]
author-avatar
Yomon-00
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有