blob: 7d0b237f9917b2598bd8d842512878dac9528846 [file] [log] [blame]
<!DOCTYPE html>
<html lang="zh" dir=ZgotmplZ>
<head>
<link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css">
<script src="/bootstrap/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" type="text/css" href="/font-awesome/css/font-awesome.min.css">
<script src="/js/anchor.min.js"></script>
<script src="/js/flink.js"></script>
<link rel="canonical" href="https://flink.apache.org/zh/how-to-contribute/code-style-and-quality-java/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Code Style and Quality Guide — Java # 序言 # Pull Requests &amp; Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # Java Language Features and Libraries # Preconditions and Log Statements # Never concatenate strings in the parameters Don’t: Preconditions.checkState(value &lt;= threshold, &quot;value must be below &quot; &#43; threshold) Don’t: LOG.debug(&quot;value is &quot; &#43; value) Do: Preconditions.checkState(value &lt;= threshold, &quot;value must be below %s&quot;, threshold) Do: LOG.">
<meta name="theme-color" content="#FFFFFF"><meta property="og:title" content="Code Style and Quality Guide — Java" />
<meta property="og:description" content="Code Style and Quality Guide — Java # 序言 # Pull Requests &amp; Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # Java Language Features and Libraries # Preconditions and Log Statements # Never concatenate strings in the parameters Don’t: Preconditions.checkState(value &lt;= threshold, &quot;value must be below &quot; &#43; threshold) Don’t: LOG.debug(&quot;value is &quot; &#43; value) Do: Preconditions.checkState(value &lt;= threshold, &quot;value must be below %s&quot;, threshold) Do: LOG." />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://flink.apache.org/zh/how-to-contribute/code-style-and-quality-java/" /><meta property="article:section" content="how-to-contribute" />
<title>Code Style and Quality Guide — Java | Apache Flink</title>
<link rel="manifest" href="/manifest.json">
<link rel="icon" href="/favicon.png" type="image/x-icon">
<link rel="alternate" hreflang="en" href="https://flink.apache.org/how-to-contribute/code-style-and-quality-java/" title="Code Style and Quality Guide — Java">
<link rel="stylesheet" href="/book.min.22eceb4d17baa9cdc0f57345edd6f215a40474022dfee39b63befb5fb3c596b5.css" integrity="sha256-IuzrTRe6qc3A9XNF7dbyFaQEdAIt/uObY777X7PFlrU=">
<script defer src="/zh.search.min.4fed8368d7410bf2cb8853d136d796128533433358adcd85133b7d8014ce76ef.js" integrity="sha256-T&#43;2DaNdBC/LLiFPRNteWEoUzQzNYrc2FEzt9gBTOdu8="></script>
<!--
Made with Book Theme
https://github.com/alex-shpak/hugo-book
-->
<meta name="generator" content="Hugo 0.124.1">
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['disableCookies']);
_paq.push(["setDomains", ["*.flink.apache.org","*.nightlies.apache.org/flink"]]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
</head>
<body dir=ZgotmplZ>
<header>
<nav class="navbar navbar-expand-xl">
<div class="container-fluid">
<a class="navbar-brand" href="/zh/">
<img src="/img/logo/png/100/flink_squirrel_100_color.png" alt="Apache Flink" height="47" width="47" class="d-inline-block align-text-middle">
<span>Apache Flink</span>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<i class="fa fa-bars navbar-toggler-icon"></i>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">About</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="/zh/what-is-flink/flink-architecture/">架构</a>
</li>
<li>
<a class="dropdown-item" href="/zh/what-is-flink/flink-applications/">应用</a>
</li>
<li>
<a class="dropdown-item" href="/zh/what-is-flink/flink-operations/">运维</a>
</li>
<li>
<a class="dropdown-item" href="/zh/what-is-flink/use-cases/">应用场景</a>
</li>
<li>
<a class="dropdown-item" href="/zh/what-is-flink/powered-by/">Flink 用户</a>
</li>
<li>
<a class="dropdown-item" href="/zh/what-is-flink/roadmap/">开发计划</a>
</li>
<li>
<a class="dropdown-item" href="/zh/what-is-flink/community/">社区 & 项目信息</a>
</li>
<li>
<a class="dropdown-item" href="/zh/what-is-flink/security/">Security</a>
</li>
<li>
<a class="dropdown-item" href="/zh/what-is-flink/special-thanks/">特殊致谢</a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">教程</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-docs-stable/docs/try-flink/local_installation/">With Flink<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-kubernetes-operator-docs-stable/docs/try-flink-kubernetes-operator/quick-start/">With Flink Kubernetes Operator<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-cdc-docs-stable/docs/get-started/introduction/">With Flink CDC<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-ml-docs-stable/docs/try-flink-ml/quick-start/">With Flink ML<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-statefun-docs-stable/getting-started/project-setup.html">With Flink Stateful Functions<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-docs-stable/docs/learn-flink/overview/">Training Course<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Documentation</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-docs-stable/">Flink 1.19 (stable)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-docs-master/">Flink Master (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-kubernetes-operator-docs-stable/">Kubernetes Operator 1.8 (latest)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-kubernetes-operator-docs-main">Kubernetes Operator Main (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-cdc-docs-stable">CDC 3.0 (stable)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-cdc-docs-master">CDC Master (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-ml-docs-stable/">ML 2.3 (stable)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-ml-docs-master">ML Master (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-statefun-docs-stable/">Stateful Functions 3.3 (stable)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-statefun-docs-master">Stateful Functions Master (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">How to Contribute</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="/zh/how-to-contribute/overview/">如何参与贡献</a>
</li>
<li>
<a class="dropdown-item" href="/zh/how-to-contribute/contribute-code/">贡献代码</a>
</li>
<li>
<a class="dropdown-item" href="/zh/how-to-contribute/reviewing-prs/">审核 Pull Request</a>
</li>
<li>
<a class="dropdown-item" href="/zh/how-to-contribute/code-style-and-quality-preamble/">代码样式与质量指南</a>
</li>
<li>
<a class="dropdown-item" href="/zh/how-to-contribute/contribute-documentation/">贡献文档</a>
</li>
<li>
<a class="dropdown-item" href="/zh/how-to-contribute/documentation-style-guide/">文档样式指南</a>
</li>
<li>
<a class="dropdown-item" href="/zh/how-to-contribute/improve-website/">贡献网站</a>
</li>
<li>
<a class="dropdown-item" href="/zh/how-to-contribute/getting-help/">获取帮助</a>
</li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="/zh/downloads/">Downloads</a>
</li>
</ul>
<div class="book-search">
<div class="book-search-spinner hidden">
<i class="fa fa-refresh fa-spin"></i>
</div>
<form class="search-bar d-flex" onsubmit="return false;"su>
<input type="text" id="book-search-input" placeholder="搜索" aria-label="搜索" maxlength="64" data-hotkeys="s/">
<i class="fa fa-search search"></i>
<i class="fa fa-circle-o-notch fa-spin spinner"></i>
</form>
<div class="book-search-spinner hidden"></div>
<ul id="book-search-results"></ul>
</div>
</div>
</div>
</nav>
<div class="navbar-clearfix"></div>
</header>
<main class="flex">
<section class="container book-page">
<article class="markdown"><h1 id="code-style-and-quality-guide--java">
Code Style and Quality Guide — Java
<a class="anchor" href="#code-style-and-quality-guide--java">#</a>
</h1>
<h4 id="序言hahahugoshortcode62s0hbhb">
<a href="/zh/how-to-contribute/code-style-and-quality-preamble/">序言</a>
<a class="anchor" href="#%e5%ba%8f%e8%a8%80hahahugoshortcode62s0hbhb">#</a>
</h4>
<h4 id="pull-requests--changeshahahugoshortcode62s1hbhb">
<a href="/zh/how-to-contribute/code-style-and-quality-pull-requests/">Pull Requests &amp; Changes</a>
<a class="anchor" href="#pull-requests--changeshahahugoshortcode62s1hbhb">#</a>
</h4>
<h4 id="常用编码指南hahahugoshortcode62s2hbhb">
<a href="/zh/how-to-contribute/code-style-and-quality-common/">常用编码指南</a>
<a class="anchor" href="#%e5%b8%b8%e7%94%a8%e7%bc%96%e7%a0%81%e6%8c%87%e5%8d%97hahahugoshortcode62s2hbhb">#</a>
</h4>
<h4 id="java-语言指南hahahugoshortcode62s3hbhb">
<a href="/zh/how-to-contribute/code-style-and-quality-java/">Java 语言指南</a>
<a class="anchor" href="#java-%e8%af%ad%e8%a8%80%e6%8c%87%e5%8d%97hahahugoshortcode62s3hbhb">#</a>
</h4>
<h4 id="scala-语言指南hahahugoshortcode62s4hbhb">
<a href="/zh/how-to-contribute/code-style-and-quality-scala/">Scala 语言指南</a>
<a class="anchor" href="#scala-%e8%af%ad%e8%a8%80%e6%8c%87%e5%8d%97hahahugoshortcode62s4hbhb">#</a>
</h4>
<h4 id="组件指南hahahugoshortcode62s5hbhb">
<a href="/zh/how-to-contribute/code-style-and-quality-components/">组件指南</a>
<a class="anchor" href="#%e7%bb%84%e4%bb%b6%e6%8c%87%e5%8d%97hahahugoshortcode62s5hbhb">#</a>
</h4>
<h4 id="格式指南hahahugoshortcode62s6hbhb">
<a href="/zh/how-to-contribute/code-style-and-quality-formatting/">格式指南</a>
<a class="anchor" href="#%e6%a0%bc%e5%bc%8f%e6%8c%87%e5%8d%97hahahugoshortcode62s6hbhb">#</a>
</h4>
<h2 id="java-language-features-and-libraries">
Java Language Features and Libraries
<a class="anchor" href="#java-language-features-and-libraries">#</a>
</h2>
<h3 id="preconditions-and-log-statements">
Preconditions and Log Statements
<a class="anchor" href="#preconditions-and-log-statements">#</a>
</h3>
<ul>
<li>Never concatenate strings in the parameters
<ul>
<li><span style="text-decoration:underline;">Don’t:</span> <code>Preconditions.checkState(value &lt;= threshold, &quot;value must be below &quot; + threshold)</code></li>
<li><span style="text-decoration:underline;">Don’t:</span> <code>LOG.debug(&quot;value is &quot; + value)</code></li>
<li><span style="text-decoration:underline;">Do:</span> <code>Preconditions.checkState(value &lt;= threshold, &quot;value must be below %s&quot;, threshold)</code></li>
<li><span style="text-decoration:underline;">Do:</span> <code>LOG.debug(&quot;value is {}&quot;, value)</code></li>
</ul>
</li>
</ul>
<h3 id="generics">
Generics
<a class="anchor" href="#generics">#</a>
</h3>
<ul>
<li><strong>No raw types:</strong> Do not use raw types, unless strictly necessary (sometimes necessary for signature matches, arrays).</li>
<li><strong>Suppress warnings for unchecked conversions:</strong> Add annotations to suppress warnings, if they cannot be avoided (such as “unchecked”, or “serial”). Otherwise warnings about generics flood the build and drown relevant warnings.</li>
</ul>
<h3 id="equals--hashcode">
equals() / hashCode()
<a class="anchor" href="#equals--hashcode">#</a>
</h3>
<ul>
<li><strong>equals() / hashCode() should be added when they are well defined only.</strong></li>
<li>They should <strong>not be added to enable a simpler assertion in tests</strong> when they are not well defined. Use hamcrest matchers in that case: <a href="https://github.com/junit-team/junit4/wiki/matchers-and-assertthat">https://github.com/junit-team/junit4/wiki/matchers-and-assertthat</a></li>
<li>A common indicator that the methods are not well defined is when they take a subset of the fields into account (other than fields that are purely auxiliary).</li>
<li>When the methods take mutable fields into account, you often have a design issue. The <code>equals()</code>/<code>hashCode()</code> methods suggest to use the type as a key, but the signatures suggest it is safe to keep mutating the type.</li>
</ul>
<h3 id="java-serialization">
Java Serialization
<a class="anchor" href="#java-serialization">#</a>
</h3>
<ul>
<li>
<p><strong>Do not use Java Serialization for anything !!!</strong></p>
</li>
<li>
<p><strong>Do not use Java Serialization for anything !!! !!!</strong></p>
</li>
<li>
<p><strong>Do not use Java Serialization for anything !!! !!! !!!</strong></p>
</li>
<li>
<p>Internal to Flink, Java serialization is used to transport messages and programs through RPC. This is the only case where we use Java serialization. Because of that, some classes need to be serializable (if they are transported via RPC).</p>
</li>
<li>
<p><strong>Serializable classes must define a Serial Version UID:</strong></p>
<p><code>private static final long serialVersionUID = 1L;</code></p>
</li>
<li>
<p><strong>The Serial Version UID for new classes should start at 1</strong> and should generally be bumped on every incompatible change to the class according to the Java serialization compatibility definition (i.e: changing the type of a field, or moving the position of a class in the class hierarchy).</p>
</li>
</ul>
<h3 id="java-reflection">
Java Reflection
<a class="anchor" href="#java-reflection">#</a>
</h3>
<p><strong>Avoid using Java’s Reflection API</strong></p>
<ul>
<li>Java’s Reflection API can be a very useful tool in certain cases but in all cases it is a hack and one should research for alternatives. The only cases where Flink should use reflection are
<ul>
<li>Dynamically loading implementations from another module (like webUI, additional serializers, pluggable query processors).</li>
<li>Extracting types inside the TypeExtractor class. This is fragile enough and should not be done outside the TypeExtractor class.</li>
<li>Some cases of cross-JDK version features, where we need to use reflection because we cannot assume a class/method to be present in all versions.</li>
</ul>
</li>
<li>If you need reflection for accessing methods or fields in tests, it usually indicates some deeper architectural issues, like wrong scoping, bad separation of concerns, or that there is no clean way to provide components / dependencies to the class that is tested</li>
</ul>
<h3 id="collections">
Collections
<a class="anchor" href="#collections">#</a>
</h3>
<ul>
<li><strong>ArrayList and ArrayDeque are almost always superior to LinkedList</strong>, except when frequently insert and deleting in the middle of the list</li>
<li><strong>For Maps, avoid patterns that require multiple lookups</strong>
<ul>
<li><code>contains()</code> before <code>get()</code><code>get()</code> and check null</li>
<li><code>contains()</code> before <code>put()</code><code>putIfAbsent()</code> or <code>computeIfAbsent()</code></li>
<li>Iterating over keys, getting values → iterate over <code>entrySet()</code></li>
</ul>
</li>
<li><strong>Set the initial capacity for a collection only if there is a good proven reason</strong> for that, otherwise do not clutter the code. In case of <strong>Maps</strong> it can be even deluding because the Map&rsquo;s load factor effectively reduces the capacity.</li>
</ul>
<h3 id="java-optional">
Java Optional
<a class="anchor" href="#java-optional">#</a>
</h3>
<ul>
<li>Use <strong>@Nullable annotation where you do not use Optional</strong> for the nullable values.</li>
<li>If you can prove that <code>Optional</code> usage would lead to a <strong>performance degradation in critical code then fallback to @Nullable</strong>.</li>
<li>Always use <strong>Optional to return nullable values</strong> in the API/public methods except the case of a proven performance concern.</li>
<li><strong>Do not use Optional as a function argument</strong>, instead either overload the method or use the Builder pattern for the set of function arguments.
<ul>
<li>Note: an Optional argument can be allowed in a private helper method if you believe that it simplifies the code
(<a href="https://github.com/apache/flink/blob/master/flink-formats/flink-avro/src/main/java/org/apache/flink/formats/avro/typeutils/AvroFactory.java#L95">example</a>).</li>
</ul>
</li>
<li><strong>Do not use Optional for class fields</strong>.</li>
</ul>
<h3 id="lambdas">
Lambdas
<a class="anchor" href="#lambdas">#</a>
</h3>
<ul>
<li>
<p>Prefer non-capturing lambdas (lambdas that do not contain references to the outer scope). Capturing lambdas need to create a new object instance for every call. Non-capturing lambdas can use the same instance for each invocation.</p>
<p><strong>don’t:</strong></p>
<pre tabindex="0"><code>map.computeIfAbsent(key, x -&gt; key.toLowerCase())
</code></pre><p><strong>do:</strong></p>
<pre tabindex="0"><code>map.computeIfAbsent(key, k -&gt; k.toLowerCase());
</code></pre></li>
<li>
<p>Consider method references instead of inline lambdas</p>
<p><strong>don’t</strong>:</p>
<pre tabindex="0"><code>map.computeIfAbsent(key, k-&gt; Loader.load(k));
</code></pre><p><strong>do:</strong></p>
<pre tabindex="0"><code>map.computeIfAbsent(key, Loader::load);
</code></pre></li>
</ul>
<h3 id="java-streams">
Java Streams
<a class="anchor" href="#java-streams">#</a>
</h3>
<ul>
<li>Avoid Java Streams in any performance critical code.</li>
<li>The main motivation to use Java Streams would be to improve code readability. As such, they can be a good match in parts of the code that are not data-intensive, but deal with coordination..</li>
<li>Even in the latter case, try to limit the scope to a method, or a few private methods within an internal class.</li>
</ul>
</article>
<div class="edit-this-page">
<p>
<a href="https://cwiki.apache.org/confluence/display/FLINK/Flink+Translation+Specifications">Want to contribute translation?</a>
</p>
<p>
<a href="//github.com/apache/flink-web/edit/asf-site/docs/content.zh/how-to-contribute/code-style-and-quality-java.md">
Edit This Page<i class="fa fa-edit fa-fw"></i>
</a>
</p>
</div>
</section>
<aside class="book-toc">
<nav id="TableOfContents"><h3>On This Page <a href="javascript:void(0)" class="toc" onclick="collapseToc()"><i class="fa fa-times" aria-hidden="true"></i></a></h3>
<ul>
<li><a href="#code-style-and-quality-guide--java">Code Style and Quality Guide — Java</a>
<ul>
<li>
<ul>
<li></li>
</ul>
</li>
<li><a href="#java-language-features-and-libraries">Java Language Features and Libraries</a>
<ul>
<li><a href="#preconditions-and-log-statements">Preconditions and Log Statements</a></li>
<li><a href="#generics">Generics</a></li>
<li><a href="#equals--hashcode">equals() / hashCode()</a></li>
<li><a href="#java-serialization">Java Serialization</a></li>
<li><a href="#java-reflection">Java Reflection</a></li>
<li><a href="#collections">Collections</a></li>
<li><a href="#java-optional">Java Optional</a></li>
<li><a href="#lambdas">Lambdas</a></li>
<li><a href="#java-streams">Java Streams</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</aside>
<aside class="expand-toc hidden">
<a class="toc" onclick="expandToc()" href="javascript:void(0)">
<i class="fa fa-bars" aria-hidden="true"></i>
</a>
</aside>
</main>
<footer>
<div class="separator"></div>
<div class="panels">
<div class="wrapper">
<div class="panel">
<ul>
<li>
<a href="https://flink-packages.org/">flink-packages.org</a>
</li>
<li>
<a href="https://www.apache.org/">Apache Software Foundation</a>
</li>
<li>
<a href="https://www.apache.org/licenses/">License</a>
</li>
<li>
<a href="/how-to-contribute/code-style-and-quality-java/">
<i class="fa fa-globe" aria-hidden="true"></i>&nbsp;English
</a>
</li>
</ul>
</div>
<div class="panel">
<ul>
<li>
<a href="/zh/what-is-flink/security">Security</a-->
</li>
<li>
<a href="https://www.apache.org/foundation/sponsorship.html">Donate</a>
</li>
<li>
<a href="https://www.apache.org/foundation/thanks.html">Thanks</a>
</li>
</ul>
</div>
<div class="panel icons">
<div>
<a href="/posts">
<div class="icon flink-blog-icon"></div>
<span>Flink blog</span>
</a>
</div>
<div>
<a href="https://github.com/apache/flink">
<div class="icon flink-github-icon"></div>
<span>Github</span>
</a>
</div>
<div>
<a href="https://twitter.com/apacheflink">
<div class="icon flink-twitter-icon"></div>
<span>Twitter</span>
</a>
</div>
</div>
</div>
</div>
<hr/>
<div class="container disclaimer">
<p>The contents of this website are © 2024 Apache Software Foundation under the terms of the Apache License v2. Apache Flink, Flink, and the Flink logo are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries.</p>
</div>
</footer>
</body>
</html>