杰瑞科技汇

Java中set/get方法的具体用法是什么?

封装

在理解 setget 之前,你必须先理解面向对象编程中的一个核心概念:封装

Java中set/get方法的具体用法是什么?-图1
(图片来源网络,侵删)

封装 的思想是:

  1. 隐藏内部状态:一个对象不应该直接暴露其内部的数据(成员变量),外部代码不应该能随意地修改对象的内部状态,这会导致对象变得不稳定和不可预测。
  2. 提供公共接口:对象应该通过一组公共的方法(public methods)来与外界交互,这些方法就像是对象的“门卫”或“服务员”,负责控制对内部数据的访问和修改。

setget 方法就是实现封装最经典、最常见的方式。

  • Getter (或 Accessor):用于获取(读取)私有成员变量的值,方法名通常以 get 开头。
  • Setter (或 Mutator):用于设置(修改)私有成员变量的值,方法名通常以 set 开头。

为什么需要使用 setget

直接让成员变量 public 看起来很方便,但会带来很多问题:

// 不好的实践:public 成员变量
public class BadUser {
    public String name;
    public int age;
}
public class Main {
    public static void main(String[] args) {
        BadUser user = new BadUser();
        user.name = "John";
        user.age = -5; // 问题:年龄可以被设置为负数!
        user.name = null; // 问题:名字可以被设置为 null!
    }
}

你看,age 可以被设置为负数,name 可以被设置为 null,这显然不符合现实逻辑,对象的状态被破坏了。

Java中set/get方法的具体用法是什么?-图2
(图片来源网络,侵删)

使用 setget 可以完美地解决这些问题。


setget 的基本语法

一个标准的 JavaBean 类通常遵循以下命名和结构规范:

  1. 成员变量必须是 private 的。
  2. 每个私有成员变量都有一个对应的 publicgetter 方法。
  3. 对于可变的成员变量,还需要一个 publicsetter 方法。

语法示例

public class User {
    // 1. 私有成员变量,对外隐藏
    private String name;
    private int age;
    // 2. Getter 方法:用于获取 name 的值
    public String getName() {
        return this.name;
    }
    // 3. Setter 方法:用于设置 name 的值
    public void setName(String name) {
        // 在这里可以添加逻辑检查
        if (name != null && !name.trim().isEmpty()) {
            this.name = name;
        } else {
            System.out.println("名字不能为空或空字符串!");
        }
    }
    // 4. Getter 方法:用于获取 age 的值
    public int getAge() {
        return this.age;
    }
    // 5. Setter 方法:用于设置 age 的值
    public void setAge(int age) {
        // 在这里可以添加逻辑检查,确保年龄是合理的
        if (age > 0 && age < 150) {
            this.age = age;
        } else {
            System.out.println("年龄必须在 1 到 149 之间!");
        }
    }
}

如何使用

public class Main {
    public static void main(String[] args) {
        User user = new User();
        // 使用 setter 方法设置值
        user.setName("Alice");
        user.setAge(30);
        // 使用 getter 方法获取值
        String userName = user.getName();
        int userAge = user.getAge();
        System.out.println("用户名: " + userName); // 输出: 用户名: Alice
        System.out.println("年龄: " + userAge);   // 输出: 年龄: 30
        // 尝试设置非法值
        user.setAge(-100); // 输出: 年龄必须在 1 到 149 之间!
        System.out.println("年龄: " + user.getAge()); // 输出: 年龄: 30 (值没有被修改)
    }
}

从上面的例子可以看出,通过 setter 方法,我们可以在赋值前加入任何我们想要的逻辑(如校验、格式化、触发事件等),从而保证了对象数据的有效性一致性


特殊情况:布尔类型的 Getter

对于 boolean 类型的成员变量,getter 方法的命名有一个小小的不同,它不以 get 开头,而是以 is 开头。

public class Product {
    private String productName;
    private boolean inStock;
    // 标准的 getter
    public String getProductName() {
        return productName;
    }
    // 布尔类型的 getter
    public boolean isInStock() {
        return inStock;
    }
    // setter 保持不变
    public void setInStock(boolean inStock) {
        this.inStock = inStock;
    }
}
// 使用
Product p = new Product();
p.setInStock(true);
boolean isAvailable = p.isInStock(); // 使用 is...() 方法

现代 Java 的演进:finalrecordvar

随着 Java 语言的发展,set/get 的使用方式也在变化。

不可变对象

如果一个对象创建后其状态不应该被改变,我们称之为不可变对象,对于这种对象,我们只需要提供 getter 方法,而不提供 setter 方法,成员变量通常用 final 修饰。

public final class ImmutablePoint {
    private final int x;
    private final int y;
    public ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
    // 只有 getter,没有 setter
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }
}

不可变对象是线程安全的,易于理解和维护,是现代 Java 编程中推荐的设计模式。

record (Java 14+ 引入,Java 16+ 正式发布)

record 是 Java 为创建简单的、不可变的数据载体而引入的一种新类型,它自动为你生成 private final 的成员变量、构造器、getter 方法、equals(), hashCode()toString() 方法。

使用 record,你不再需要手动编写 setget,代码极其简洁。

// 使用 record 定义一个与上面 ImmutablePoint 功能相同的类
public record Point(int x, int y) {
    // 编译器会自动生成所有必要的代码,包括 getX() 和 getY()
}
// 使用
Point p = new Point(10, 20);
int x = p.x(); // 直接通过访问器访问,就像 getter 一样
int y = p.y();
System.out.println("Point is: " + p); // toString() 也自动生成了

Lombok 库

Lombok 是一个非常流行的库,它通过注解来自动生成 settergettertoString()equals() 等样板代码,这极大地减少了重复的代码编写。

import lombok.Getter;
import lombok.Setter;
@Getter // 为所有成员变量生成 getter
@Setter // 为所有成员变量生成 setter
public class LombokUser {
    private String name;
    private int age;
}
// 使用方式与普通类完全一样
public class Main {
    public static void main(String[] args) {
        LombokUser user = new LombokUser();
        user.setName("Bob");
        user.setAge(25);
        System.out.println(user.getName());
    }
}

var (Java 10+ 引入)

var 是一个局部变量类型推断关键字,它不会改变 set/get 的工作原理,但可以让你的代码更简洁。

// 传统写法
User user1 = new User();
user1.setName("Charlie");
// 使用 var
var user2 = new User(); // 编译器自动推断 user2 的类型是 User
user2.setName("David");

特性 描述 优点
private 成员变量 对外隐藏对象的内部状态。 保护数据,防止外部直接、不安全的修改。
public Getter 提供读取私有成员变量的安全通道。 控制对数据的读取,可以在读取时进行计算或转换。
public Setter 提供修改私有成员变量的安全通道。 核心价值:可以在修改前进行数据校验,确保对象状态的有效性一致性
封装 通过 private + public 方法组合实现。 提高了代码的安全性可维护性灵活性
不可变对象 只有 getter,没有 setter,成员变量为 final 线程安全,易于设计和使用。
record / Lombok 现代 Java 提供的简化 set/get 编写的工具。 减少样板代码,提高开发效率。

最佳实践建议:

  1. 永远优先将成员变量设为 private
  2. 除非有特殊原因(如需要修改对象状态),否则总是为 private 成员变量提供 gettersetter
  3. setter 方法中尽可能地加入校验逻辑,这是封装最重要的体现。
  4. 对于不会改变状态的数据,考虑创建不可变对象或使用 record
  5. 在团队项目中,统一使用 Lombok 可以显著提升开发效率和代码整洁度。
分享:
扫描分享到社交APP
上一篇
下一篇