<?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>Bankkase Blog</title>
    <link>https://bankkase.pages.dev/</link>
    <description>Recent content on Bankkase Blog</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Tue, 21 Jul 2026 20:00:34 +0800</lastBuildDate>
    <atom:link href="https://bankkase.pages.dev/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>甜筒是我的罪过啊</title>
      <link>https://bankkase.pages.dev/posts/%E6%9D%82%E8%B0%88/%E7%94%9C%E7%AD%92%E6%98%AF%E6%88%91%E7%9A%84%E7%BD%AA%E8%BF%87%E5%95%8A/</link>
      <pubDate>Tue, 21 Jul 2026 20:00:34 +0800</pubDate>
      <guid>https://bankkase.pages.dev/posts/%E6%9D%82%E8%B0%88/%E7%94%9C%E7%AD%92%E6%98%AF%E6%88%91%E7%9A%84%E7%BD%AA%E8%BF%87%E5%95%8A/</guid>
      <description>&lt;p&gt;今天吃完饭，去“苦沙火乡”买了一支甜筒。边骑车边吃，哪曾想一下路肩甜筒就被颠断了……&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;灵魂四格漫画&#34; loading=&#34;lazy&#34; src=&#34;https://bankkase.pages.dev/posts/%E6%9D%82%E8%B0%88/%E7%94%9C%E7%AD%92%E6%98%AF%E6%88%91%E7%9A%84%E7%BD%AA%E8%BF%87%E5%95%8A/%E7%94%9C%E7%AD%92%E6%98%AF%E6%88%91%E7%9A%84%E7%BD%AA%E8%BF%87%E5%95%8A.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;哎，太可悲了太可恨了。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;怨我，这就是我的罪孽啊。&lt;/p&gt;</description>
    </item>
    <item>
      <title>异常</title>
      <link>https://bankkase.pages.dev/posts/java/%E5%BC%82%E5%B8%B8/</link>
      <pubDate>Sat, 18 Jul 2026 11:16:20 +0800</pubDate>
      <guid>https://bankkase.pages.dev/posts/java/%E5%BC%82%E5%B8%B8/</guid>
      <description>&lt;h2 id=&#34;异常简介&#34;&gt;异常简介&lt;/h2&gt;
&lt;p&gt;异常是为了在出错的时候，提供一个机制把控制权交给能够处理这个错误的代码手上。如果没有异常，异常产生处和处理处的代码可能很远。&lt;/p&gt;
&lt;p&gt;异常的层次结构：&lt;/p&gt;
&lt;p&gt;基类：Throwable
直接继承Throwable：Error和Exception
Error被设计成虚拟机内部错误，程序员不应该抛出
Exception是我们平常关注的范围。&lt;/p&gt;
&lt;p&gt;IOException和RuntimeException是Exception下的两个常见的直接子类。Exception还有更多直接子类。&lt;/p&gt;
&lt;p&gt;所有派生于Error类或RuntimeException类的异常都是非检查型unchecked异常。
所有其他异常都是检查型checked异常。&lt;/p&gt;
&lt;p&gt;语义上，RuntimeException指的是编程错误导致的异常，如&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ArrayIndexOutOfBoundsException&lt;/li&gt;
&lt;li&gt;NullPointerException&lt;/li&gt;
&lt;li&gt;ClassCastException&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;创建异常类&#34;&gt;创建异常类&lt;/h3&gt;
&lt;p&gt;我们需要继承一个Exception的子类。同时惯例我们应该实现两个构造器：一个无参和一个带详细信息字符串的构造器。&lt;/p&gt;
&lt;h2 id=&#34;异常的捕获和传播&#34;&gt;异常的捕获和传播&lt;/h2&gt;
&lt;p&gt;要捕获异常，需要建立一个try-catch块。
如果在try块中遇到catch指定的异常，那么直接跳到对应catch语句块。
预估遇到catch未指定的异常，那么方法直接退出。
如果try块正常运行，那么不运行catch块，继续运行方法的后续代码。&lt;/p&gt;
&lt;p&gt;如何判断处理还是传递异常？
在工程实践中，推荐遵循**尽早抛出，延迟捕获（Throw early, catch late）**的原则：
在代码最底层的逻辑验证阶段，一旦检测到异常状态立即抛出；在整个调用链路中，除非能够真正处理问题或必须转译异常，否则应一路放行，交由拥有全局业务视野的顶层框架或统一异常处理器（如 Spring 的 @ExceptionHandler）进行集中处理。&lt;/p&gt;
&lt;h2 id=&#34;finnally和try-with-resources&#34;&gt;finnally和try-with-resources&lt;/h2&gt;
&lt;p&gt;finally子句：无论是否排除是否被捕获的异常，都会在最后执行。
可以只有finally没有catch&lt;/p&gt;
&lt;p&gt;不要在finally中使用&lt;code&gt;throw&lt;/code&gt;, &lt;code&gt;return&lt;/code&gt;, &lt;code&gt;break&lt;/code&gt;, &lt;code&gt;continue&lt;/code&gt;等改变控制流的语句。
一个良好的实践是使用两个独立的try，try-finally用于关闭资源，try-catch用于处理异常。&lt;/p&gt;
&lt;p&gt;java7以上支持try-with-resources&lt;/p&gt;
&lt;p&gt;对于实现了AutoClosable接口：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AutoClosable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt; Exception
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;的类（资源），try-with-resources语法会在try块结束后自动关闭这些资源。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; (Resource res &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ...) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; with res.....
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#75715e&#34;&gt;// 不管有没有异常，是否被捕获，都会在这里调用res.close()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; (Exception e) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;java9之后，可以提供effectively final的变量了：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// out 是方法的参数，满足effectively final
try (out) {
  // do sth
} // out.close
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;没什么人在意的细节：在try-with-resources中，如果try块和close都抛出了异常，close抛出的异常会被抑制。它们被用addSuppressed方法加到try抛的异常上，然后重新抛出try抛出的异常。如果你感兴趣，可以使用getSuppressed方法获取这些异常。&lt;/p&gt;</description>
    </item>
    <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>
