Java bean 是个什么概念?

本文通过一个Java单向链表类的例子说明了JavaBean的重要性及其如何帮助开发者维护向后兼容性。同时对比了Java与其他现代编程语言如C#、Scala在此方面的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



Java语言欠缺属性、事件、多重继承功能。所以,如果要在Java程序中实现一些面向对象编程的常见需求,只能手写大量胶水代码。Java Bean正是编写这套胶水代码的惯用模式或约定。这些约定包括getXxx、setXxx、isXxx、addXxxListener、XxxEvent等。遵守上述约定的类可以用于若干工具或库。

举个例子,假如有人要用Java实现一个单向链表类,可能会这样写:
// 编译成 java-int-list_1.0.jar
public final class JavaIntList {
  static class Node {
    public Node next;
    public int value;
  }
  public Node head;
  public int size;
}
上述实现为了能够快速获取链表的大小,把链表大小缓存在size变量中。用法如下:
JavaIntList myList = new JavaIntList();
System.out.println(myList.size);
JavaIntList的作者很满意,于是开源了java-int-list库的1.0版。文件名是java-int-list_1.0.jar。发布后,吸引了许多用户来使用java-int-list_1.0.jar。
有一天,作者决定要节省内存,不要缓存size变量了,把代码改成这样:
// 编译成 java-int-list_2.0.jar
public final class JavaIntList {
  static final class Node {
    public Node next;
    public int value;
  }
  public Node head;
  public int getSize() {
    Node n = head;
    int i = 0;
    while (n != null) {
      n = n.next;
      i++;
    }
    return i;
  }
}

然后发布了2.0版:java-int-list_2.0.jar。发布后,原有java-int-list_1.0.jar的用户纷纷升级版本到2.0。这些用户一升级,就发现自己的程序全部坏掉了,说是找不到什么size变量。于是这些用户就把作者暴打一顿,再也不敢用java-int-list库了。

这个故事告诉我们,如果不想被暴打致死,你就必须保持向后兼容性。太阳公司在设计Java语言时,也懂得这个道理。所以Java标准库中,绝对不会出现public int size这样的代码,而一定会一开始就写成:
private int size;
public int getSize() { return size; }

让用户一开始就使用getSize,以便有朝一日修改getSize实现时,不破坏向后兼容性。这种public int getSize() { return size; }的惯用手法,就是Java Bean。

现在是2014年,C#、Scala等比Java新的面向对象语言自身就提供了语言特性来实现这些常用需求,所以根本不需要Java Bean这样繁琐的约定。

比如,假如有个Scala版的ScalaIntList:
// 编译成 scala-int-list_1.0.jar
object ScalaIntList {
  final case class Node(next: Node, value: Int)
}
final class ScalaIntList {
  var head: ScalaIntList.Node = null
  var size: Int = 0
}
用户这样用:
val myList = new ScalaIntList
println(myList.size)
有一天你心血来潮改成这样:
// 编译成 scala-int-list_2.0.jar
object ScalaIntList {
  final case class Node(next: Node, value: Int)
}
final class ScalaIntList {
  var head: ScalaIntList.Node = null
  final def size: Int = {
    var n = head
    var i = 0
    while (n != null) {
      n = n.next
      i++
    }
    i
  }
}

用户还是照样能用,根本不破坏向后兼容性。所以Scala程序只要不考虑和Java交互,一般就不需要类似Java Bean这样的约定。

顺便说一句,向后兼容性分为源代码级和二进制级,Scala的var或val改为final def的话,无论源代码级的向后兼容性,还是二进制级的向后兼容性,都不遭受破坏。但C#的字段改为属性的话,虽然不破坏源代码级的向后兼容性,但是会破坏二进制级的向后兼容性。这是C#的设计缺陷,导致微软的编码规范不得不禁止使用公有字段。
### Java Bean 概念 Java Bean 是一种基于 Java 编写的可重用组件,它遵循一定的编码规范。具体而言,Java Bean 是一个具体的、公共的类,并且拥有无参构造函数[^2]。它的核心特点在于通过 `getter` 和 `setter` 方法对外部隐藏内部数据结构的同时允许访问和修改其属性。 #### 特性 1. **封装性**:所有的字段都应声明为私有(private),并通过公共的 getter 和 setter 方法进行访问。 2. **无参构造器**:为了便于实例化对象Java Bean 必须提供一个无参的公共构造方法。 3. **序列化支持**:通常建议让 Java Bean 实现 `Serializable` 接口以便能够存储到文件或者在网络上传输。 4. **符合命名约定**:对于布尔类型的属性,除了标准的 get/is 前缀外,还可以使用 set 进行赋值操作。 例如,下面是一个简单的 Java Bean 示例: ```java public class Person implements java.io.Serializable { private String name; private int age; // 无参构造器 public Person() {} // Getter and Setter methods public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } ``` 此代码片段展示了如何构建一个基本的 Java Bean 类型——Person[^2]。 --- ### Spring Framework 中的 Bean 在 Spring 框架里,“Bean”特指由 IoC (Inversion of Control) 容器管理的对象实体。Spring 提供了多种方式来定义 Beans 并控制它们的行为,包括但不限于 XML 配置文件以及注解驱动的方式[@Component,@Service,@Repository 等][^5]。 #### Scope 属性 - **Singleton**: 默认的作用范围,默认情况下每个容器只会存在唯一的一个 Bean 实例。当多个线程同时调用同一个 Singleton Bean 时可能存在并发问题,除非它是无状态的[^3]。 - **Prototype**: 每次请求都会生成新的 Bean 实例,因此不会遇到共享状态带来的同步难题。 #### 注入依赖关系 借助于自动装配功能 (`@Autowired`) 及限定符(`@Qualifier`),开发者可以在运行期动态决定哪个具体的实现应该被注入到目标组件之中[^4]。 示例展示如下: ```java @Component public class AnotherBean { private final MyBean myBean; @Autowired public AnotherBean(@Qualifier("myBeanName") MyBean myBean) { this.myBean = myBean; } // Other logic... } ``` 这里演示了一个典型的场景,即通过构造函数注入指定名为 `"myBeanName"` 的 Bean 到当前上下文中。 --- ### 总结 无论是传统的 Java Bean 还是现代框架下的 Spring Bean,两者均强调良好的面向对象编程实践原则,如高内聚低耦合的设计理念。理解并熟练运用这些基础知识有助于提升软件开发效率与质量。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值