java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java get和set方法

Java 中 get 和 set 方法详解及实现细节

作者:祈祷苍天赐我java之术

本文详细介绍了Java中get和set方法的使用,包括它们在面向对象编程中的作用、命名规范、实现细节、使用场景以及常见问题的解决方案,通过遵循这些最佳实践,可以提高代码的可维护性、封装性和可读性,感兴趣的朋友跟随小编一起看看吧

一、get 和 set 方法的基础认知

1.1 定义与作用

get 方法(访问器)和 set 方法(修改器)是面向对象编程中实现封装的关键技术。它们提供了一种标准化的方式来访问和修改类的私有成员变量。在 Java 等面向对象语言中,为了实现良好的封装性,通常会将类的成员变量声明为 private,然后通过 public 的 get 和 set 方法来操作这些变量。

这种设计模式具有以下特点:

示例:一个完整的 User 类实现

public class User {
    // 私有成员变量
    private String name;
    private int age;
    private String email;
    // get方法:获取name的值
    public String getName() {
        return name;
    }
    // set方法:设置name的值
    public void setName(String name) {
        this.name = name;
    }
    // 可以添加更多getter和setter方法
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
}

1.2 为什么需要 get 和 set 方法

虽然直接将成员变量声明为 public 可以简化代码编写,但这种做法会导致严重的设计问题:

public void setAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException("年龄不能为负数");
    }
    this.age = age;
}
public String getName() {
    System.out.println("访问了name属性");
    return name;
}
public synchronized String getName() {
    return name;
}

通过 get 和 set 方法,开发人员可以在不暴露内部实现的前提下,安全地提供变量的访问和修改通道,同时保持对数据访问的完全控制。这种模式是现代面向对象编程的最佳实践之一。

二、get 和 set 方法的命名规范

遵循规范的命名方式是写出可维护、易读代码的基础。在 Java 中,get 和 set 方法作为访问对象属性的标准方式,有着严格的命名约定。这些约定不仅被广泛认可,也是 JavaBean 规范的重要组成部分。

2.1 基本命名规则详解

get 方法命名规则

对于非布尔类型的变量:

对于布尔类型的变量:

set 方法命名规则

适用于所有变量类型:

2.2 命名示例与应用场景

public class Person {
    // 成员变量声明
    private String name;     // 字符串类型
    private int age;         // 整型
    private boolean married; // 布尔类型
    // 正确的get/set方法命名示例
    // 非布尔类型的getter
    public String getName() { 
        return name; 
    }
    // 非布尔类型的setter
    public void setName(String name) { 
        this.name = name; 
    }
    // 非布尔类型的getter
    public int getAge() { 
        return age; 
    }
    // 非布尔类型的setter
    public void setAge(int age) { 
        this.age = age; 
    }
    // 布尔类型的getter(使用is前缀)
    public boolean isMarried() { 
        return married; 
    } 
    // 布尔类型的setter
    public void setMarried(boolean married) { 
        this.married = married; 
    }
}

实际应用中的注意事项

  1. 一致性:在整个项目中应保持命名风格一致
  2. 特殊情况处理
    • 对于缩写词(如ID),应保持首字母大写(如getID()而非getId()
    • 对于多个单词组成的变量名,每个单词首字母都应大写(如getFirstName()
  3. IDE支持:现代IDE(如IntelliJ IDEA、Eclipse)都提供自动生成getter/setter的功能,可以确保遵循规范

遵循这些命名规范不仅使代码更易读,还能确保与各种框架(如Spring、Hibernate)的良好兼容性。

三、get 和 set 方法的实现细节

3.1 参数与返回值

set 方法

get 方法

3.2 方法体中的常见操作

在实际开发中,get 和 set 方法的方法体往往不只是简单的赋值和返回,还可能包含以下高级用法:

3.2.1 参数验证

在 set 方法中可以加入业务逻辑验证,确保数据有效性:

public void setAge(int age) {
    // 验证年龄范围
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException("年龄必须在0-150之间");
    }
    // 验证通过后才赋值
    this.age = age;
}

其他验证示例:

3.2.2 触发事件

当变量值改变时,可以触发相关业务逻辑:

private String address;
public void setAddress(String address) {
    // 保存旧值用于比较
    String oldAddress = this.address;
    this.address = address;
    // 只有地址真正改变时才触发通知
    if (!Objects.equals(oldAddress, address)) {
        notifyAddressChanged();
    }
}
private void notifyAddressChanged() {
    // 实际业务逻辑可能包括:
    // 1. 记录变更日志
    // 2. 发送MQ消息通知其他系统
    // 3. 更新相关缓存
    System.out.println("地址已更新为:" + this.address);
}

典型应用场景:

3.2.3 延迟加载

在 get 方法中实现资源的按需初始化:

private List<String> hobbies;
public List<String> getHobbies() {
    // 第一次访问时才初始化
    if (hobbies == null) {
        hobbies = new ArrayList<>();
        // 可以添加默认值
        hobbies.add("阅读");
        hobbies.add("运动");
    }
    return Collections.unmodifiableList(hobbies); // 返回不可修改的视图
}

其他延迟加载场景:

注意事项:

四、get 和 set 方法的使用场景

4.1 JavaBean 规范详解

JavaBean 规范是 Java 平台中用于创建可重用组件的标准规范,其核心要求包括:

public class User {
    // 类实现
}
public User() {} // 默认构造方法

属性访问规范

private String name;
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}

4.2 序列化与反序列化机制

private transient String password; // 不会被默认序列化
@JsonIgnore
public String getPassword() { // 显式排除
    return password;
}

4.3 主流框架集成原理

Spring 框架集成

依赖注入:通过 setter 方法注入依赖对象

@Autowired
public void setService(UserService service) {
    this.service = service;
}

配置绑定:@ConfigurationProperties 通过 setter 绑定配置

MyBatis 结果映射

<resultMap id="userMap" type="User">
    <result property="name" column="user_name"/>
</resultMap>
public void setAge(int age) {
    if(age < 0) throw new IllegalArgumentException();
    this.age = age;
}

模板引擎支持
Thymeleaf、JSP EL 表达式等视图技术都依赖 getter 方法访问属性:

<div th:text="${user.name}">...</div>

五、使用 get 和 set 方法的注意事项

5.1 不要过度使用

在面向对象编程中,并非所有的成员变量都需要提供 get 和 set 方法,过度使用会破坏封装性:

5.2 避免在 get/set 方法中执行耗时操作

get 和 set 方法应该保持简洁高效,遵循最小惊讶原则:

5.3 注意封装性

private List<String> tags = new ArrayList<>();
// 危险做法:外部可以直接修改内部集合
public List<String> getTags() {
    return tags; 
}
// 安全做法1:返回防御性副本
public List<String> getTags() {
    return new ArrayList<>(tags);
}
// 安全做法2:返回不可修改视图(Java)
public List<String> getTags() {
    return Collections.unmodifiableList(tags);
}
// 安全做法3:使用不可变集合(Guava)
public ImmutableList<String> getTags() {
    return ImmutableList.copyOf(tags);
}

5.4 注意线程安全

在多线程环境下,get/set方法需要特别考虑:

六、get 和 set 方法的自动化工具

手动编写 get 和 set 方法不仅繁琐,还容易出错,特别是在处理大型类时,需要为每个字段都编写对应的访问方法,既浪费时间又增加了代码维护难度。在实际开发中,我们可以利用以下工具自动生成这些方法,提高开发效率:

6.1 IDE 自带功能

主流 IDE 都提供了快速生成 getter 和 setter 的功能:

6.2 Lombok 框架

Lombok 是一个 Java 库,通过注解自动生成 getter 和 setter 方法,极大简化代码:

import lombok.Getter;
import lombok.Setter;
// 类级别注解
@Getter @Setter
public class User {
    private String name;
    private int age;
    // 字段级注解
    @Getter(AccessLevel.PROTECTED) 
    private String password;
}

使用 Lombok 需要:

  1. 在项目中引入依赖(Maven/Gradle)
  2. 在 IDE 中安装 Lombok 插件(否则会显示编译错误)
  3. 启用注解处理(部分 IDE 需要额外配置)

Lombok 还支持生成构造器、toString()、equals()等方法,可以显著减少样板代码。

七、常见问题与解决方案

7.1 命名错误导致框架无法识别

当 getter/setter 方法命名不规范时,许多依赖反射机制的框架(如 Spring、Hibernate、Jackson 等)将无法正确识别和操作对象的属性。

常见问题表现:

解决方法:

  1. 严格遵循 JavaBean 命名规范:
    • getter 方法:getXxx()(布尔属性可以用 isXxx()
    • setter 方法:setXxx(参数类型 value)
  2. 使用 IDE 自动生成方法:
    • 在 IntelliJ IDEA 中:右键 → Generate → Getter and Setter
    • 在 Eclipse 中:Source → Generate Getters and Setters
  3. 使用 Lombok 注解自动生成:
    @Getter @Setter
    private String name;
    

7.2 子类覆盖父类的 get/set 方法

public class Parent {
    public Number getValue() {
        return 0;
    }
}
public class Child extends Parent {
    @Override
    public Integer getValue() { // 合法,Integer 是 Number 的子类
        return 1;
    }
}

7.3 循环依赖问题

在 getter/setter 方法中调用其他对象的方法时,容易形成循环依赖,导致以下问题:

典型场景:

class A {
    private B b;
    public B getB() {
        if(b == null) {
            b = new B();
            b.setA(this); // 循环设置
        }
        return b;
    }
}
class B {
    private A a;
    public A getA() {
        if(a == null) {
            a = new A();
            a.setB(this); // 循环设置
        }
        return a;
    }
}

到此这篇关于Java 中 get 和 set 方法详解(更新版)的文章就介绍到这了,更多相关java get和set方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文