作为 Java 初学者,掌握面向对象高级特性是提升编程能力的关键一步。本文将系统梳理代码块、内部类、函数式编程(Lambda 与方法引用)及常用 API(String、ArrayList)的核心知识点,结合实例讲解,帮助你快速理解并上手实战。

一、代码块:类的 "初始化利器"

代码块是 Java 类的五大成分之一(成员变量、构造器、方法、代码块、内部类),用于完成类或对象的初始化工作,分为静态代码块实例代码块两类。

1. 静态代码块

  • 格式:使用static {}包裹代码
  • 特点:当类加载时自动执行,且只执行一次(因为类只会加载一次)。
  • 作用:初始化类的静态变量,或执行类级别的预处理操作。

示例

public class Student {

    // 静态变量

    private static String schoolName;

    

    // 静态代码块:初始化静态变量

    static {

        schoolName = "xxx";

        System.out.println("静态代码块执行:初始化学校名称");

    }

}

// 当Student类首次被使用时,静态代码块自动执行

2. 实例代码块

  • 格式:使用{}直接包裹代码(无 static 关键字)
  • 特点:每次创建对象时执行,且执行在构造器之前。
  • 作用:初始化对象的实例变量,与构造器配合完成对象初始化。

示例

public class Student {

    private String name;

    private int age;

    

    // 实例代码块:初始化实例变量

    {

        name = "默认姓名";

        age = 18;

        System.out.println("实例代码块执行:初始化默认信息");

    }

    

    // 构造器

    public Student() {

        System.out.println("构造器执行:创建对象");

    }

}

// 测试

public class Test {

    public static void main(String[] args) {

        Student s1 = new Student(); // 实例代码块先执行,再执行构造器

        Student s2 = new Student(); // 每次创建对象都执行实例代码块

    }

}

二、内部类:类中的 "嵌套结构"

当一个类的内部包含另一个完整的事物,且该事物无需单独设计时,可将其定义为内部类。内部类分为成员内部类局部内部类匿名内部类

1. 成员内部类

定义在类的成员位置(与成员变量、成员方法同级)的内部类,属于外部类的普通成员。

核心特点:
  • 可直接访问外部类的实例成员和静态成员。
  • 如需在内部类中获取外部类对象,使用外部类名.this
创建对象格式:

外部类名.内部类名 对象名 = new 外部类().new 内部类();

示例

// 外部类

public class Car {

    private String brand = "奔驰"; // 外部类实例变量

    

    // 成员内部类

    public class Engine {

        public void start() {

            // 直接访问外部类成员

            System.out.println(brand + "发动机启动");

            // 获取外部类对象

            Car car = Car.this;

            System.out.println("外部类品牌:" + car.brand);

        }

    }

}

// 测试

public class Test {

    public static void main(String[] args) {

        // 创建成员内部类对象

        Car.Engine engine = new Car().new Engine();

        engine.start(); // 输出:奔驰发动机启动  外部类品牌:奔驰

    }

}

2. 局部内部类(了解)

定义在方法、代码块或构造器等执行体中的内部类,作用域仅限于当前执行体,实际开发中使用较少(文档标注为 "鸡肋语法")。

示例

public class Test {

    public void show() {

        // 局部内部类(仅在show()方法中有效)

        class LocalClass {

            public void print() {

                System.out.println("局部内部类方法");

            }

        }

        // 创建局部内部类对象并使用

        new LocalClass().print();

    }

}

3. 匿名内部类:"简化子类对象创建" 的利器

匿名内部类是特殊的局部内部类,无需声明类名,本质是 "继承了某个类或实现了某个接口的子类对象",常用于快速创建子类对象。

核心特点:
  • 格式:new 类或接口(参数...) { 重写方法体 };
  • 立即创建一个子类对象,无类名(隐藏默认名称)。
  • 常用于作为参数传递给方法,简化代码。
实战场景 1:接口实现简化

// 定义接口

public interface Swimming {

    void swim();

}

public class Test {

    // 方法接收Swimming类型参数

    public static void goSwim(Swimming s) {

        s.swim();

    }

    public static void main(String[] args) {

        // 匿名内部类作为参数传递

        goSwim(new Swimming() {

            @Override

            public void swim() {

                System.out.println("学生游泳飞快~");

            }

        });

        goSwim(new Swimming() {

            @Override

            public void swim() {

                System.out.println("老师游泳还行~");

            }

        });

    }

}

实战场景 2:排序逻辑定制

使用Comparator接口的匿名内部类实现数组排序:

import java.util.Arrays;

import java.util.Comparator;

public class Student {

    private String name;

    private int age;

    // 构造器、getter/setter省略

    public Student(String name, int age) {

        this.name = name;

        this.age = age;

    }

    @Override

    public String toString() {

        return "Student{name='" + name + "', age=" + age + "}";

    }

    public static void main(String[] args) {

        Student[] students = {

            new Student("玛卡巴卡", 16),

            new Student("唔西迪西", 12),

            new Student("依古比古", 18)

        };

        // 匿名内部类定义排序规则(按年龄升序)

        Arrays.sort(students, new Comparator<Student>() {

            @Override

            public int compare(Student o1, Student o2) {

                return o1.age - o2.age; // 前-后:升序;后-前:降序

            }

        });

        System.out.println(Arrays.toString(students));

        // 输出:[Student{name='唔西迪西', age=12}, ...]

    }

}

三、函数式编程:Lambda 与方法引用

JDK 8 引入的函数式编程特性,可大幅简化代码,核心是Lambda 表达式方法引用

1. Lambda 表达式:简化匿名内部类

Lambda 表达式用于替代函数式接口的匿名内部类,让代码更简洁。

核心概念:
  • 函数式接口:有且仅有一个抽象方法的接口,可通过@FunctionalInterface注解约束(编译时校验)。
  • Lambda 格式(形参列表) -> { 方法体代码 }
基本使用:简化函数式接口实现

Swimming接口为例,对比匿名内部类与 Lambda:

// 匿名内部类方式

Swimming s1 = new Swimming() {

    @Override

    public void swim() {

        System.out.println("游泳~");

    }

};

// Lambda方式(简化后)

Swimming s2 = () -> {

    System.out.println("游泳~");

};

Lambda 省略规则:
  1. 形参列表的参数类型可省略(编译器自动推断)。
  2. 若形参列表只有一个参数,可省略小括号()
  3. 若方法体只有一行代码,可省略大括号{}和分号;,若有return需一并省略。

示例:简化排序逻辑

// 原匿名内部类排序

Arrays.sort(students, new Comparator<Student>() {

    @Override

    public int compare(Student o1, Student o2) {

        return o1.age - o2.age;

    }

});

// Lambda简化(省略参数类型)

Arrays.sort(students, (o1, o2) -> {

    return o1.age - o2.age;

});

// 进一步简化(单行代码省略{}和return)

Arrays.sort(students, (o1, o2) -> o1.age - o2.age);

2. 方法引用:进一步简化 Lambda

当 Lambda 表达式仅调用一个已存在的方法,且参数传递关系一致时,可使用方法引用进一步简化。

四种引用类型:

类型

格式

使用场景

静态方法引用

类名::静态方法名

Lambda 体仅调用静态方法,参数一致

实例方法引用

对象名::实例方法名

Lambda 体仅调用实例方法,参数一致

特定类型方法引用

类名::实例方法名

第一个参数是方法调用者,其余参数是方法入参

构造器引用

类名::new

Lambda 体仅创建对象,参数与构造器一致

示例:

import java.util.Arrays;

import java.util.Comparator;

// 静态方法引用

class StringUtil {

    public static int compareByLength(String s1, String s2) {

        return s1.length() - s2.length();

    }

}

public class Test {

    public static void main(String[] args) {

        String[] strs = {"apple", "banana", "cat"};

        

        // 静态方法引用:StringUtil::compareByLength

        Arrays.sort(strs, StringUtil::compareByLength);

        System.out.println(Arrays.toString(strs)); // [cat, apple, banana]

        // 特定类型方法引用(String类的compareTo方法)

        Arrays.sort(strs, String::compareTo); // 等价于(s1,s2)->s1.compareTo(s2)

    }

}

四、常用 API 实战:String 与 ArrayList

掌握常用 API 是 Java 开发的基础,这里重点梳理StringArrayList的核心用法。

1. String 类:字符串处理神器

String用于封装字符串数据,提供丰富的字符串处理方法。

创建 String 对象的两种方式:
  • 直接赋值String s = "你好";(推荐,复用常量池对象)。
  • 构造器创建

String s1 = new String(); // 空字符串

String s2 = new String("hello"); // 基于字符串创建

String s3 = new String(new char[]{'a','b','c'}); // 基于字符数组创建

常用方法:

方法名

说明

public int length​()

获取字符串的长度返回(就是字符个数)

public char charAt​(int index)

获取某个索引位置处的字符返回

public char[] toCharArray​()

将当前字符串转换成字符数组返回

public boolean equals(Object anObject

判断当前字符串与另一个字符串的内容一样,一样返回true

public boolean equalsIgnoreCase(String anotherString)

判断当前字符串与另一个字符串的内容是否一样(忽略大小写)

public String substring(int beginIndex, int endIndex

根据开始和结束索引进行截取,得到新的字符串(包前不包后)

public String substring(int beginIndex

从传入的索引处截取,截取到末尾,得到新的字符串返回

public String replace(CharSequence target, CharSequence replacement) 

使用新值,将字符串中的旧值替换,得到新的字符串

public boolean contains(CharSequence s)

判断字符串中是否包含了某个字符串

public boolean startsWith(String prefix)

判断字符串是否以某个字符串内容开头,开头返回true,反之

public String[] split(String regex) 

把字符串按照某个字符串内容分割,并返回字符串数组回来

实战案例:登录功能

import java.util.Scanner;

public class LoginDemo {

    private static final String USERNAME = "admin";

    private static final String PASSWORD = "123456";

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int chance = 3; // 3次登录机会

        while (chance > 0) {

            System.out.println("请输入用户名:");

            String username = sc.next();

            System.out.println("请输入密码:");

            String password = sc.next();

            if (USERNAME.equals(username) && PASSWORD.equals(password)) {

                System.out.println("欢迎进入系统!");

                break;

            } else {

                chance--;

                if (chance > 0) {

                    System.out.println("用户名或密码错误,剩余" + chance + "次机会");

                } else {

                    System.out.println("登录失败,已锁定");

                }

            }

        }

        sc.close();

    }

}

2. ArrayList:动态数组容器

ArrayList是 Java 中最常用的集合类,用于存储动态长度的元素(大小可变,功能丰富)。

核心用法:
  • 创建对象ArrayList<String> list = new ArrayList<>();(泛型指定存储元素类型)。
  • 常用方法

常用方法名

说明

public boolean add(E e)

将指定的元素添加到此集合的末尾

public void add(int index,E element)

在此集合中的指定位置插入指定的元素

public E get(int index)

返回指定索引处的元素

public int size()

返回集合中的元素的个数

public E remove(int index)

删除指定索引处的元素,返回被删除的元素

public boolean remove(Object o)

删除指定的元素,返回删除是否成功

public E set(int index,E element)

修改指定索引处的元素,返回被修改的元素

实战案例:ArrayList 基本操作

import java.util.ArrayList;

public class ArrayListDemo {

    public static void main(String[] args) {

        // 创建存储字符串的集合

        ArrayList<String> list = new ArrayList<>();

        // 添加元素

        list.add("Java");

        list.add("Python");

        list.add("C++");

        System.out.println(list); // [Java, Python, C++]

        // 插入元素

        list.add(1, "JavaScript");

        System.out.println(list); // [Java, JavaScript, Python, C++]

        // 获取元素

        String elem = list.get(2);

        System.out.println("索引2的元素:" + elem); // Python

        // 修改元素

        String old = list.set(3, "Go");

        System.out.println("修改前:" + old + ",修改后:" + list); // [Java, JavaScript, Python, Go]

        // 删除元素

        list.remove(0);

        System.out.println("删除后:" + list); // [JavaScript, Python, Go]

        // 集合大小

        System.out.println("元素个数:" + list.size()); // 3

    }

}

总结

本文梳理了 Java 面向对象高级的核心知识点,包括代码块的初始化逻辑、内部类的分类与应用、函数式编程的 Lambda 与方法引用简化技巧,以及常用 API(String、ArrayList)的实战用法。这些知识点是 Java 开发的基础,建议结合示例代码反复练习,逐步掌握其核心逻辑。

后续可进一步深入学习集合框架其他类(如HashMapLinkedList)和 Stream 流等高级特性,不断提升 Java 编程能力!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐