Featured image of post Java|2.类 (简洁版)

Java|2.类 (简洁版)

AI 辅助信息

  • 使用工具:Gemini 2.5 Pro

内存管理与对象模型

自动垃圾回收(GC)

Java通过JVM的垃圾回收机制自动管理内存,开发者无需手动释放对象。所有对象通过new在堆上创建,生命周期由GC决定。例如:

1
2
3
4
public void javaMethod() {  
    MyClass obj = new MyClass(); // 对象在堆上创建  
    // 使用obj...  
} // 方法结束后,obj引用不再可达,GC会在未来某个时间回收内存  

引用类型对象模型

Java中所有非基本类型(如intdouble)的对象变量存储的是堆上对象的引用(可视为安全的指针)。与C++不同,Java不允许在栈上直接创建对象实例:

1
2
MyClass objRef; // 引用初始值为null  
objRef = new MyClass(); // 引用指向堆上的对象  

参数传递特性

Java的对象参数传递是引用的按值传递。这意味着方法内部对引用的修改不会影响外部变量,但可以通过引用修改对象的状态。

构造器(Constructor)与初始化

初始化方式

Java的成员变量初始化通常在构造器方法体内完成,或在声明时直接赋值:

1
2
3
4
5
6
7
class MyClass {  
    private int value = 10; // 声明时赋值  

    public MyClass(int v) {  
        this.value = v; // 构造器内赋值  
    }  
}  

构造器调用规则

  • 子类构造器必须在第一行显式调用父类构造器(super(参数))。若未显式调用,编译器会自动插入super()(调用父类无参构造器)。若父类无无参构造器,子类必须显式调用。
  • 构造器委托:通过this(参数)调用同一类的其他构造器,必须是构造器的第一条语句:
1
2
3
4
5
6
7
8
9
class Box {  
    public Box(int width) {  
        this(width, 0); // 调用另一个构造器  
    }  

    public Box(int width, int height) {  
        // 初始化逻辑  
    }  
}  

默认构造器

若未定义任何构造器,编译器会自动生成一个无参默认构造器(public)。一旦定义任意构造器,编译器不再提供默认构造器。


继承(Inheritance)与接口(Interface)

单继承与接口实现

Java采用单继承(一个类只能有一个直接父类),通过extends实现继承。为弥补多继承缺失,Java引入接口interface),允许类实现多个接口(implements):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 单继承示例  
class Dog extends Animal {  
    // 继承Animal的所有非private成员  
}  

// 接口实现示例  
interface Playable {  
    void play(); // 抽象方法  
}  

class Music implements Playable {  
    @Override  
    public void play() {  
        System.out.println("播放音乐");  
    }  
}  

继承的核心用途

  • 代码复用:子类直接使用父类的属性和方法。
  • 类型层次结构:构建从抽象到具体的分类体系(如Dog is an Animal)。

接口的设计哲学

接口定义行为契约(“能做什么”),而非类型(“是什么”)。实现接口的类必须提供所有抽象方法的具体实现,从而实现多态和解耦。

接口冲突处理

当多个接口定义同名方法时,实现类需根据以下规则处理:

  1. 方法签名相同(参数、返回类型一致):实现类只需提供一次公共实现。无论通过哪个接口的引用来调用该方法,最终执行的都是子类中的单一实现。
  2. 方法签名不同(参数不同):实现类需分别实现每个方法。这属于方法重载(Overload)的范畴。
  3. 方法签名相同但返回类型不同:编译失败。Java不允许定义两个只有返回类型不同的同名方法。

示例场景
假设GameArtwork接口均定义了play()方法,而Starfield类同时实现这两个接口:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
interface Game {  
    void play();  
}  

interface Artwork {  
    void play();  
}  

class Starfield implements Game, Artwork {  
    @Override  
    public void play() {  
        System.out.println("播放游戏并展示艺术效果");  
    }  
}  

此时Starfield只需提供一次play()的实现,即可满足两个接口的契约。


多态(Polymorphism)与方法重写

默认虚函数机制

Java中所有非static、非private的方法默认是虚函数,支持运行时多态。子类通过@Override注解重写父类方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Animal {  
    public void eat() {  
        System.out.println("This animal eats food.");  
    }  
}  

class Dog extends Animal {  
    @Override  
    public void eat() {  
        System.out.println("This dog eats dog food.");  
    }  
}  

方法重写 vs. 重载

  • 重写(Override):子类重新定义父类方法(方法签名完全相同)。
  • 重载(Overload):同一类中同名方法参数列表不同(参数个数、类型或顺序不同)。

访问控制与封装

四种访问修饰符

Java通过四类访问修饰符控制成员可见性,从宽松到严格依次为:public > protected > default(包私有) > private

修饰符同一类同一包子类(不同包)其他包
public
protected
default
private

最佳实践

  • 将字段设为private,通过publicgetter/setter控制访问。
  • 接口和公共API使用public,内部实现细节使用protecteddefault

其他关键特性

泛型(Generics)

Java泛型通过类型擦除实现,运行时所有泛型信息会被擦除:

1
2
3
List<String> list1 = new ArrayList<>();  
List<Integer> list2 = new ArrayList<>();  
// 运行时list1和list2的类型均为List  

总结

Java的类设计在继承、内存管理、多态等方面与传统OOP语言存在显著差异。理解其自动内存管理引用模型单继承+多接口机制,以及默认虚函数访问控制策略,是掌握Java面向对象编程的核心。对于有工程经验的开发者,建议重点关注接口设计、多态实现和访问控制的实际应用场景。

本文采用 CC BY 4.0 许可协议,转载请注明出处。
使用 Hugo 构建
主题 StackJimmy 设计