Java-Chapter 9 Objects and Classes

问题 1:什么是类和对象?

答案

  1. 是对象的模板,定义了对象的属性(变量)和行为(方法)。
  2. 对象是类的实例,表示类的具体实现。

解释

  • 类(Class):描述事物的抽象定义。例如,"学生"可以定义为一个类,包含属性如姓名和年龄,以及行为如学习和考试。
  • 对象(Object):是类的具体化。例如,“张三”是学生类的一个对象,其属性值为姓名=张三、年龄=20。

问题 2:如何创建对象?

答案
使用 new 操作符创建对象,并通过点操作符(.访问成员。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Student {
String name; // 属性
int age;

// 构造器
Student(String name, int age) {
this.name = name;
this.age = age;
}

void study() {
System.out.println(name + " is studying.");
}
}

public class Main {
public static void main(String[] args) {
Student student = new Student("张三", 20); // 创建对象
student.study(); // 访问方法
System.out.println(student.name); // 访问属性
}
}

输出

1
2
张三 is studying.
张三

问题 3:什么是静态变量和实例变量?

答案

  • 实例变量:属于类的每个对象,实例变量的值在对象之间是独立的。
  • 静态变量:属于类本身,所有对象共享同一个静态变量值。

解释

  • 实例变量的生命周期随着对象创建和销毁而存在。
  • 静态变量的生命周期从类加载到 JVM 关闭。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Counter {
static int count = 0; // 静态变量
int id; // 实例变量

Counter() {
count++;
id = count;
}

void showId() {
System.out.println("Object ID: " + id);
}
}

public class Main {
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
c1.showId(); // 输出:Object ID: 1
c2.showId(); // 输出:Object ID: 2
System.out.println("Count: " + Counter.count); // 静态变量,输出:Count: 2
}
}

问题 4:什么是静态方法和实例方法?

答案

  • 实例方法:需要对象调用,与具体实例关联。
  • 静态方法:不需要实例,通过类名直接调用。

解释

  • 静态方法通常用于工具类方法或不依赖实例的功能。
  • 实例方法需要依赖具体对象的状态。

示例

1
2
3
4
5
6
7
8
9
10
11
class Utility {
static void printHello() {
System.out.println("Hello, World!");
}
}

public class Main {
public static void main(String[] args) {
Utility.printHello(); // 静态方法直接通过类名调用
}
}

输出

1
Hello, World!

问题 5:如何访问静态变量和方法?

答案
静态变量和方法可以通过类名实例对象访问,但为了清晰起见,推荐使用 ClassName.variableClassName.method 的形式。

解释
静态变量和方法属于类本身,而不是具体的对象。通过类名访问可以直观体现其与类的关联性。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Example {
static int count = 0; // 静态变量

static void printMessage() { // 静态方法
System.out.println("Static method called!");
}
}

public class Main {
public static void main(String[] args) {
Example.printMessage(); // 推荐用类名访问
System.out.println("Count: " + Example.count);
}
}

输出

1
2
Static method called!
Count: 0

问题 6:访问修饰符的作用是什么?

答案
修饰符决定类、方法和数据成员的访问权限。

  • public:可以被所有类访问。
  • default(无修饰符):只能在同一个包内访问。
  • private:只能在类内部访问。

解释
访问修饰符用于实现封装,控制类的成员对外暴露的程度。

示例

1
2
3
4
5
6
7
8
9
10
11
class AccessModifiers {
public int publicValue = 1; // 公开成员
int defaultValue = 2; // 包访问权限
private int privateValue = 3; // 私有成员

public void showValues() {
System.out.println("Public: " + publicValue);
System.out.println("Default: " + defaultValue);
System.out.println("Private: " + privateValue);
}
}
  • publicValue 可在任何地方访问。
  • defaultValue 只能在同包内访问。
  • privateValue 只能在类内访问。

问题 7:Java 参数是如何传递的?

答案

  • 对于基本数据类型:按值传递,方法内修改不影响原变量。
  • 对于引用类型:传递的是对象的引用,方法内可以修改对象的内容,但不能改变引用指向的对象。

解释
Java 的参数传递是“值传递”。对于引用类型,传递的值是对象的引用地址,允许通过该引用修改对象内容,但引用本身不能被更改。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Demo {
int value;

Demo(int value) {
this.value = value;
}
}

public class Main {
public static void modifyPrimitive(int x) {
x = 10; // 修改局部变量,不影响原变量
}

public static void modifyObject(Demo obj) {
obj.value = 10; // 修改对象内容,影响原对象
}

public static void main(String[] args) {
int a = 5;
Demo demo = new Demo(5);

modifyPrimitive(a);
modifyObject(demo);

System.out.println("a: " + a); // 输出 a: 5
System.out.println("demo.value: " + demo.value); // 输出 demo.value: 10
}
}

问题 8:什么是不可变类?如何设计?

答案
不可变类是指对象一旦创建后,其状态(数据)就不能被修改。

设计不可变类的方法

  1. 将所有数据字段声明为 private
  2. 不提供改变字段的 mutator 方法(如 setXXX)。
  3. 如果类包含引用类型字段,不提供返回引用的访问器,避免外部修改。
  4. 将类声明为 final 防止继承(可选)。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
final class ImmutableExample {
private final String name;

public ImmutableExample(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

public class Main {
public static void main(String[] args) {
ImmutableExample obj = new ImmutableExample("Immutable Object");
System.out.println(obj.getName());
// obj.name = "New Name"; // 错误,name 是不可变的
}
}

输出

1
Immutable Object