一、实验内容
掌握类的定义和对象的创建。
1. 运行教材第三章中例 3-1 到例 3-8。
例 3-1:求两个数的最大值。
public class MaxValue {
// 自定义成员方法:接收两个整数,返回最大值
public int doMaxValue(int a, int b) {
// 三元运算符:条件成立取前者,不成立取后者
return a > b ? a : b;
}
public static void main(String[] args) {
MaxValue m = new MaxValue();
// 调用自定义方法,传入参数 3 和 5
int max = m.doMaxValue(3, 5);
System.out.println("这两个数的最大值是:" + max);
}
}运行结果:
这两个数的最大值是:5

例 3-2:求输出数的最大值
// 演示 Java 方法重载:同类中方法名相同,参数列表不同
public class OverloadMaxValue {
// 重载方法 1:一个 int 参数
public void doMaxValue(int a) {
System.out.println(a);
}
// 重载方法 2:两个 int 参数,用三元运算符返回最大值
public int doMaxValue(int a, int b) {
return a > b ? a : b;
}
public static void main(String[] args) {
OverloadMaxValue m = new OverloadMaxValue();
// 自动匹配调用 单个参数 的重载方法
m.doMaxValue(30);
// 自动匹配调用 两个参数 的重载方法并打印结果
System.out.println(m.doMaxValue(30, 40));
}
}运行结果:
30
40

例 3-3:定义一个学生类,创建学生对象,给学生对象赋值,并调用学生上课的方法。
class Student {
// 成员变量(属性)
String no; // 学号
String name; // 姓名
int age; // 年龄
// 成员方法(行为):学生上课
public void goToClass() {
System.out.println(name + "学生去上课!");
}
}
public class Test {
public static void main(String[] args) {
// 1. 创建 Student 对象(实例化)
Student stu = new Student();
// 2. 为对象属性赋值
stu.no = "soft001";
stu.name = "张三";
stu.age = 20;
// 3. 调用对象的成员方法
stu.goToClass();
}
}运行结果:
张三学生去上课!

例 3-4:this 关键字的实例。
// 演示 this 关键字:区分成员变量和局部变量
public class Student {
String name;
// 构造方法:创建对象时自动调用,用于初始化属性
// 参数 name 是局部变量,与成员变量重名
public Student(String name) {
// this.成员变量 = 局部变量
// this 代表当前对象,用来区分重名变量
this.name = name;
}
public static void main(String[] args) {
// 创建对象,自动调用构造方法
Student stu = new Student("soft");
// 输出成员变量值
System.out.println("学生姓名:" + stu.name);
}
}运行结果:
学生姓名:soft

例 3-5:重新定义学生的类。
// 演示构造方法重载 + this() 调用本类构造方法
public class Student {
String name;
// 带参数构造方法:接收姓名并赋值
public Student(String name) {
// this 代表当前对象,给成员变量赋值
this.name = name;
}
// 无参构造方法
public Student() {
// this(...) 调用本类带参构造方法
// 必须写在构造方法第一行
this("soft");
}
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu.name);
}
}运行结果:
soft
例 3-6:包的创建实例。
// 包声明:必须放在代码第一行(注释除外)
package li_3_6;
public class Student {
String name;
public Student(String name) {
this.name = name;
}
}
例 3-7:内部类实例。
// 外部类
class OuterClass {
// 外部类私有静态变量
private static String university = "xxxx";
// 外部类私有实例变量
private String name;
private int age;
// 外部类构造方法:初始化成员变量
public OuterClass(String name, int age) {
this.name = name;
this.age = age;
}
// 成员内部类(非静态内部类)
public class InnerClass {
// 内部类成员变量
private String school = "soft";
// 内部类方法:访问外部类所有成员
public void print() {
// 访问外部类静态成员
System.out.println(OuterClass.university);
// 访问外部类实例成员
System.out.println(OuterClass.this.name);
System.out.println(OuterClass.this.age);
// 访问内部类自己的成员
System.out.println(school);
}
}
}
public class InnerClassTest {
public static void main(String[] args) {
// 1. 先创建外部类对象
OuterClass outer = new OuterClass("bks", 29);
// 2. 通过外部类对象创建内部类对象(固定语法)
OuterClass.InnerClass innerClass = outer.new InnerClass();
// 3. 调用内部类方法
innerClass.print();
}
}运行结果:
xxxx
bks
29
soft

例 3-8:静态的内部类举例。
// 外部类
class OuterClass {
// 外部类静态成员变量
private static String university = "xxxx";
// 外部类实例成员变量
private String name;
private int age;
// 外部类构造方法
public OuterClass(String name, int age) {
this.name = name;
this.age = age;
}
// 静态内部类:使用 static 修饰
public static class InnerClass {
// 静态内部类的成员变量
private String school = "soft";
// 内部类方法
public void print() {
// 静态内部类可以直接访问外部类静态成员
System.out.println(OuterClass.university);
// 访问内部类自己的成员
System.out.println(school);
}
}
}
public class InnerClassStaticTest {
public static void main(String[] args) {
// 静态内部类直接创建,不需要外部类对象
OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
// 调用方法
innerClass.print();
}
}运行结果:
xxxx
soft

一、非静态内部类(普通内部类)
- 必须先创建外部类对象,才能创建它;
- 能直接访问外部类所有成员(静态、非静态都可以);
- 里面不能写 static 变量、static 方法。
二、静态内部类(static 修饰的内部类)
- 不用创建外部类对象,能直接单独 new;
- 只能直接访问外部类的 static 成员;想访问外部普通成员,必须手动 new 外部类对象;
- 内部随便写普通变量、static 变量、static 方法都允许。
三、考试标准简答(直接写答案)
- 非静态内部类依赖外部类实例存在,有指向外部类对象的引用,可访问外部类全部成员,类内部不允许定义静态成员;
- 静态内部类独立于外部类实例,仅可直接访问外部类静态成员,类内部可定义静态、非静态成员。
2. 创建一个名为 Rectangle 的类,用来表示一个矩形,该类包含长、宽两个属性,包含一个求面积(getArea())和一个求周长(getPerimeter())的方法,创建对象并测试 getArea() 和 getPerimeter() 两个方法。
(1)定义 Rectangle 类
// 矩形类:定义属性、构造方法、求面积/周长的功能
public class Rectangle {
// 成员变量:长和宽
double length;
double width;
// 无参构造方法
public Rectangle() {
}
// 有参构造方法:创建对象时直接初始化长和宽
public Rectangle(double length, double width) {
// this 区分成员变量和参数
this.length = length;
this.width = width;
}
// 计算面积
public double getArea() {
return length * width;
}
// 计算周长
public double getPerimeter() {
return 2 * (length + width);
}
}(2)定义 TestRectangle 测试类
import java.util.Scanner;
// 测试类:演示两种创建矩形对象的方式
public class TestRectangle {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 方式一:无参构造创建对象,再手动赋值
System.out.println("===== 无参构造方式 =====");
Rectangle rect1 = new Rectangle();
System.out.print("请输入矩形的长:");
rect1.length = scanner.nextDouble();
System.out.print("请输入矩形的宽:");
rect1.width = scanner.nextDouble();
System.out.println("矩形面积:" + rect1.getArea());
System.out.println("矩形周长:" + rect1.getPerimeter());
// 方式二:有参构造创建对象,直接传参初始化
System.out.println("\n===== 有参构造方式 =====");
System.out.print("请输入矩形的长:");
double len = scanner.nextDouble();
System.out.print("请输入矩形的宽:");
double wid = scanner.nextDouble();
Rectangle rect2 = new Rectangle(len, wid);
System.out.println("矩形面积:" + rect2.getArea());
System.out.println("矩形周长:" + rect2.getPerimeter());
scanner.close();
}
}运行结果:
===== 无参构造方式 =====
请输入矩形的长:15
请输入矩形的宽:15
矩形面积:225.0
矩形周长:60.0
===== 有参构造方式 =====
请输入矩形的长:15
请输入矩形的宽:15
矩形面积:225.0
矩形周长:60.0

二、课后习题
第三章:类和对象
第三章 一、填空题:
- 类的定义由类头和 类体 两部分组成。
- 类 是组成 Java 程序的基本要素,封装了一类对象的状态和方法。
- 类的实现包括两部分:类声明和 类体。
- 类体有两部分构成:一部分是 变量 的定义,另一部分是方法的定义。
- 在类体中,变量定义部分所定义的变量称为类的 成员变量。
- 成员变量在整个类内都有效,局部 变量只在定义它的方法内有效。
- 用修饰符 static 说明的成员变量是类变量。
- 变量的名字与成员变量的名字相同,则成员变量被 隐藏,该成员变量在这个方法内暂时失效。
- Java 中成员变量又分为实例成员变量和 静态成员变量(类变量)。
- 用修饰符 static 说明的成员变量是 静态成员变量(类变量)。
- 局部变量的名字与成员变量的名字相同,若想在该方法内使用成员变量,必须使用关键字 this。
- 方法定义包括两部分:方法的声明(方法头) 和方法体。
- 在 Java 中,当一个方法不需要返回数据时返回类型必须是 void。
- Java 中类的方法分为 实例方法 和类方法。
- 在类方法中只能调用类变量和类方法,不能调用 实例 方法。
第三章 二、选择题:
-
在编写实现文件读写功能的 Java 程序时,需要在程序的开头写上语句(C)。
(A)import java.applet.*;(Applet 相关包)
(B)import java.awt.*;(图形界面相关包)
(C)import java.io.*;(文件读写需要使用 IO 包,正确)
(D)import java.awt.event.*;(事件处理相关包) -
有一个类 A,以下为其构造函数的声明,其中正确的是(B)。
(A)void A(int x){...}(构造函数不能有返回值类型,错误)
(B)A(int x){...}(与类名同名、无返回值类型,正确)
(C)a(int x){...}(构造函数名必须和类名完全一致,错误)
(D)void a(int x){...}(有返回值类型,且方法名与类名不一致,错误) -
下列方法定义中,正确的是(D)。
(A)int x( int a, b ) { return (a - b); }(形参 b 未声明数据类型,错误)
(B)double x( int a, int b) { int w; w = a - b; }(返回值类型为 double,但方法体无 return 语句,错误)
(C)double x( a, b ) { return b; }(形参 a、b 未声明数据类型,错误)
(D)int x( int a, int b) { return a - b; }(形参声明完整,返回值类型与 return 语句匹配,正确) -
下列类定义中,不正确的是(C)。
(A)class x { .... }(普通类定义,合法)
(B)class x extends y { .... }(类继承定义,合法)
(C)static class x implements y1,y2 { .... }(外部类不能用 static 修饰,只有静态内部类才可以用 static 修饰,错误)
(D)public class x extends Applet { .... }(公共类继承 Applet,合法) -
对于下列代码:
public class Parent {
public int addValue(int a, int b) {
int s;
s = a + b;
return s;
}
}
class Child extends Parent {
}下述(CD)方法可以加入类 Child?
(A) int addValue(int a, int b){// do something...}(错误,同签名试图重写,无修饰符(包权限)比父类public权限更严格,Java 禁止重写时缩小访问权限,编译报错,不可加入)
(B) public void addValue(int a, int b){// do something...}(错误,参数列表未变,仅修改返回值,既不满足重写返回值要求,也不构成重载,编译报错,不可加入)
(C) public int addValue(int a){// do something...}(正确,方法名相同、参数个数不同,构成方法重载,语法合法,可加入)
(D) public int addValue(int a, int b){// do something...}(正确,方法签名、权限、返回值均与父类匹配,是合法方法重写,可加入)
方法签名 = 方法名 + 参数列表(个数、类型、顺序)。返回值不属于签名的一部分!
子类可以重写或者重载父类的方法
- 重写要求:子类重写父类同签名方法,返回值必须兼容(int/Integer),不能直接改成 void ,权限不能缩小,否则编译器直接报语法错误,和你大括号里打印什么毫无关系。
-
(与上面选择题的第 1 题重复!!!省略)
-
以下关于构造函数的描述错误的是(A)。
(A) 构造函数的返回类型只能是 void 型(错误,构造函数没有返回值类型,也不能写 void)
(B) 构造函数是类的一种特殊函数,它的方法名必须与类名相同(正确)
(C) 构造函数的主要作用是完成对类的对象的初始化工作(正确)
(D) 一般在创建新对象时,系统会自动调用构造函数(正确) -
关于修饰符 static ,以下叙述错误的是(D)。
(A) static 方法不可被覆盖(正确,静态方法不参与多态,不能被重写)
(B) static 可以用来修饰类(正确,Java 中可以定义静态内部类)
(C) static 方法不可以直接访问非静态的方法,否则编译出错(正确,静态方法中没有隐式 this,无法直接访问非静态成员)
(D) static 方法只能访问类变量或方法参数,不可直接访问成员变量(错误,静态方法也可以访问局部变量(静态方法内部,完全可以自己定义局部变量并使用),不只是类变量和方法参数) -
给出如下代码:
class Test {
//定义成员 a
public static void fun() {
// some code...
}
}要在函数 fun() 中直接访问 a ,以下成员变量 a 定义正确的是(B)。
(A) public int a(错误,非静态成员变量,不能被静态方法直接访问)
(B) static int a(正确,静态成员变量,可以被静态方法直接访问)
(C) int a(错误,非静态成员变量,不能被静态方法直接访问)
(D) protected int a(错误,非静态成员变量,不能被静态方法直接访问)
- 编译并运行以下程序,以下描述哪个选项是正确的(C)。
class ATestOfToString {
protected String toString(){
return super.toString();
}
}(A) 编译通过运行无异常(错误)
(B) 编译通过但运行时出错(错误)
(C) 行 2 出错,不能成功编译(正确,方法重写时,子类方法的访问权限不能比父类更严格。Object 类的 toString() 方法是 public 的,这里用 protected 修饰会编译报错)
(D) 不能成功编译,行 3 出错(错误,错误在第 2 行的方法声明)
第三章 三、输出结果题:
阅读下面的程序,程序保存为 Test.java。
public class Test {
short mValue;
public static void main(String[] args) {
int a = 32;
int b = 56;
Test os = new Test(a + b);
os.Show();
}
protected Test(short aValue) {
mValue = aValue;
}
public void Show() {
System.out.println(mValue);
}
}上面的程序编译是否成功?如果编译出错,指出哪行出错,并说明理由;如果编译正确,运行结果是什么?
编译错误,错误出现在第 7 行 Test os = new Test(a+b);
变量 a 和 b 均为 int 类型,因此 a+b 的运算结果也是 int 类型。而构造方法 protected Test(short aValue) 要求传入 short 类型的参数。在 Java 中,高数据类型(int)无法自动转换为低数据类型(short),必须进行强制类型转换,否则编译器会报错。
第三章 四、问答题:
- 什么是对象?什么是类?对象与类的关系是什么?
- 对象是现实世界中某一类事物的具体实例,包含属性(状态)和行为(方法),万物皆可为对象。
- 类是对一组具有相同属性和行为的对象的抽象描述,是创建对象的模板。
- 关系:类是对象的抽象,对象是类的实例化;类是抽象概念,对象是具体实体;一个类可以实例化出多个对象。
- 类的定义中包括哪些基本信息?
- 类头:[修饰符] class 类名 [extends 父类名] [implements 接口列表]
- 类体:
- 属性(成员变量)定义:描述对象的状态
- 方法定义:描述对象的行为,包括构造方法和普通方法。
- 如何运行被打包后的字节码文件?
java 主类名(通过 JVM 解释执行字节码文件)
- 类变量与实例变量的区别有哪些?
- 类变量(静态变量,static 修饰):属于整个类,被所有对象共享;一个对象修改其值后,所有对象访问到的都是修改后的值。
- 实例变量(非静态变量):属于每个对象私有,每个对象都有独立的副本;一个对象修改其值,不影响其他对象的同名实例变量(比如人的年龄 age)。
- 类方法与实例方法的区别有哪些?
- 类方法(静态方法,static 修饰):属于整个类,不依赖对象;只能访问类变量和其他类方法,不能直接访问实例变量和实例方法;可通过类名.方法名()或对象.方法名()调用;不能被重写。
- 实例方法(非静态方法):属于对象,必须通过对象调用;既可以访问类变量、类方法,也可以访问实例变量和实例方法;可以被重写。
- 什么叫构造函数重载?
在同一个类中,定义多个方法名与类名完全相同,但参数列表(参数个数、类型或顺序)不同的构造方法,就构成了构造函数重载。作用是提供多种方式创建对象,方便对象初始化。
- 什么是方法,及方法的作用有哪些?
- 方法是定义在类中、具有特定功能的代码块,描述对象的行为。
- 作用:封装一段重复执行的逻辑,提高代码复用率;让代码结构更清晰,便于维护和修改;实现特定的功能,完成数据的处理和返回。
- Java 中引入包的优点是什么?
- 解决命名冲突:不同包中的类可以同名,避免重名问题;
- 组织和管理类:将相关的类和接口按功能分组,方便查找和管理;
- 提供访问控制:包配合访问修饰符,可以实现类和成员的封装与权限控制;
- 支持模块化开发:不同功能模块可以放在不同的包中,便于项目分工和维护。
- 如何将需要的外部类引入程序中?如何引用包中的某个类?如何引用整个包?
在 Java 中通过 import 语句引入外部类。
// 引用包中的某个类:
import 包名.类名;
// 例如:import java.util.Scanner;// 引用整个包中的所有类:
import 包名.*;
// 例如:import java.util.*;也可以不写 import,直接在代码中使用类的全限定名:包名.类名,例如:java.util.Scanner sc = new java.util.Scanner(System.in);
第三章 五、编程题:
第一题:
编写一个完整的 Java Application 程序,包括:①复数类 Complex;②主类 Test。将每组测试数据相加并显示结果,三组测试的复数为:1 + 2i 和 1 - 2i;1 + 2i 和 3 + 4i;1 + 2i 和 -1 + 2i。其中,复数类 Complex 必须满足如下要求:
(1) 复数类 Complex 的属性
- realPart:int 型,代表复数的实部。
- imaginPart:int 型,代表复数的虚部。
(2) 复数类 Complex 的方法
- Complex():构造函数,将复数的实部和虚部都置 0。
- Complex(int r,int i):构造函数,将复数的实部初始化为 r,将虚部初始化为 i。
- Complex complexAdd(Complex a):将当前复数对象与形参复数对象 a 相加,所得的结果仍是一个复数对象,返回给此方法的调用者。
- public String toString():把当前复数对象的实部、虚部组合成 “a + bi” 的字符串形式;若实部为 0,虚部不为 0,则返回 “bi”;若虚部为 0,则返回 “a”。
// 定义复数类 Complex
class Complex {
int realPart; // 实部
int imaginPart; // 虚部
// 无参构造方法,实部虚部初始化为 0
Complex() {
realPart = 0;
imaginPart = 0;
}
// 带参构造方法,初始化实部和虚部
Complex(int r, int i) {
realPart = r;
imaginPart = i;
}
// 复数加法:当前复数 + 参数复数,返回新复数
Complex complexAdd(Complex a) {
int r = this.realPart + a.realPart;
int i = this.imaginPart + a.imaginPart;
return new Complex(r, i);
}
// 格式化输出复数字符串,重写 Object 类的 toString 方法
@Override
public String toString() {
if (realPart == 0 && imaginPart != 0) {
return imaginPart + "i";
} else if (imaginPart == 0) {
return realPart + "";
} else {
return realPart + "+" + imaginPart + "i";
}
}
}
public class Test {
public static void main(String[] args) {
// 第一组:1+2i 和 1-2i
Complex c1 = new Complex(1, 2);
Complex c2 = new Complex(1, -2);
System.out.println(c1 + " + " + c2 + " = " + c1.complexAdd(c2));
// 第二组:1+2i 和 3+4i
Complex c3 = new Complex(1, 2);
Complex c4 = new Complex(3, 4);
System.out.println(c3 + " + " + c4 + " = " + c3.complexAdd(c4));
// 第三组:1+2i 和 -1+2i
Complex c5 = new Complex(1, 2);
Complex c6 = new Complex(-1, 2);
System.out.println(c5 + " + " + c6 + " = " + c5.complexAdd(c6));
}
}运行结果:
1+2i + 1+-2i = 2
1+2i + 3+4i = 4+6i
1+2i + -1+2i = 4i
第二题:
创建一个名为 Rectangle 的类来表示一个使用宽度和高度来改变量的矩形,矩形的宽度和高度由构造方法来确定。为 Rectangle 类创建下列方法:
(1)getArea() 返回矩形的面积,要求长和高的范围为 0~50。
(2)getPerimeter() 返回矩形的周长。
(3)Draw 使用星号 (*) 作为描绘字符画出该矩形(假设宽度和高度为整数)。
(4)在另一个类 TestRectangle 中编写 main() 方法来测试 Rectangle 类。
// 矩形类Rectangle
class Rectangle {
int width; // 矩形宽度
int height; // 矩形高度
// 构造方法,给宽、高赋值
Rectangle(int w, int h) {
width = w;
height = h;
}
// 求面积,宽高限制0~50
public int getArea() {
// 超出范围按0处理
if (width < 0 || width > 50 || height < 0 || height > 50) {
return 0;
}
return width * height;
}
// 求周长
public int getPerimeter() {
if (width < 0 || width > 50 || height < 0 || height > 50) {
return 0;
}
return 2 * (width + height);
}
// 用*打印矩形
public void Draw() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
public class TestRectangle {
public static void main(String[] args) {
// 实例化一个宽 4、高 3 的矩形
Rectangle r = new Rectangle(4, 3);
System.out.println("面积:" + r.getArea());
System.out.println("周长:" + r.getPerimeter());
System.out.println("矩形图形:");
r.Draw();
}
}运行结果:
面积:12
周长:14
矩形图形:
****
****
****
评论