Java 泛型類型擦除

📖 概述

本文檔詳細解釋了 Flink 中 TypeInformation 的作用、原理和使用方法,幫助理解為什么 Flink 需要顯式的類型信息。

🎯 核心問題:Java 泛型類型擦除

什么是類型擦除?

Java 在編譯時會將泛型信息擦除,這意味著在運行時無法獲取泛型的具體類型信息。

在這里插入圖片描述

類型擦除的影響

  • 無法選擇合適的序列化器 - 不知道數據類型就無法優化序列化
  • 無法進行類型檢查 - 運行時類型安全無法保證
  • 性能優化受限 - 只能使用通用的低效處理方式

類型擦除的影響

  • 無法選擇合適的序列化器 - 不知道數據類型就無法優化序列化
  • 無法進行類型檢查 - 運行時類型安全無法保證
  • 性能優化受限 - 只能使用通用的低效處理方式

🔧 Flink 的解決方案:TypeInformation

核心代碼解析

在 Flink 的 StreamExecutionEnvironment.addSource() 方法中:

// 這行代碼的作用:為數據源解析類型信息
TypeInformation<OUT> resolvedTypeInfo =getTypeInfo(function, sourceName, SourceFunction.class, typeInfo);

類型推斷策略

在這里插入圖片描述

getTypeInfo 方法的邏輯

  1. 優先使用用戶指定的類型 - 如果 typeInfo 參數不為 null
  2. 查詢源函數的類型 - 如果實現了 ResultTypeQueryable 接口
  3. 反射分析 - 使用 TypeExtractor.createTypeInfo() 分析泛型
  4. 兜底處理 - 創建 MissingTypeInfo 對象

💻 完整代碼示例

以下代碼演示了 Java 泛型類型擦除問題以及 Flink 如何通過 TypeInformation 解決這個問題:

package org.apache.flink.streaming.examples.lkk;import java.util.ArrayList;
import java.util.List;/*** 演示Java泛型類型擦除和TypeInformation的必要性*/
public class TypeInformationExample {public static void main(String[] args) {// 演示類型擦除問題demonstrateTypeErasure();// 演示Flink如何解決這個問題demonstrateFlinkSolution();}/*** 演示Java泛型類型擦除的問題*/public static void demonstrateTypeErasure() {System.out.println("=== Java泛型類型擦除演示 ===");// 創建不同類型的ListList<String> stringList = new ArrayList<>();List<Integer> intList = new ArrayList<>();List<Person> personList = new ArrayList<>();stringList.add("Hello");intList.add(123);personList.add(new Person("張三", 25));// 在運行時,所有泛型信息都被擦除了!System.out.println("stringList的運行時類型: " + stringList.getClass());System.out.println("intList的運行時類型: " + intList.getClass());System.out.println("personList的運行時類型: " + personList.getClass());// 它們的Class都是一樣的!System.out.println("三個List的Class是否相同: " +(stringList.getClass() == intList.getClass() &&intList.getClass() == personList.getClass()));// 這就是問題所在:運行時無法知道List里裝的是什么類型!System.out.println();}/*** 演示Flink如何通過TypeInformation解決類型擦除問題*/public static void demonstrateFlinkSolution() {System.out.println("=== Flink TypeInformation解決方案演示 ===");// 模擬Flink的TypeInformationTypeInfo<String> stringTypeInfo = new TypeInfo<>("String類型", String.class);TypeInfo<Integer> intTypeInfo = new TypeInfo<>("Integer類型", Integer.class);TypeInfo<Person> personTypeInfo = new TypeInfo<>("Person類型", Person.class);// 模擬Flink的數據處理processData("Hello World", stringTypeInfo);processData(42, intTypeInfo);processData(new Person("李四", 30), personTypeInfo);}/*** 模擬Flink如何根據TypeInformation選擇不同的處理策略*/public static <T> void processData(T data, TypeInfo<T> typeInfo) {System.out.println("處理數據: " + data);System.out.println("類型信息: " + typeInfo.getTypeName());// 根據類型信息選擇不同的序列化策略if (typeInfo.getTypeClass() == String.class) {System.out.println("→ 使用字符串序列化器:UTF-8編碼");} else if (typeInfo.getTypeClass() == Integer.class) {System.out.println("→ 使用整數序列化器:4字節二進制");} else if (typeInfo.getTypeClass() == Person.class) {System.out.println("→ 使用對象序列化器:JSON格式");}System.out.println("數據處理完成!");System.out.println();}/*** 模擬Flink的TypeInformation類*/static class TypeInfo<T> {private final String typeName;private final Class<T> typeClass;public TypeInfo(String typeName, Class<T> typeClass) {this.typeName = typeName;this.typeClass = typeClass;}public String getTypeName() {return typeName;}public Class<T> getTypeClass() {return typeClass;}}/*** 示例Person類*/static class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}}
}

運行結果

=== Java泛型類型擦除演示 ===
stringList的運行時類型: class java.util.ArrayList
intList的運行時類型: class java.util.ArrayList
personList的運行時類型: class java.util.ArrayList
三個List的Class是否相同: true=== Flink TypeInformation解決方案演示 ===
處理數據: Hello World
類型信息: String類型
→ 使用字符串序列化器:UTF-8編碼
數據處理完成!處理數據: 42
類型信息: Integer類型
→ 使用整數序列化器:4字節二進制
數據處理完成!處理數據: Person{name='李四', age=30}
類型信息: Person類型
→ 使用對象序列化器:JSON格式
數據處理完成!

🚀 性能優化的重要性

不同類型的序列化策略

數據類型序列化器優勢
StringUTF-8字符串序列化器緊湊的文本編碼
Integer4字節整數序列化器固定長度,高效
Person對象POJO/Kryo序列化器結構化對象處理
集合類型集合序列化器批量處理優化

TypeInformation 的核心價值

  1. 解決類型擦除問題 - 在運行時保留類型信息
  2. 選擇最優序列化器 - 根據類型選擇高效的序列化方式
  3. 保證類型安全 - 編譯時和運行時的類型檢查
  4. 性能優化 - 避免使用低效的通用序列化器

🎯 總結

關鍵要點

  • Java 泛型類型擦除:運行時無法獲取泛型的具體類型信息
  • TypeInformation 作用:顯式保存類型信息,指導 Flink 如何處理數據
  • 類型推斷策略:用戶指定 → ResultTypeQueryable → 反射分析 → 兜底處理
  • 性能優化:不同類型使用不同的序列化策略,提高處理效率
  • 類型安全:確保分布式計算中的數據類型一致性

實際應用

在 Flink 應用開發中,理解 TypeInformation 有助于:

  • 正確處理自定義數據類型
  • 優化序列化性能
  • 避免類型相關的運行時錯誤
  • 更好地理解 Flink 的內部機制

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919254.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919254.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919254.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從“寫代碼”到“定義需求”:AI編程工具如何重構軟件開發的核心流程?

從“寫代碼”到“定義需求”&#xff1a;AI編程工具如何重構軟件開發的核心流程&#xff1f; 軟件開發的核心流程正在經歷一場靜默革命。十年前&#xff0c;開發者的日常被“寫代碼”填滿——從變量定義到邏輯實現&#xff0c;每行代碼都需要手動敲擊&#xff1b;而今天&#x…

一顆TTS語音芯片給產品增加智能語音播報能力

?一顆TTS語音芯片給產品增加智能語音播報能力傳統語音播報芯片可以設置一些固定的語音片段或者內容&#xff0c;但是對于現在各種創新產品層出不窮的時代&#xff0c;傳統的語音播報芯片能力似乎有點不夠用了。而TTS語音合成芯片&#xff0c;正在逐漸登上舞臺中央。TTS語音合成…

[免費]基于Python的影視數據可視化分析系統(Flask+echarts)【論文+源碼+SQL腳本】

大家好&#xff0c;我是python222_小鋒老師&#xff0c;看到一個不錯的基于Python的影視數據可視化分析系統(Flaskecharts)&#xff0c;分享下哈。 項目視頻演示 【免費】基于Python的愛奇藝影視電影數據可視化分析系統(Flaskecharts) Python畢業設計_嗶哩嗶哩_bilibili 系統…

Three.js 材質系統深度解析

簡介 Three.js 是一個功能強大的開源 3D 圖形庫&#xff0c;廣泛應用于 Web 端的 3D 可視化開發。其材質系統是 Three.js 的核心組成部分之一&#xff0c;負責定義 3D 對象的表面外觀和渲染效果。從簡單的顏色填充到復雜的動態效果&#xff0c;材質系統為開發者提供了高度靈活…

FP16(半精度)和FP32(單精度)

FP16&#xff08;Half-Precision Floating Point&#xff0c;半精度浮點數&#xff09;是一種使用16位二進制數表示浮點數值的數據格式&#xff0c;在深度學習、圖形渲染和高性能計算中廣泛應用。其核心定義、技術特性與應用價值如下&#xff1a;一、FP16的核心定義與結構二進制…

基于Vue + Node能源采購系統的設計與實現/基于express的能源管理系統#node.js

基于Vue Node能源采購系統的設計與實現/基于express的能源管理系統#node.js

代碼管理系統簡介與部署

目錄版本控制1&#xff1a;版本控制概念2&#xff1a;版本控制的功能&#xff08;1&#xff09;檢入檢出控制&#xff08;2&#xff09;分支和合井&#xff08;3&#xff09;歷史記錄3&#xff1a;版本控制的流程&#xff08;1&#xff09;創建配置項。&#xff08;2&#xff0…

Pandas數據結構詳解Series與DataFrame

Pandas數據結構詳解&#xff1a;Series與DataFrame實戰指南 前言 Pandas是Python數據分析的核心庫&#xff0c;其強大的數據處理能力主要基于兩種核心數據結構&#xff1a;Series和DataFrame。本文將深入解析這兩種數據結構的概念、創建方式、常用屬性和方法&#xff0c;并通…

TensorRT-LLM.V1.1.0rc0:在無 GitHub 訪問權限的服務器上編譯 TensorRT-LLM 的完整實踐

一、TensorRT-LLM有三種安裝方式&#xff0c;從簡單到難 1.NGC上的預構建發布容器進行部署,見《tensorrt-llm0.20.0離線部署DeepSeek-R1-Distill-Qwen-32B》。 2.通過pip進行部署。 3.從源頭構建再部署。 在實際開發中&#xff0c;我們常常面臨這樣的場景&#xff1a;本地筆記…

完整、可落地的 Elasticsearch 拼音補全配置模板 設計方案

在中文搜索場景中&#xff0c;用戶經常使用拼音輸入&#xff08;如 “iPhone”、“pingguo”&#xff09;來搜索中文內容&#xff08;如“蘋果手機”&#xff09;。為了提升用戶體驗&#xff0c;Elasticsearch 可通過 拼音分詞器 Completion Suggester 實現 拼音補全&#xff…

Redis面試精講 Day 23:Redis與數據庫數據一致性保障

【Redis面試精講 Day 23】Redis與數據庫數據一致性保障 在“Redis面試精講”系列的第23天&#xff0c;我們將深入探討Redis與數據庫數據一致性保障這一在高并發分布式系統中極為關鍵的技術難題。該主題是面試中的高頻壓軸題&#xff0c;常出現在中高級后端開發、架構師崗位的考…

HTML <link rel=“preload“>:提前加載關鍵資源的性能優化利器

在網頁性能優化中&#xff0c;“資源加載時機”是影響用戶體驗的關鍵因素——一個延遲加載的核心CSS可能導致頁面“閃白”&#xff0c;一段未及時加載的關鍵JS可能讓交互按鈕失效。傳統的資源加載方式&#xff08;如<link>加載CSS、<script>加載JS&#xff09;依賴…

WPF加載記憶上次圖像

問題點使用MVVM先viewModel構造函數然后才Loaded事件,但Loaded事情時halcon控件沒有加載完畢。Window_ContentRendered事件中halcon控件才有了句柄。解決問題1.viewModel函數中調用相機的類獲取相機名(在這里是為了MVVM中以后可以做其它的事情如識別二維碼)2.在Window_ContentR…

AT89C52單片機介紹

目錄 1AT89C52原理圖及結構框圖 1.1 原理圖 1.2 AT89C52 結構框圖 1.2.1 8 位 CPU 1.2.2 存儲器 1.2.3 I/O 端口 1.2.4 定時器 / 計數器 1.2.5 串行通信接口 1.2.6 中斷系統 1.2.7 時鐘與復位 1.2.8 總線結構 1.2.9 特殊功能寄存器區 2 AT89C52引腳介紹(PDIP) …

聯網車輛功能安全和網絡安全的挑戰與當前解決方案

摘要在過去的二十年里&#xff0c;數字化重塑了我們的日常生活&#xff0c;汽車行業也身處這一變革之中。如今的車輛正變得日益智能且聯網&#xff0c;具備了更多的安全和便捷功能&#xff08;如自動緊急制動、自適應巡航控制&#xff09;。下一代車輛將實現高度自動化乃至 5 級…

網絡安全(Java語言)腳本 匯總(二)

文章目錄目錄遍歷漏洞掃描器源代碼思路一、核心功能二、依賴庫三、核心流程四、關鍵方法五、數據結構六、輸出信息目錄遍歷漏洞掃描器 源代碼 /*** description : 目錄遍歷漏洞掃描器* 注意; 在輸入URL時 要求必須保存 ?page 的末尾 才能保證路徑合成的有效性*//*** desc…

基于 ArcFace/ArcMargin 損失函數的深度特征學習高性能人臉識別解決方案

要實現當前最先進的人臉識別系統,我們需要采用業界公認性能最佳的算法框架,主要包括基于 ArcFace/ArcMargin 損失函數的深度特征學習、MTCNN 人臉檢測與對齊以及高效特征檢索三大核心技術。以下是優化后的解決方案: 核心優化點說明 算法選擇:采用 ArcFace(Additive Angul…

Sql server 查詢每個表大小

在SQL Server中&#xff0c;你可以通過查詢系統視圖和系統表來獲取數據庫中每個表的大小。這可以通過幾種不同的方式來實現&#xff0c;下面是一些常用的方法&#xff1a;方法1&#xff1a;使用sp_spaceused存儲過程sp_spaceused是一個內置的存儲過程&#xff0c;可以用來顯示數…

react 錯誤邊界

注意點&#xff1a; 類組件是可以和函數式組件混合寫的&#xff01;&#xff01;&#xff01;getDerivedStateFromError是靜態的&#xff0c;避免副作用&#xff0c;如果想將錯誤上報到服務器&#xff0c;則去componentDidCatch里去處理。getDerivedStateFromError直接返回{ ha…

自定義 VSCode 標題欄以區分不同版本

自定義 VSCode 標題欄以區分不同版本 當您在同一臺計算機上使用多個 Visual Studio Code 版本時&#xff0c;自定義窗口標題欄是一個有效的方法&#xff0c;可以幫助您快速區分它們。 為何需要區分多個 VSCode 版本&#xff1f; 在同一臺電腦上安裝和使用多個 VSCode 實例是很常…