目录 🔗 16 内部类与常用API 📑 目录 16.1 内部类概述 16.2 成员内部类 16.2.1 定义与使用 16.2.2 创建成员内部类对象 16.2.3 特点 16.3 静态内部类 16.3.1 定义与使用 16.3.2 创建静态内部类对象 16.3.3 特点 16.4 局部内部类 16.5 匿名内部类 16.5.1 什么是匿名内部类 16.5.2 语法 16.5.3 基于接口的匿名内部类 16.5.4 基于抽象类的匿名内部类 16.5.5 匿名内部类作为方法参数 16.5.6 实际应用场景 16.6 String类 16.6.1 String的不可变性 16.6.2 字符串比较 16.6.3 常用方法速查表 16.6.4 常见操作示例 16.7 StringBuilder类 16.7.1 为什么需要StringBuilder 16.7.2 StringBuilder vs String vs StringBuffer 16.7.3 常用方法 16.7.4 链式调用 16.7.5 实际应用 16.8 包装类 16.8.1 什么是包装类 16.8.2 装箱与拆箱 16.8.3 常用方法 16.8.4 Integer缓存池 16.8.5 字符串与基本类型转换 16.9 本章总结 💬 互动时间 📚 参考资料 🔗 16 内部类与常用API 更新日期 :2026年5月版权声明 :本文为原创内容,转载请注明出处。系列 :Java入门到精通系列 · 第二阶段 · 面向对象
📑 目录 16.1 内部类概述 16.2 成员内部类 16.3 静态内部类 16.4 局部内部类 16.5 匿名内部类 16.6 String类 16.7 StringBuilder类 16.8 包装类 16.9 本章总结 16.1 内部类概述 内部类 是定义在另一个类内部 的类。Java中有四种内部类:
类型 定义位置 使用频率 成员内部类 类中,方法外 ⭐⭐ 静态内部类 类中,用static修饰 ⭐⭐⭐ 局部内部类 方法内部 ⭐ 匿名内部类 方法内或表达式中 ⭐⭐⭐⭐⭐
16.2 成员内部类 16.2.1 定义与使用 public class Outer { private int num= 10 ; private String name= "外部类" ; // 成员内部类 public class Inner { private int num= 20 ; public void show ( ) { int num= 30 ; System . out. println ( num) ; // 30(局部变量) System . out. println ( this . num) ; // 20(内部类成员变量) System . out. println ( Outer . this . num) ; // 10(外部类成员变量) System . out. println ( name) ; // 直接访问外部类成员 } } } 16.2.2 创建成员内部类对象 public class InnerClassDemo { public static void main ( String [ ] args) { Outer outer= new Outer ( ) ; // 语法:外部类对象.new 内部类() Outer. Inner inner= outer. new Inner ( ) ; inner. show ( ) ; } } 16.2.3 特点 特点 说明 可以访问外部类所有成员 包括private 需要外部类对象才能创建 outer.new Inner()不能有static成员 JDK16之前
16.3 静态内部类 16.3.1 定义与使用 public class Outer { private static int num= 10 ; private String name= "外部类" ; // 静态内部类 public static class StaticInner { public void show ( ) { System . out. println ( num) ; // 可以访问外部类的静态成员 // System.out.println(name); // ❌ 不能访问非静态成员 } } } 16.3.2 创建静态内部类对象 // 不需要外部类对象 Outer. StaticInner inner= new Outer. StaticInner ( ) ; inner. show ( ) ; 16.3.3 特点 特点 说明 用static修饰 不依赖外部类实例 只能访问外部类静态成员 不能访问非静态成员 创建不需要外部类对象 new Outer.StaticInner()可以有static成员 ✅
16.4 局部内部类 16.4.1 定义与使用 public class Outer { public void method ( ) { // 局部内部类:定义在方法内部 class LocalInner { private int num= 100 ; public void show ( ) { System . out. println ( "局部内部类:" + num) ; } } // 在方法内使用 LocalInner inner= new LocalInner ( ) ; inner. show ( ) ; } } 16.4.2 特点 只在方法内部可见和使用 可以访问外部类的成员 可以访问方法中的final 或effectively final 局部变量 public void method ( ) { final int x= 10 ; // 必须是final或effectively final class LocalInner { public void show ( ) { System . out. println ( x) ; // ✅ // x = 20; // ❌ 不能修改 } } } 16.5 匿名内部类 16.5.1 什么是匿名内部类 匿名内部类 是内部类的简写形式,没有类名,常用于只需要使用一次的场景。
16.5.2 语法 new 接口名/ 类名( ) { // 重写方法 } ; 16.5.3 基于接口的匿名内部类 public interface Animal { void speak ( ) ; } public class AnonymDemo { public static void main ( String [ ] args) { // 传统写法:定义一个实现类 // 匿名内部类写法: Animal dog= new Animal ( ) { @Override public void speak ( ) { System . out. println ( "汪汪汪!" ) ; } } ; Animal cat= new Animal ( ) { @Override public void speak ( ) { System . out. println ( "喵喵喵~" ) ; } } ; dog. speak ( ) ; // 汪汪汪! cat. speak ( ) ; // 喵喵喵~ } } 16.5.4 基于抽象类的匿名内部类 public abstract class Greeting { public abstract void greet ( String name) ; } Greeting hello= new Greeting ( ) { @Override public void greet ( String name) { System . out. println ( "你好," + name+ "!" ) ; } } ; hello. greet ( "张三" ) ; // 你好,张三! 16.5.5 匿名内部类作为方法参数 public class Demo { public static void main ( String [ ] args) { // 直接传入匿名内部类 useAnimal ( new Animal ( ) { @Override public void speak ( ) { System . out. println ( "嘎嘎嘎!" ) ; } } ) ; } public static void useAnimal ( Animal a) { a. speak ( ) ; } } 16.5.6 实际应用场景 // 排序中的匿名内部类 Collections . sort ( names, new Comparator < String > ( ) { @Override public int compare ( String s1, String s2) { return s1. length ( ) - s2. length ( ) ; } } ) ; // 线程中的匿名内部类 Thread t= new Thread ( new Runnable ( ) { @Override public void run ( ) { System . out. println ( "子线程执行中..." ) ; } } ) ; t. start ( ) ; 16.6 String类 16.6.1 String的不可变性 String s= "Hello" ; s= s+ " World" ; // 原来的"Hello"没有改变,而是创建了新对象"Hello World" 特性 说明 不可变 字符串内容一旦创建不能修改 字符串常量池 相同字面量共享同一对象 final类 不能被继承
16.6.2 字符串比较 String s1= "Hello" ; String s2= "Hello" ; String s3= new String ( "Hello" ) ; System . out. println ( s1== s2) ; // true(常量池同一对象) System . out. println ( s1== s3) ; // false(堆中不同对象) System . out. println ( s1. equals ( s3) ) ; // true(内容相同) 📌永远用equals()比较字符串内容,不要用==!
16.6.3 常用方法速查表 方法 说明 示例 length()长度 "Hello".length()→ 5charAt(int)获取指定位置字符 "Hello".charAt(1)→ ‘e’substring(int)截取子串 "Hello".substring(2)→ “llo”substring(int,int)截取范围 "Hello".substring(1,3)→ “el”indexOf(String)查找位置 "Hello".indexOf("ll")→ 2contains(String)是否包含 "Hello".contains("ell")→ truestartsWith(String)是否以…开头 "Hello".startsWith("He")→ trueendsWith(String)是否以…结尾 "Hello".endsWith("lo")→ trueisEmpty()是否为空 "".isEmpty()→ trueisBlank()是否为空白 " ".isBlank()→ true (JDK11+)toUpperCase()转大写 "Hello".toUpperCase()→ “HELLO”toLowerCase()转小写 "Hello".toLowerCase()→ “hello”trim()去除两端空格 " Hi ".trim()→ “Hi”replace(a,b)替换 "Hello".replace("l","L")→ “HeLLo”split(String)分割 "a,b,c".split(",")→ [“a”,“b”,“c”]toCharArray()转字符数组 "Hello".toCharArray()valueOf()转字符串 String.valueOf(123)→ “123”equals()内容比较 s1.equals(s2)equalsIgnoreCase()忽略大小写比较 "HI".equalsIgnoreCase("hi")→ true
16.6.4 常见操作示例 public class StringDemo { public static void main ( String [ ] args) { String str= "Hello, World! Hello, Java!" ; // 统计某个字符出现次数 int count= 0 ; for ( int i= 0 ; i< str. length ( ) ; i++ ) { if ( str. charAt ( i) == 'H' ) count++ ; } System . out. println ( "H出现了" + count+ "次" ) ; // 2 // 反转字符串 String reversed= new StringBuilder ( str) . reverse ( ) . toString ( ) ; System . out. println ( reversed) ; // 判断回文 String palindrome= "abcba" ; String rev= new StringBuilder ( palindrome) . reverse ( ) . toString ( ) ; System . out. println ( palindrome. equals ( rev) ) ; // true // 分割字符串 String csv= "张三,20,男,计算机" ; String [ ] parts= csv. split ( "," ) ; for ( String part: parts) { System . out. println ( part) ; } } } 16.7 StringBuilder类 16.7.1 为什么需要StringBuilder // String拼接的问题 String s= "" ; for ( int i= 0 ; i< 10000 ; i++ ) { s+= "a" ; // 每次拼接都创建新对象,性能极差! } // StringBuilder拼接 StringBuilder sb= new StringBuilder ( ) ; for ( int i= 0 ; i< 10000 ; i++ ) { sb. append ( "a" ) ; // 在同一个对象上操作,性能好 } String result= sb. toString ( ) ; 16.7.2 StringBuilder vs String vs StringBuffer 对比 String StringBuilder StringBuffer 可变性 不可变 可变 可变 线程安全 ✅(不可变) ❌ ✅(synchronized) 性能 拼接慢 最快 较快 使用场景 少量操作 单线程大量操作 多线程大量操作
16.7.3 常用方法 方法 说明 返回值 append(任意类型)追加内容 StringBuilder insert(int, 任意类型)在指定位置插入 StringBuilder delete(int, int)删除范围 StringBuilder deleteCharAt(int)删除指定位置 StringBuilder replace(int, int, String)替换范围 StringBuilder reverse()反转 StringBuilder toString()转为String String length()长度 int capacity()容量 int
16.7.4 链式调用 String result= new StringBuilder ( ) . append ( "Hello" ) . append ( ", " ) . append ( "World" ) . append ( "!" ) . toString ( ) ; System . out. println ( result) ; // Hello, World! 16.7.5 实际应用 // 拼接数组为字符串 public static String join ( int [ ] arr, String separator) { StringBuilder sb= new StringBuilder ( ) ; for ( int i= 0 ; i< arr. length; i++ ) { sb. append ( arr[ i] ) ; if ( i< arr. length- 1 ) { sb. append ( separator) ; } } return sb. toString ( ) ; } // 使用示例 System . out. println ( join ( new int [ ] { 1 , 2 , 3 , 4 , 5 } , "-" ) ) ; // 输出:1-2-3-4-5 16.8 包装类 16.8.1 什么是包装类 Java为8种基本类型提供了对应的引用类型 (包装类),使得基本类型也能面向对象。
基本类型 包装类 byteByteshortShortintIntegerlongLongfloatFloatdoubleDoublecharCharacterbooleanBoolean
16.8.2 装箱与拆箱 // 装箱:基本类型 → 包装类 Integer i1= Integer . valueOf ( 100 ) ; // 手动装箱 Integer i2= 100 ; // 自动装箱(JDK5+) // 拆箱:包装类 → 基本类型 int n1= i1. intValue ( ) ; // 手动拆箱 int n2= i1; // 自动拆箱(JDK5+) 16.8.3 常用方法 方法 说明 示例 parseInt(String)字符串转int Integer.parseInt("123")→ 123parseDouble(String)字符串转double Double.parseDouble("3.14")valueOf(String)字符串转包装类 Integer.valueOf("123")toString()转字符串 Integer.toString(123)→ “123”MAX_VALUE最大值 Integer.MAX_VALUE→ 2147483647MIN_VALUE最小值 Integer.MIN_VALUE→ -2147483648
16.8.4 Integer缓存池 Integer a= 127 ; Integer b= 127 ; System . out. println ( a== b) ; // true(缓存池,-128~127) Integer c= 128 ; Integer d= 128 ; System . out. println ( c== d) ; // false(超出缓存范围,新对象) System . out. println ( c. equals ( d) ) ; // true 📌包装类比较一律用equals(),不要用==!
16.8.5 字符串与基本类型转换 String → int: Integer.parseInt("123") String → double: Double.parseDouble("3.14") String → boolean: Boolean.parseBoolean("true") int → String: String.valueOf(123) 或 "" + 123 或 Integer.toString(123) double → String: String.valueOf(3.14)public class TypeConvertDemo { public static void main ( String [ ] args) { // 字符串转基本类型 int age= Integer . parseInt ( "25" ) ; double price= Double . parseDouble ( "99.9" ) ; boolean flag= Boolean . parseBoolean ( "true" ) ; // 基本类型转字符串 String ageStr= String . valueOf ( age) ; String priceStr= String . valueOf ( price) ; System . out. println ( age+ 1 ) ; // 26(数学运算) System . out. println ( ageStr+ 1 ) ; // 251(字符串拼接) // 异常处理 try { int num= Integer . parseInt ( "abc" ) ; } catch ( NumberFormatException e) { System . out. println ( "格式错误,无法转换!" ) ; } } } 16.9 本章总结 知识回顾 知识点 核心内容 成员内部类 定义在类中,可访问外部类所有成员 静态内部类 static修饰,不依赖外部类实例 局部内部类 定义在方法中,只在方法内可见 匿名内部类 没有名字,一次性使用,最常用 String 不可变,用equals比较 StringBuilder 可变,高性能拼接 包装类 基本类型的面向对象版本,自动装箱拆箱
练习题 统计一个字符串中大写字母、小写字母、数字和其他字符的个数。 使用StringBuilder将一个字符串反转,并判断是否为回文。 将一个字符串中的数字提取出来,求和。 💬 互动时间 匿名内部类在实际开发中有哪些应用? String为什么设计为不可变的? 📢下篇预告 :[17-常用工具类] —— 学习Math、Arrays、Collections和日期时间API!
📚 参考资料 Oracle Java 官方文档 - Inner Classes Oracle Java 官方文档 - String 《Effective Java》第3版,第6、11条