视频加载失败

Java 基础 Day03:代码块、内部类、Lambda 与方法引用

1245 字
6 分钟
Java 基础 Day03:代码块、内部类、Lambda 与方法引用

代码块#

静态代码块#

  • 写法:static { ... },类加载时执行一次,优先于 main
  • 用途:初始化静态资源(连接、配置等)
  • 执行顺序:静态代码块 → main
static {
System.out.println("静态代码块"); // 先打印
}
public static void main(String[] args) {
System.out.println("main"); // 后打印
}

实例代码块#

  • 写法:{ ... },每次 new 对象时执行,跟着对象走
  • 用途:初始化实例资源(给成员变量赋初始值)
  • 特点:不 new 不执行(main 里只有 new Codedemo2() 才触发)
类型写法执行时机用途
静态代码块static {}类加载,一次初始化静态资源
实例代码块{}每次 new初始化实例资源

内部类#

成员内部类#

  • 格式:外部类里直接定义的类
Outer.Inner o1 = new Outer().new Inner(); // 先 new 外部类,再 new 内部类
o1.show();
  • 成员内部类可以直接访问外部类的静态成员和实例成员(如 Outer 的 name1)

匿名内部类#

  • 本质:一个没有类名的子类/实现类,new 父类/接口() { 重写方法 }
Animal a = new Animal() { // Animal 是抽象类
@Override
public void cry() {
System.out.println("叫");
}
};
  • 作为对象参数传给方法:老师/学生都要参加游泳时,不再建 Teacher/Student 类,直接两个匿名对象传进 start(Swim s):
Swim s1 = new Swim() { // 老师版
@Override public void swim() { System.out.println("老师快速游泳"); }
};
start(s1); // 一个方法,两份实现,不用写子类
  • GUI 事件监听:jb.addActionListener(new ActionListener() {...})——Swing 按钮监听器的经典写法,Swing/Android 里到处是这个模式

Lambda 表达式#

  • 函数式接口 @FunctionalInterface:只能有一个抽象方法的接口,才能被 Lambda 简化
@FunctionalInterface
interface Swim {
void swim();
}
  • Lambda 就是简化”函数式接口”的匿名内部类(抽象类不能简化,只有接口可以)
// 匿名内部类写法
Swim s1 = new Swim() {
@Override public void swim() { System.out.println("游泳快"); }
};
// Lambda 写法
Swim s2 = () -> { System.out.println("游泳快"); };
  • 简写规则(记忆口诀):
    1. 参数类型全都可以不写
    2. 一个参数可以省略括号
    3. 一行代码可以去掉大括号和 return

方法引用#

Lambda 的进一步缩写:当 Lambda 体只是”调用一个现成的方法”时,可以直接用 ::

类型写法例子对应 Lambda
静态方法引用类名::方法名MathUtil::add(a,b) -> MathUtil.add(a,b)
实例方法引用对象名::方法名util::add(a,b) -> util.add(a,b)
特定类型方法引用类型::实例方法String::compareToIgnoreCase(s1,s2) -> s1.compareToIgnoreCase(s2)
构造器引用类名::newStudent::new(name,age) -> new Student(name,age)
  • 前提:函数式接口抽象方法的参数列表与引用的方法/构造器一致
  • 实战例子:给英文字符串数组忽略大小写排序
Arrays.sort(names, String::compareToIgnoreCase);
  • 构造器引用 Student::new:抽象方法 build(String,int) 的参数正好对应 Student(String,int) 构造器

String 入门#

  • 创建字符串两种方式:
    1. 双引号:String s1 = "hello";——本质也调用 new String(...)
    2. 构造器:String s2 = new String();——空字符串 ""
  • String 的不可变性、常量池、常用 API 在这一天只起了头,留待后续深入

ArrayList 基本使用#

  • 泛型集合:ArrayList<String> list = new ArrayList<>();
  • 基本 CRUD(增删改查):增删查在前面的博客实战中已经用过,这次系统地过一遍
  • System.out.println(list) 直接打印整个列表内容

博客实战复盘:排序与数据预置#

控制台博客项目继续演进,这一天落地的两步是排序(Comparator)和预置数据,正好用上代码块、Lambda 与方法引用。

排序:Comparator 三种写法演进#

给文章列表按发布时间倒序,从最原始的写法到最终形态:

// 写法1 匿名内部类(内部类知识)
articles.sort(new Comparator<Article>() {
@Override public int compare(Article o1, Article o2) {
return o1.getCreateTime().compareTo(o2.getCreateTime());
}
});
// 写法2 Lambda(函数式接口被简化)
articles.sort((o1, o2) -> o1.getCreateTime().compareTo(o2.getCreateTime()));
// 写法3 方法引用(最终形态,项目里实际使用的)
articles.sort(Comparator.comparing(Article::getCreateTime).reversed());
  • Comparator.comparing(Article::getCreateTime) = 「按哪个字段排」+ 方法引用取字段
  • .reversed() = 倒序(最新在前)
  • 巧用:createTime 格式为 yyyy-MM-dd HH:mm:ss,String 字典序 = 时间序

实例代码块预置数据#

private final ArrayList<Article> articles = new ArrayList<>();
// 实例代码块:对象创建时执行。单例只 new 一次 → 恰好预置一次
{
Article a1 = new Article("Java 入门", "第一篇", "rk");
a1.setId(nextId++); // 不走 save(),要手动分配 id + 同步自增
articles.add(a1);
// ...
}
  • 为什么用实例代码块而不是静态代码块:静态代码块不能访问实例字段(articles),实例代码块可以——正好对应实例代码块给实例字段赋初值的用途
  • 为什么恰好预置一次:Repository 是单例,只 new 一次,代码块跟着对象走
  • id 撞车坑:预置数据要手动 setId(nextId++),否则用户新发的文章 id 会和示例文章重复

String 落点#

  • validateInput 用 title.trim().isEmpty() 判空——trim 去首尾空格、isEmpty 判空串,String 基础的直接应用

Stream API 还没学到——排序用 Comparator.comparing 已是函数式写法,之后学了 Stream,filter/map/sorted 会更省代码。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

打赏
Java 基础 Day03:代码块、内部类、Lambda 与方法引用
https://ryuki.icu/posts/java-basics-day03/
作者
RK
发布于
2026-08-05
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
RK
Long may the sunshine
公告
Long may the sunshine
分类
标签
最新动态
站点天气
天气加载中…
站点统计
文章
27
分类
6
标签
59
总字数
39,139
篝火已燃
0 天
最后活动
0 天前
每日一签