虽然我不能直接提供整本书的代码(这涉及版权),但我可以为您提供 书中核心概念的代码示例,这些示例完美地体现了 "Thinking in Java" 的教学思想,我会按照书的章节结构来组织这些示例,并附上详细的解释。

一切都是对象
这是 TIJ 的核心思想,Java 是一种面向对象的语言,程序的基本构建块是对象,理解对象是第一步。
示例:HelloDate.java
这个简单的程序展示了如何创建一个对象(Date)并调用其方法。
import java.util.Date; // 1. 引入 Date 类所在的包
/**
* 第一个 Thinking in Java 风格的示例。
* 展示了如何创建对象并调用其方法。
* @author Your Name
*/
public class HelloDate {
/**
* 程序的入口点。
* @param args 命令行参数(本例中未使用)
*/
public static void main(String[] args) {
// 2. 创建一个 Date 对象(实例化)
// new 关键字在堆上为对象分配内存
Date date = new Date();
// 3. 调用对象的 toString() 方法(隐式调用)
// 并使用 System.out.println 将结果打印到控制台
System.out.println("Hello, it is: " + date);
// 4. 显式调用 toString() 方法,效果与上面相同
System.out.println("Explicit call: " + date.toString());
}
}
TIJ 思想解析:
import: 告诉编译器去哪里寻找Date类的定义,这是使用“工具箱”(库)中对象的前提。new: 这是创建对象的唯一方式,它在内存中为对象分配空间,并调用构造函数来初始化对象。- (点操作符): 用于访问对象的成员(方法或字段)。
date.toString()的意思是“在date这个对象上,执行toString方法”。 System.out.println: 它本身就是一个对象,我们调用了它的println方法来打印信息。
控制执行流程
控制流决定了代码的执行顺序,包括 if-else、for、while、switch 等。

示例:Fibonacci.java
使用 for 循环来计算斐波那契数列,展示了循环和变量的使用。
/**
* 演示 for 循环和变量。
* 计算并打印斐波那契数列的前 N 个数。
*/
public class Fibonacci {
public static void main(String[] args) {
int n = 10; // 我们想计算前10个数
int[] fib = new int[n]; // 创建一个数组来存储结果
// 初始化前两个数
fib[0] = 1;
fib[1] = 1;
// 使用 for 循环计算后续的数
// 从第3个位置(索引2)开始,直到数组末尾
for (int i = 2; i < n; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
// 打印结果
System.out.println("The first " + n + " Fibonacci numbers are:");
for (int i = 0; i < n; i++) {
System.out.print(fib[i] + " ");
}
}
}
TIJ 思想解析:
- 初始化:
int n = 10;和fib[0] = 1;是任何计算程序的第一步,明确地设置初始状态。 - 循环:
for循环是执行重复任务最清晰、最常用的方式,循环的三个部分(初始化、条件、迭代)写在一起,非常直观。 - 状态管理:
fib[i]的值依赖于前两个计算结果,这体现了编程中“基于之前的结果计算当前结果”的常见模式。
初始化与清理
对象创建后需要初始化,不再需要时需要被清理(垃圾回收),这是资源管理的核心。
示例:SimpleConstructor.java
展示构造函数如何用于对象的初始化。

/**
* 一个简单的类,其构造函数用于打印信息,
* 以证明对象在创建时确实被初始化了。
*/
class Rock {
// Rock 类的构造函数
// 当创建 Rock 对象时,这个方法会自动被调用
public Rock(int i) {
System.out.println("Creating Rock number " + i);
}
}
public class SimpleConstructor {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
// new Rock(i) 会触发 Rock 的构造函数
new Rock(i);
}
}
}
TIJ 思想解析:
- 构造函数: 它的方法名与类名完全相同,没有返回类型,它的唯一目的就是在创建对象时进行初始化,这是保证对象处于有效、可用状态的关键。
new的副作用:new Rock(i)这行代码做了两件事:1. 在堆上分配内存;2. 调用Rock的构造函数来填充这块内存。
访问权限控制
封装是面向对象的四大特性之一,通过 public, private, protected 等修饰符控制对类成员的访问,是实现封装的基础。
示例:Cookie.java
展示了 private 如何保护类的内部状态。
/**
* 演示封装和访问权限控制。
* Cookie 类的内部数据(如 i)是私有的,外部无法直接访问。
*/
class Cookie {
// 私有变量,只能在 Cookie 类内部访问
private int i = 5;
// 公有方法,是外部世界与这个类交互的唯一合法途径
public void bite() {
i--;
}
// 提供一个 "getter" 方法来查看私有变量的值
public int getI() {
return i;
}
}
public class Cookie {
public static void main(String[] args) {
Cookie x = new Cookie();
// x.i = 9; // 错误!i 是私有的,外部不能直接修改它。
x.bite(); // 正确!通过公有方法来操作内部状态。
System.out.println("Value of i is: " + x.getI());
}
}
TIJ 思想解析:
private: 它像一道墙,将类的内部实现细节与外部使用者隔离开来,这防止了外部代码意外地或恶意地破坏对象的状态。- 公有方法:
bite()和getI()是类的“公共接口”,使用者通过调用这些方法来请求对象执行某些操作或提供某些信息,而不需要知道这些操作是如何实现的。 - 封装的好处: 当你决定修改
i的存储方式(比如用一个 String 代替)时,只要保证bite()和getI()的行为不变,所有使用这个类的代码都不需要修改。
复用类
代码复用是提高效率和质量的关键,Java 提供了两种主要方式:组合和继承。
示例:Bath.java (组合)
组合意味着在新类中创建一个现有类的对象。
import java.io.*;
/**
* 演示“组合”。
* Bath 类由其他几个更简单的对象(如 Soap, Towel)组合而成。
*/
public class Bath {
// 在类的内部声明其他类的对象引用
private String // 初始化是在定义处完成的
s1 = "Happy",
s2 = "Happy",
s3, s4;
private Soap castille;
private int i;
private float toy;
// 构造函数是进行复杂初始化的好地方
public Bath() {
System.out.println("Inside Bath()");
s3 = "Joy";
toy = 3.14f;
castille = new Soap();
}
// 实例初始化块,在构造函数调用期间执行
{ i = 47; }
public String toString() {
if (s4 == null) // 延迟初始化
s4 = "Joy";
return
"s1 = " + s1 + "\n" +
"s2 = " + s2 + "\n" +
"s3 = " + s3 + "\n" +
"s4 = " + s4 + "\n" +
"i = " + i + "\n" +
"toy = " + toy + "\n" +
"castille = " + castille;
}
public static void main(String[] args) {
Bath b = new Bath();
System.out.println(b); 