《Java程序设计基础》实验指导手册
实验总体目标
本系列实验旨在帮助学生掌握Java语言的核心语法、面向对象编程思想、常用API的使用以及基本的程序调试能力,通过动手实践,培养学生分析问题、设计算法、编写代码和调试程序的综合能力,为后续更高级的Java开发和软件工程课程打下坚实的基础。

实验环境准备
- 操作系统: Windows 10/11, macOS, 或 Linux
- Java Development Kit (JDK): 推荐 JDK 8 或更高版本 (如 JDK 11, JDK 17 LTS),确保
JAVA_HOME环境变量配置正确,bin目录已添加到系统的PATH环境变量中。 - 集成开发环境:
- 推荐: IntelliJ IDEA (社区版免费,功能强大)
- 备选: Eclipse IDE for Java Developers, VS Code (配合Java扩展包)
Java开发环境搭建与第一个Java程序
实验目的
- 掌握JDK的下载、安装和环境变量配置。
- 熟悉IntelliJ IDEA (或Eclipse) 的安装和基本配置。
- 掌握编写、编译、运行Java程序的基本流程。
- 理解
HelloWorld程序的结构,并能解释其每个部分的作用。
与步骤
-
安装JDK并配置环境变量
- 访问Oracle官网或OpenJDK官网下载对应操作系统的JDK安装包。
- 运行安装程序,记住安装路径(
C:\Program Files\Java\jdk-17)。 - 配置系统环境变量:
- 新建系统变量
JAVA_HOME,值为JDK的安装路径。 - 编辑系统变量
Path,新建一项%JAVA_HOME%\bin。
- 新建系统变量
- 打开命令提示符,输入
java -version和javac -version,验证安装是否成功。
-
创建第一个Java项目
- 打开IntelliJ IDEA。
- 选择
File -> New -> Project。 - 选择
Java,确保Project SDK已选择你安装的JDK版本。 - 点击
Create。
-
编写
HelloWorld代码- 在左侧项目结构中,找到
src文件夹。 - 右键
src->New -> Java Class,创建一个名为HelloWorld的类。 - 在
HelloWorld.java文件中输入以下代码:
public class HelloWorld { // main方法是Java程序的入口 public static void main(String[] args) { // System.out.println() 用于在控制台输出一行文本 System.out.println("Hello, World!"); } } - 在左侧项目结构中,找到
-
编译并运行程序
(图片来源网络,侵删)- 点击工具栏上的绿色三角 "Run" 按钮。
- 观察下方的 "Run" 窗口,应能看到输出
Hello, World!。 - (可选)尝试使用命令行编译和运行:
- 打开命令提示符,进入到
HelloWorld.java文件所在的目录。 - 输入
javac HelloWorld.java进行编译,会生成HelloWorld.class文件。 - 输入
java HelloWorld运行程序,注意不要加.class后缀。
- 打开命令提示符,进入到
实验报告要求
- 描述JDK安装和环境变量配置的详细步骤,并附上配置成功的截图。
- 附上
HelloWorld.java的源代码。 - 解释
public class HelloWorld、public static void main(String[] args)和System.out.println("Hello, World!");这三行代码的含义。
思考题
- 为什么
public static void main(String[] args)是Java程序的入口? - 如果将
class HelloWorld改为class helloWorld,程序还能运行吗?为什么? javac和java命令分别有什么作用?
Java基本语法与数据类型
实验目的
- 掌握Java基本数据类型(
int,double,char,boolean等)的使用。 - 掌握变量、常量的声明和赋值。
- 掌握算术运算符、关系运算符、逻辑运算符的使用。
- 掌握
Scanner类实现基本的键盘输入。
与步骤
-
创建
BasicSyntax类,完成以下任务:- 声明不同类型的变量并赋值。
- 进行算术运算(加减乘除、取余、自增自减)并输出结果。
- 进行关系运算(大于、小于、等于)和逻辑运算(与、或、非)并输出结果。
- 使用
Scanner从键盘读取一个整数和一个字符串,并输出。
-
参考代码
import java.util.Scanner; // 导入Scanner类 public class BasicSyntax { public static void main(String[] args) { // 1. 基本数据类型和变量 int age = 20; double price = 99.99; char grade = 'A'; boolean isStudent = true; String name = "张三"; System.out.println("姓名: " + name); System.out.println("年龄: " + age); System.out.println("价格: " + price); System.out.println("等级: " + grade); System.out.println("是否是学生: " + isStudent); // 2. 算术运算符 int a = 10, b = 3; System.out.println("\n算术运算:"); System.out.println(a + " + " + b + " = " + (a + b)); System.out.println(a + " - " + b + " = " + (a - b)); System.out.println(a + " * " + b + " = " + (a * b)); System.out.println(a + " / " + b + " = " + (a / b)); // 整数除法 System.out.println(a + " % " + b + " = " + (a % b)); // 取余 // 3. 关系和逻辑运算符 System.out.println("\n关系和逻辑运算:"); System.out.println(a + " > " + b + " 是 " + (a > b)); System.out.println("isStudent && age > 18 是 " + (isStudent && age > 18)); System.out.println("isStudent || age < 18 是 " + (isStudent || age < 18)); System.out.println("!isStudent 是 " + !isStudent); // 4. 使用Scanner进行键盘输入 Scanner scanner = new Scanner(System.in); System.out.println("\n请输入你的年龄: "); int inputAge = scanner.nextInt(); // 读取整数 System.out.println("请输入你的城市: "); String inputCity = scanner.next(); // 读取字符串 System.out.println("你输入的年龄是: " + inputAge + ", 城市是: " + inputCity); scanner.close(); // 关闭Scanner,释放资源 } }
实验报告要求
- 附上
BasicSyntax.java的完整源代码。 - 运行程序,截图展示程序运行结果。
- 写出
int和double在进行混合运算时的类型转换规则。
思考题
Scanner使用完后为什么要调用close()方法?a++和++a有什么区别?- 如何将一个
String类型的数字(如 "123")转换为一个int类型的数字?
流程控制语句
实验目的
- 掌握
if-else条件语句的使用。 - 掌握
switch多分支语句的使用。 - 掌握
for,while,do-while三种循环语句的使用。 - 理解
break和continue在循环中的作用。
与步骤
-
任务1:成绩等级判断
- 创建
GradeEvaluator类。 - 使用
Scanner读取一个学生的百分制成绩。 - 使用
if-else if-else结构判断成绩等级(90-100为A,80-89为B,70-79为C,60-69为D,60以下为E)并输出。
- 创建
-
任务2:简单的计算器
(图片来源网络,侵删)- 创建
SimpleCalculator类。 - 使用
Scanner读取两个数字和一个运算符(, , , )。 - 使用
switch语句根据运算符执行相应的计算并输出结果。
- 创建
-
任务3:打印九九乘法表
- 创建
MultiplicationTable类。 - 使用嵌套的
for循环打印标准的九九乘法表。
- 创建
-
参考代码(部分)
// GradeEvaluator.java import java.util.Scanner; public class GradeEvaluator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入成绩 (0-100): "); int score = scanner.nextInt(); if (score >= 90 && score <= 100) { System.out.println("等级: A"); } else if (score >= 80 && score < 90) { System.out.println("等级: B"); } else if (score >= 70 && score < 80) { System.out.println("等级: C"); } else if (score >= 60 && score < 70) { System.out.println("等级: D"); } else if (score >= 0 && score < 60) { System.out.println("等级: E"); } else { System.out.println("输入的成绩无效!"); } scanner.close(); } } // MultiplicationTable.java public class MultiplicationTable { public static void main(String[] args) { // 外层循环控制行 for (int i = 1; i <= 9; i++) { // 内层循环控制列 for (int j = 1; j <= i; j++) { System.out.print(j + " * " + i + " = " + (i * j) + "\t"); } // 每行结束后换行 System.out.println(); } } }
实验报告要求
- 分别附上三个任务的完整源代码。
- 分别截图展示三个程序的运行结果。
- 在
MultiplicationTable中,如果将for (int j = 1; j <= i; j++)改为for (int j = 1; j <= 9; j++),输出会变成什么样?为什么?
思考题
switch语句中的break语句有什么作用?如果去掉break会发生什么?for循环和while循环在什么场景下使用更合适?do-while循环和while循环最主要的区别是什么?
数组与方法
实验目的
- 掌握一维数组的声明、创建、初始化和遍历。
- 掌握二维数组的基本使用。
- 理解方法的定义、调用和参数传递。
- 掌握方法的重载。
与步骤
-
任务1:数组操作
- 创建
ArrayDemo类。 - 创建一个包含5个整数的数组,并初始化。
- 遍历数组并打印所有元素。
- 计算数组中所有元素的和,并输出。
- 创建
-
任务2:方法定义与调用
- 创建
MethodDemo类。 - 定义一个方法
findMax(int[] arr),用于找出一个整数数组的最大值。 - 在
main方法中创建一个数组,调用findMax方法并打印结果。 - 定义一个方法
printArray(int[] arr),用于打印数组。 - 在
main方法中调用printArray方法。
- 创建
-
任务3:方法重载
- 在
MethodDemo类中,再定义一个findMax方法,但它接收两个double类型的参数,并返回较大的那个。 - 在
main方法中测试这个重载方法。
- 在
-
参考代码
public class MethodDemo { // main方法 public static void main(String[] args) { int[] numbers = {12, 45, 7, 23, 56}; double[] dNumbers = {12.5, 45.2, 7.8, 23.9}; // 调用打印数组的方法 printArray(numbers); // 调用查找最大值的方法 int maxInt = findMax(numbers); System.out.println("整型数组的最大值是: " + maxInt); double maxDouble = findMax(dNumbers[0], dNumbers[1]); // 测试重载 System.out.println("两个double数中的较大值是: " + maxDouble); } // 打印整型数组的方法 public static void printArray(int[] arr) { System.out.print("数组元素: ["); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]); if (i < arr.length - 1) { System.out.print(", "); } } System.out.println("]"); } // 查找整型数组最大值的方法 public static int findMax(int[] arr) { if (arr == null || arr.length == 0) { throw new IllegalArgumentException("数组不能为空"); } int max = arr[0]; for (int num : arr) { if (num > max) { max = num; } } return max; } // 方法重载:查找两个double数中的较大者 public static double findMax(double a, double b) { return a > b ? a : b; } }
实验报告要求
- 附上
MethodDemo.java的完整源代码。 - 截图展示程序运行结果。
- 解释什么是方法重载?重载的方法在什么情况下被认为是不同的?
思考题
- 数组的长度属性
length是什么类型的? - 当一个数组作为参数传递给方法时,传递的是值传递还是引用传递?
- 如何将一个数组的内容复制到另一个数组中?(提示:
System.arraycopy()或Arrays.copyOf())
面向对象编程(一):类与对象
实验目的
- 掌握类的定义,包括成员变量(属性)和成员方法。
- 掌握对象的创建和使用。
- 理解构造函数的作用和重载。
- 理解
this关键字的用法。
与步骤
-
设计一个
Student类- 属性:
name(String),age(int),studentId(String)。 - 构造函数:
- 一个无参构造函数。
- 一个带参构造函数,用于初始化所有属性。
- 方法:
study(): 打印 "[name] is studying."introduce(): 打印学生的自我介绍信息。getter和setter方法:为每个私有属性提供访问器和修改器。
- 属性:
-
创建
StudentTest类进行测试- 在
main方法中,创建两个Student对象。 - 一个对象使用无参构造函数创建,然后通过
setter方法设置属性。 - 另一个对象使用带参构造函数直接创建。
- 调用这两个对象的
introduce()和study()方法。
- 在
-
参考代码
// Student.java public class Student { // 1. 成员变量(属性),通常设为private以实现封装 private String name; private int age; private String studentId; // 2. 构造函数 // 无参构造函数 public Student() { System.out.println("一个Student对象被创建了(无参构造)"); } // 带参构造函数 public Student(String name, int age, String studentId) { this.name = name; // this.name 指代当前对象的name属性 this.age = age; this.studentId = studentId; System.out.println("一个Student对象被创建了(带参构造)"); } // 3. 成员方法 public void study() { System.out.println(this.name + " is studying."); } public void introduce() { System.out.println("大家好,我叫" + this.name + ",今年" + this.age + "岁,学号是" + this.studentId + "。"); } // 4. Getter 和 Setter 方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getStudentId() { return studentId; } public void setStudentId(String studentId) { this.studentId = studentId; } } // StudentTest.java public class StudentTest { public static void main(String[] args) { // 使用无参构造函数创建对象 Student student1 = new Student(); student1.setName("李四"); student1.setAge(21); student1.setStudentId("20250001"); System.out.println("--- 学生1的信息 ---"); student1.introduce(); student1.study(); System.out.println("\n-----------------\n"); // 使用带参构造函数创建对象 Student student2 = new Student("王五", 22, "20250002"); System.out.println("--- 学生2的信息 ---"); student2.introduce(); student2.study(); } }
实验报告要求
- 分别附上
Student.java和StudentTest.java的源代码。 - 截图展示程序运行结果。
this.name = name;中,两个name有什么区别?this关键字的作用是什么?
思考题
- 如果不定义任何构造函数,Java会做什么?
- 什么是封装?为什么要封装?
- 如果将
Student类中的age属性设为private,但在StudentTest中直接通过student1.age = -100;赋值,会发生什么?如何避免这种情况?
面向对象编程(二):继承、多态与抽象
实验目的
- 掌握类的继承,使用
extends关键字。 - 理解方法重写。
- 理解多态的概念和实现(父类引用指向子类对象)。
- 掌握抽象类和抽象方法的定义。
与步骤
-
设计一个继承体系
- 创建一个抽象类
Animal。- 属性:
name(String)。 - 构造函数:
public Animal(String name) - 抽象方法:
public abstract void eat(); - 普通方法:
public void sleep(),打印 "[name] is sleeping."
- 属性:
- 创建
Dog类,继承Animal。- 构造函数:
public Dog(String name) - 重写
eat()方法,打印 "[name] is eating bones."
- 构造函数:
- 创建
Cat类,继承Animal。- 构造函数:
public Cat(String name) - 重写
eat()方法,打印 "[name] is eating fish."
- 构造函数:
- 创建一个抽象类
-
创建
PolymorphismTest类测试多态- 在
main方法中,创建一个Animal类型的数组。 - 将
Dog对象和Cat对象存入数组。 - 遍历数组,对于数组中的每一个元素,调用
eat()和sleep()方法,观察多态行为。
- 在
-
参考代码
// Animal.java public abstract class Animal { private String name; public Animal(String name) { this.name = name; } public String getName() { return name; } // 抽象方法,没有方法体,必须由子类重写 public abstract void eat(); // 普通方法 public void sleep() { System.out.println(this.name + " is sleeping."); } } // Dog.java public class Dog extends Animal { public Dog(String name) { super(name); // 调用父类的构造函数 } @Override // 注解,表示重写父类方法 public void eat() { System.out.println(this.getName() + " is eating bones."); } } // Cat.java public class Cat extends Animal { public Cat(String name) { super(name); } @Override public void eat() { System.out.println(this.getName() + " is eating fish."); } } // PolymorphismTest.java public class PolymorphismTest { public static void main(String[] args) { // 父类引用指向子类对象,这就是多态 Animal dog = new Dog("旺财"); Animal cat = new Cat("咪咪"); // 创建一个Animal数组,存放不同子类的对象 Animal[] animals = new Animal[2]; animals[0] = dog; animals[1] = cat; // 遍历数组,调用方法 for (Animal animal : animals) { // 编译时看Animal类,运行时看实际对象类型(Dog或Cat) // 这就是多态的精髓:同一接口,不同实现 System.out.print(animal.getName() + " 的行为: "); animal.eat(); // 调用的是子类重写后的eat()方法 animal.sleep(); // 调用的是父类的sleep()方法 System.out.println("-------------------"); } } }
实验报告要求
- 分别附上
Animal.java,Dog.java,Cat.java,PolymorphismTest.java的源代码。 - 截图展示程序运行结果。
- 解释代码中
Animal dog = new Dog("旺财");这行代码体现了什么面向对象特性?并描述其运行机制。
思考题
abstract类不能被实例化,那它有什么用?final关键字可以修饰类、方法和变量,它们分别有什么含义?- 什么是
super关键字?它和this有什么区别和联系?
常用API与异常处理
实验目的
- 掌握
String类的常用方法(length(),charAt(),substring(),equals()等)。 - 掌握
StringBuilder类的使用及其与String的区别。 - 掌握
Date和SimpleDateFormat类处理日期和时间。 - 理解异常的概念,掌握
try-catch-finally结构的使用。
与步骤
-
String与StringBuilder操作- 创建
StringApiDemo类。 - 演示
String的不可变性。 - 演示
StringBuilder的高效拼接。 - 使用
StringBuilder实现一个简单的字符串反转功能。
- 创建
-
日期时间处理
- 创建
DateApiDemo类。 - 获取当前日期和时间。
- 使用
SimpleDateFormat将Date对象格式化为指定格式的字符串(如 "yyyy-MM-dd HH:mm:ss")。 - 将一个日期字符串解析为
Date对象。
- 创建
-
异常处理
- 创建
ExceptionDemo类。 - 模拟一个场景:用户输入两个整数,程序计算它们的商。
- 使用
try-catch结构处理可能发生的InputMismatchException(输入类型不匹配) 和ArithmeticException(除数为0) 异常。
- 创建
-
参考代码
import java.util.Date; import java.text.SimpleDateFormat; import java.text.ParseException; import java.util.Scanner; public class ExceptionDemo { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("--- 除法计算器 ---"); try { System.out.print("请输入第一个整数: "); int num1 = scanner.nextInt(); System.out.print("请输入第二个整数: "); int num2 = scanner.nextInt(); int result = num1 / num2; System.out.println("计算结果是: " + result); } catch (java.util.InputMismatchException e) { System.out.println("错误:请输入有效的整数!"); } catch (ArithmeticException e) { System.out.println("错误:除数不能为零!"); } finally { // 无论是否发生异常,finally块中的代码都会执行 System.out.println("程序执行完毕。"); scanner.close(); } } }
实验报告要求
- 附上
ExceptionDemo.java的完整源代码。 - 截图展示程序正常输入、输入非数字、输入除数为0三种情况的运行结果。
try-catch-finally语句块中,finally的作用是什么?什么情况下finally中的代码可能不会执行?
思考题
- 为什么说
String对象是不可变的?这对性能有什么影响? - 和
equals()方法在比较字符串时有何不同? - 什么是受检异常和非受检异常?各举一个例子。
文件I/O与集合框架
实验目的
- 掌握使用
File类和FileReader/FileWriter进行基本的文件读写。 - 掌握使用
BufferedReader和BufferedWriter进行高效的文件读写。 - 掌握
ArrayList集合的基本操作(增、删、改、查、遍历)。 - 了解
HashMap集合的基本用法(存、取、遍历)。
与步骤
-
使用
ArrayList管理学生信息- 创建
StudentManager类。 - 在
main方法中,创建一个ArrayList<Student>集合(使用实验五中的Student类)。 - 向集合中添加几个
Student对象。 - 遍历集合,打印所有学生的信息。
- 创建
-
使用
HashMap管理学生信息- 修改
StudentManager类。 - 创建一个
HashMap<String, Student>集合,以学号为键,Student对象为值。 - 向
HashMap中添加学生信息。 - 根据学号查找一个学生并打印其信息。
- 修改
-
文件读写
- 创建一个
FileIODemo类。 - 使用
BufferedWriter将一个字符串 "Hello, File I/O!" 写入到test.txt文件中。 - 使用
BufferedReader从test.txt文件中读取内容并打印到控制台。
- 创建一个
-
参考代码
import java.io.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class FileIODemo { public static void main(String[] args) { String fileName = "test.txt"; String content = "Hello, File I/O! This is a test."; // 1. 写入文件 try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) { writer.write(content); System.out.println("文件写入成功!"); } catch (IOException e) { System.out.println("写入文件时出错: " + e.getMessage()); } // 2. 读取文件 System.out.println("\n--- 开始读取文件内容 ---"); try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { System.out.println("读取文件时出错: " + e.getMessage()); } } }
实验报告要求
- 附上
FileIODemo.java的完整源代码。 - 截图展示程序运行结果,并附上生成的
test.txt文件的内容截图。 ArrayList和HashMap的主要区别是什么?分别在什么场景下使用?
思考题
- 为什么进行文件I/O操作时,推荐使用
try-with-resources语句? ArrayList和数组有什么区别?HashMap是如何根据键来快速查找值的?
总结与建议
- 循序渐进: 实验的难度是递增的,请务必完成前面的实验再进行后面的实验。
- 勤动手: 程序设计是实践性极强的学科,光看不练是学不会的,多敲代码,多尝试修改代码观察结果。
- 善用调试器: 学会使用IDE的调试功能(断点、单步执行、查看变量值),这是排查错误最有效的方法。
- 多查文档: 遇到问题,先尝试查阅Java官方文档或搜索引擎,培养独立解决问题的能力。
- 写好注释: 良好的注释和代码风格是优秀程序员的必备素质。
希望这份详细的实验指导能对你的Java学习之路有所帮助!祝你实验顺利!
