<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Posts on Bankkase Blog</title>
    <link>https://bankkase.pages.dev/posts/</link>
    <description>Recent content in Posts on Bankkase Blog</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Fri, 17 Jul 2026 09:35:51 +0800</lastBuildDate>
    <atom:link href="https://bankkase.pages.dev/posts/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Lambda表达式和函数式接口</title>
      <link>https://bankkase.pages.dev/posts/java/lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%92%8C%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3/</link>
      <pubDate>Fri, 17 Jul 2026 09:35:51 +0800</pubDate>
      <guid>https://bankkase.pages.dev/posts/java/lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%92%8C%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3/</guid>
      <description>&lt;h2 id=&#34;lambda表达式和函数式接口&#34;&gt;Lambda表达式和函数式接口&lt;/h2&gt;
&lt;p&gt;Lambda表达式语法的本质上就是一种表达式，而非对象。
Lambda表达式的返回值会被自动推导。如果参数被省略，那么也会尝试自动推导。&lt;/p&gt;
&lt;p&gt;函数式接口(Functional Interface)指的是只有一个抽象方法的接口。（可以有一些非抽象方法，如重写或默认）
Lambda表达式是被设计为快速地转换为函数式接口的实例。程序员不用手动初始化函数式接口的实例了，这些对象和类的管理由编译器处理。&lt;/p&gt;
&lt;h3 id=&#34;方法引用和构造器引用&#34;&gt;方法引用和构造器引用&lt;/h3&gt;
&lt;p&gt;方法引用（Method Reference）是一种简便方式，可以在只想调用一个方法而不做其他操作时，直接使用某个方法的逻辑。
原理类似于Lambda表达式，编译器自动为你创建函数式接口的实例。
例如：
&lt;code&gt;var timer = new Timer(1000, System.out::println)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;要注意方法重载的选择受函数式接口的签名影响。
方法引用支持三种语法：
&lt;code&gt;object::instanceMethod&lt;/code&gt;：lambda表达式的参数列表原样传送到这个对象的这个方法的参数中。
&lt;code&gt;Class::instanceMethod&lt;/code&gt;：lambda表达式的第一个参数成为方法的隐式参数，也就是说：&lt;code&gt;String::compareToIgnoreCase&lt;/code&gt;, 等价于&lt;code&gt;(a, b) -&amp;gt; a.compareToIgnoreCase(b)&lt;/code&gt;
&lt;code&gt;Class::staticMethod&lt;/code&gt;: 所有参数传递到静态方法。&lt;/p&gt;
&lt;p&gt;构造器引用
格式：&lt;code&gt;Class::new&lt;/code&gt;
解决的问题：将类型被擦除的数组重新构建为特定对象数组。
例如：&lt;code&gt;Person[] people = stream.toArray(Person::new)&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;变量作用域和闭包&#34;&gt;变量作用域和闭包&lt;/h3&gt;
&lt;p&gt;Lambda表达式由三部分组成：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;一个代码块&lt;/li&gt;
&lt;li&gt;参数&lt;/li&gt;
&lt;li&gt;自由变量的值，这里是指非参数切不在代码块内被定义的变量&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当lambda体使用了外部的变量时，称为这个变量被捕获（captured）
捕获capture自由变量的代码块称为闭包closure。lambda表达式就是闭包。&lt;/p&gt;
&lt;p&gt;捕获变量的限制（这是为了并发安全考虑）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在lambda体中，不可以改变捕获的变量。&lt;/li&gt;
&lt;li&gt;捕获的变量不可能在外部改变&lt;/li&gt;
&lt;li&gt;捕获的变量必须是事实最终变量(efectively final)。aka，变量初始化后不会再被赋新值。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;lambda表达式的体与它的上一层嵌套块有相同的作用域。也就是说，lambda表达式不新建作用域，参数和内部变量不能和上一层重名。
这也是为什么你可以直接使用外层方法的&lt;code&gt;this&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;lambda表达式的应用&#34;&gt;Lambda表达式的应用&lt;/h3&gt;
&lt;p&gt;《Core Java 中文版》6.2.7&lt;/p&gt;
&lt;p&gt;为什么要使用Lambda表达式？一个重要原因是支持代码的延迟执行（deferred execution）
换句话说，如果不需要延迟执行，那么很可能不需要lambda表达式。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在一个单独的线程运行代码&lt;/li&gt;
&lt;li&gt;在算法的适当位置运行代码（比如排序的比较操作）&lt;/li&gt;
&lt;li&gt;发生某种事件时才触发代码&lt;/li&gt;
&lt;li&gt;只在必要时才执行代码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;常用的函数式接口：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Runnable
Supplier&amp;lt;T&amp;gt;
Comsumer&amp;lt;T&amp;gt;
BiConsumer&amp;lt;T, U&amp;gt;
Function&amp;lt;T,R&amp;gt;
BiFunction&amp;lt;T, U, R&amp;gt;
UnaryOperator&amp;lt;T&amp;gt;
BynaryOperator&amp;lt;T&amp;gt;
Predicate&amp;lt;T&amp;gt;
BiPredicator&amp;lt;T, U&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;除了&lt;code&gt;Runnable&lt;/code&gt;，它们都在&lt;code&gt;java.util.function&lt;/code&gt;里面&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hello World</title>
      <link>https://bankkase.pages.dev/posts/hello-world/</link>
      <pubDate>Thu, 16 Jul 2026 23:58:25 +0800</pubDate>
      <guid>https://bankkase.pages.dev/posts/hello-world/</guid>
      <description>&lt;p&gt;这是我的第一篇博客！&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
