什么是JavaBean?

Ami*_*hum 1677 java serializable javabeans

我认为,我认为"Bean"是一个带有属性和getter/setter的Java类.据我所知,它相当于C结构.真的吗?

另外,bean和普通类之间是否存在真正的语法差异?有没有特殊的定义或界面?

基本上,为什么会有这个术语呢?

编辑:如果您能够如此友善并添加有关Serializable界面的信息,以及它的含义,那么对您的回答,我将非常感激.

hvg*_*des 1881

JavaBean只是一个标准

  1. 私有的所有属性(使用getter/setters)
  2. 公共无参数构造函数
  3. 实施Serializable.

而已.这只是一个惯例.但是很多图书馆依赖它.

关于Serializable,从API文档:

实现java.io.Serializable接口的类启用了类的可序列化.未实现此接口的类将不会将其任何状态序列化或反序列化.可序列化类的所有子类型本身都是可序列化的.序列化接口没有方法或字段,仅用于标识可序列化的语义.

换句话说,可序列化的对象可以写入流,因此文件,对象数据库,任何东西都可以.

此外,JavaBean与另一个类之间没有语法差异 - 如果JavaBean遵循标准,则该类定义JavaBean.

它有一个术语,因为标准允许库以编程方式使用您以预定义方式定义的类实例来执行操作.例如,如果一个库想要传递你传递给它的任何对象,它知道它可以,因为你的对象是可序列化的(假设lib要求你的对象是适当的JavaBeans).

  • 在我看来,几乎所有围绕bean的文档都不能像你一样简洁地描述这个术语.+1 (177认同)
  • @worldsayshi - 不,这不是必需的.例如,bean可以包含String; 和String不是bean.(String是不可变的,所以你不能通过调用空构造函数和setter来创建它.)Serializable对象应该具有Seri​​alizable成员似乎是合理的,除非它以某种方式从外部序列化它们.所以不,Java bean成员不需要拥有Java bean的任何方面.虽然它们更简单*,如果它们也是豆类. (13认同)
  • "所有私有财产"都不正确.属性是从getter和setter推断的(如果有一个方法X getFoo() - > bean有一个名为"foo"的可读属性;如果有一个方法setFoo(X foo) - > bean有一个可写的属性叫做"富").属性可以由成员字段(但不一定是)支持,这些字段通常是私有的. (11认同)
  • bean的成员是否也需要bean?似乎是一个合理的要求.. (10认同)
  • 所以豆类基本上是遵循上述三个标准的POJO ??? (8认同)
  • 我可以看到Java开发人员吹嘘的OOP的每个优势是如何通过尝试解决非生产性问题,Annotations,Reflections,XML,Beans,VM来消除的.多么令人难以置信的语言 (4认同)
  • 我希望成为一个Java bean"一个必须公开的类".它真的需要它应该实现Serializable接口?? (2认同)
  • 听起来好像你不应该声明状态变量final,因为你有一个no-args构造函数.这是正确的吗? (2认同)
  • @ncmathsadist,是的,情况一定是这样。 (2认同)
  • 多谢!为什么我必须到处搜索才能找到这个?为什么人们不能像你一样直接回答你的问题?!​​!对于如此简单的标准来说,这是一个非常不直观的术语。 (2认同)

cHa*_*Hao 275

有一个术语让它听起来很特别.现实远没有那么神秘.

基本上,一个"豆":

  • 是一个可序列化的对象(即,它实现java.io.Serializable,并且正确地执行),即
  • 有"属性",其getter和setter只是具有某些名称的方法(比如说,getFoo()是"Foo"属性的getter),以及
  • 有一个公共0-arg构造函数(因此可以随意创建并通过设置其属性进行配置).

更新:

至于Serializable:这只是一个"标记接口"(一个不声明任何函数的接口)告诉Java实现类同意(并暗示它有能力)"序列化" - 一个转换的过程一个实例到一个字节流.这些字节可以存储在文件中,通过网络连接发送等,并且有足够的信息允许JVM(至少是知道对象类型的那个)稍后重建对象 - 可能在不同的实例中应用程序,甚至是整个其他机器!

当然,为了做到这一点,班级必须遵守某些限制.其中最主要的是所有实例字段必须是基本类型(int,bool等),某些类的实例也可序列化,或者标记为transientJava不会尝试包含它们.(这当然意味着transient字段不会在流上的行程中存活.transient如果需要,应该准备具有字段的类以重新初始化它们.)

不能由那些遵守限制类不应该实现Serializable(和,IIRC,Java编译器甚至不会它这样做.)

  • @ kingfrito_5005:它将是一个或另一个.但是如果它是一个类的实例,那么该类是否可序列化是很重要的.为了使类可序列化,其非"瞬态"部分必须是某些可序列化类型. (8认同)
  • @Amos:不过,当我调查它时,似乎“默认构造函数”在 Java 中与 C++ 中的含义略有不同。:P 将“默认”替换为“0-arg”。 (3认同)

Kam*_*mal 91

JavaBeans是遵循极其简单的编码约定的Java类.你所要做的就是去

  1. 实现java.io.Serializable接口 - 保存对象的状态
  2. 使用公共空参数构造函数 - 实例化对象
  3. 并提供公共getter和setter方法 - 获取和设置私有变量(属性)的值.


小智 59

JavaBeans的属性

JavaBean是一个满足某些编程约定的Java对象:

  1. JavaBean类必须实现SerializableExternalizable

  2. JavaBean类必须具有无参数构造函数

  3. 所有JavaBean属性都必须具有公共setter和getter方法

  4. 所有JavaBean实例变量都应该是私有的

JavaBeans的示例

@Entity
public class Employee implements Serializable{

   @Id
   private int id;
   private String name;   
   private int salary;  

   public Employee() {}

   public Employee(String name, int salary) {
      this.name = name;
      this.salary = salary;
   }
   public int getId() {
      return id;
   }
   public void setId( int id ) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName( String name ) {
      this.name = name;
   }
   public int getSalary() {
      return salary;
   }
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}
Run Code Online (Sandbox Code Playgroud)

  • @giannischristofakis不,注释不是必需的.注释是Spring Framework的一部分,它广泛使用Java Bean. (7认同)
  • @Renato这很简单.想想spring必须用arg-constructor自动实例化你的bean ...它会作为参数传递什么?;) (6认同)
  • 注释是必需的还是Java Bean的一部分? (3认同)

iti*_*skj 21

用例子说明.

1. import java.io.Serializable

至于序列化,请参阅文档.

私人领域

字段应该是私有的,以防止外部类轻松修改这些字段.使用usuagly getter/setter方法而不是直接访问这些字段.

3.构造函数

没有任何参数的公共构造函数.

4. getter/setter

用于访问和修改私有字段的getter和setter方法.

/** 1. import java.io.Serializable */
public class User implements java.io.Serializable {
    /** 2. private fields */
    private int id;
    private String name;

    /** 3. Constructor */
    public User() {
    }
    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    /** 4. getter/setter */
    // getter
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    // setter
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我猜对于`setId(int id)`主体,您的意思是说`this.id = id;`而不是`this.id = is;`。 (2认同)

HAN*_*ANU 18

Java Bean用于更少的代码和更多的工作方法...... Java Bean在整个Java EE中用作运行时发现和访问的通用契约.例如,JavaServer Pages(JSP)使用Java Bean作为页面之间或servlet和JSP之间的数据传输对象.Java EE的JavaBeans Activation Framework使用Java Bean将MIME数据类型的支持集成到Java EE中.Java EE Management API使用JavaBeans作为在Java EE环境中管理资源的工具的基础.

关于序列化:

在对象序列化中,对象可以表示为包含对象数据的字节序列,以及有关对象类型和对象中存储的数据类型的信息.

将序列化对象写入文件后,可以从文件中读取并反序列化,即表示对象及其数据的类型信息和字节可用于在内存中重新创建对象.


Tru*_* Ha 17

在跨多个服务器部署项目时,您会发现序列化很有用,因为bean将被持久化并在它们之间传输.

  • 比如一个带有几个服务器的集群,对于Websphere这个链接http://stackoverflow.com/questions/3193345/how-to-deploye-ear-file-in-websphre-clustered-environment可能会有所帮助. (4认同)
  • 您能否提供有关跨多台服务器部署项目的更多信息?谢谢你 (3认同)

rps*_*rps 15

对于可用作 Java bean 的 Java 类,其方法名称需要符合属性方法事件的 JavaBeans 指南(也称为设计模式) 。该类必须是公共类才能被任何 beanbox 工具或容器访问。容器必须能够实例化它;当类为 public 时,即使没有提供显式的、公共的、零参数的构造函数,容器也应该能够这样做。(没有显式构造函数的 Java 公共类具有默认的公共零参数构造函数。)因此,至少,Java 公共类,即使将属性作为唯一成员(当然,需要伴随公共 getter 和 setter)或公共method作为唯一的成员,是一个Java bean。该属性可以是只读属性(它具有 getter 方法但没有 setter)或只写属性(仅具有 setter 方法)。具有公共事件侦听器注册方法作为唯一成员的 Java 公共类也是 Java bean。JavaBeans规范不\xe2\x80\x99 要求如果此类 Java 类具有显式公共构造函数,则它应该是零参数构造函数。如果可以提供一个包含序列化实例的文件(扩展名为 .ser),beanbox 工具就可以使用该文件来实例化原型 bean。否则,该类将需要一个构造函数,无论是显式的还是默认的,它是公共的且零参数。

\n

一旦 bean 被实例化,JavaBeans API (java.beans.*) 就可以内省它并调用它的方法。如果没有实现 BeanInfo 接口或扩展 BeanInfo 实现的类(例如 SimpleBeanInfo 类)可用,则内省涉及使用反射(隐式内省)来研究目标 bean 支持的方法,然后应用简单的设计模式(指南)从这些方法中推断出支持哪些属性、事件和公共方法。如果实现 BeanInfo 接口的类(对于 Bean Foo,它必须命名为 FooBeanInfo)可用,则 API 会绕过隐式自省并使用此类的公共方法( getPropertyDescriptor()、 getMethodDescriptors()、 getEventSetDescriptors() )来获取信息。如果扩展 SimpleBeanInfo 的类可用,则根据重写哪些 SimpleBeanInfo 公共方法( getPropertyDescriptor()、 getMethodDescriptors()、 getEventSetDescriptors() ),它将使用这些重写的方法来获取信息;对于未被重写的方法,它\xe2\x80\x99将默认为相应的隐式内省。无论如何,bean 都需要实例化,即使没有对其执行隐式内省。因此,需要一个公共零参数构造函数。但是,当然,序列化或外部化接口对于被识别来说并不是必需的。然而,JavaBeans 规范说, \xe2\x80\x98We\xe2\x80\x99d 也喜欢它是 \xe2\x80\x9ctrivial\xe2\x80\x9d 对于一个小 Bean 的常见情况,它只是想拥有它的内部状态已保存,\xe2\x80\x99 不想考虑它。\xe2\x80\x99 因此,所有 bean 都必须实现 Serialized 或Externalized 接口。

\n

总体而言,JavaBeans 规范对于 bean 的构成并不严格且快速。“编写 JavaBeans 组件出奇地简单。您不需要特殊的工具,也不必实现任何接口。编写 Bean 只需遵循某些编码约定即可。您所要做的就是创建您的类看起来像 bean \xe2\x80\x94 使用 bean 的工具将能够识别并使用你的 bean。” 简单地说,即使下面的类也是一个 Java bean,

\n

public class Trivial implements java.io.Serializable {}

\n

到目前为止描述的是Java SE 版本(JavaBeans)。如下所述,Bean 是 Java EE 版本。这些版本是建立在上述基本思想之上的。特别是,他们考虑的一个主要想法是,如果 bean 构造函数确实有一些参数怎么办。这些参数可以是简单类型、类/接口类型或两者。应该有一种方法让容器知道在实例化 bean 时可以替代参数的值。这样做的方法是程序员可以通过注释或 XML 配置文件或两者的组合来配置(指定值)。

\n

春豆

\n

Spring bean 在 Spring IoC 容器中运行。程序员可以通过 XML 配置文件、注释或两者的组合进行配置。

\n

在 Spring 中,如果 bean 构造函数具有简单类型或类/接口类型参数,则可以将值指定为字符串(<value>在前一种情况下作为构造函数参数元素的属性,<idref>在后一种情况下作为构造函数参数元素的元素)以类型安全的方式。引用其他 Spring bean(称为协作者;通过<ref>构造函数参数元素中的元素)基本上是依赖注入,并且也是类型安全的。显然,依赖项(协作者 bean)可能有一个带有注入参数的构造函数;这些注入的依赖项可能有一个带有参数的构造函数等等。此场景最终应在注入的依赖项处终止,这些依赖项是容器可以通过构造实例化的原型 bean。

\n

JSF 托管 Bean

\n

JSF 托管 Bean 在 Web 容器中运行。它们可以使用 @ManagedBean 注释或应用程序配置资源文件 Managed-bean.xml 进行配置。JSF规范仅支持通过资源注入(非类型安全)进行注入。此注入不适合在构造函数上注入。无论如何,规范要求 JSF 托管 Bean 必须具有公共零参数构造函数。进一步指出,\xe2\x80\x9c从本规范的 2.3 版开始,强烈建议不要使用本节中指定的托管 bean 工具。解决相同问题的更好、更内聚的集成解决方案是使用上下文和依赖注入 (CDI),如 JSR-365 中所指定。”换句话说,应该使用 CDI 托管 bean,它确实在构造函数上提供类型安全的依赖注入类似于Spring beans,CDI规范采用了Managed Beans规范,该规范适用于JEE平台的所有容器,而不仅仅是Web层,因此Web容器需要实现CDI规范。

\n

托管 Bean

\n

以下是托管 Bean 规范的摘录\n\xe2\x80\x9c 托管 Bean 是具有最低要求的容器管理对象,\n 也称为首字母缩略词 \xe2\x80\x9cPOJOs\xe2\x80\x9d(普通旧 Java对象)\xe2\x80\xa6它们可以看作是 Java SE 平台上发现的 JavaBeans 组件模型的 Java EE 平台增强版本\xe2\x80\xa6它不会被托管的读者错过\xe2\x80\x99 Bean 的前身是 JavaServer Faces (JSF) 技术\xe2\x80\xa6 中的同名工具。本规范中定义的 Managed Beans 代表了 JSF 中那些工具的泛化;特别是,托管 Bean 可以在 Java EE 应用程序中的任何位置使用,而不仅仅是在 Web 模块中。例如,在基本组件模型中,托管 Bean 必须提供无参构造函数,但是基于托管 Bean 构建的规范(例如 CDI (JSR-299))可以放宽该要求,并允许托管 Bean 为构造函数提供更多功能。复杂的签名,只要它们遵循一些明确定义的规则...托管 Bean 不能是:最终类、抽象类或非静态内部类。与常规 JavaBean 组件不同,托管 Bean 可能无法序列化。\xe2\x80\x9d\n因此,托管 Bean(也称为 POJO 或 POJO beans)的规范允许像 CDI 中那样进行扩展。

\n

CDI 豆

\n

CDI 规范将托管 Bean 重新定义为:\n在 Java EE 中运行时,如果顶级 Java 类满足以下要求,则它就是托管 Bean:

\n

\xe2\x80\xa2 不是内部类。\n\xe2\x80\xa2 是非抽象类,或者被注解@Decorator。\n\xe2\x80\xa2 没有实现 javax.enterprise .inject.spi.Extension。\n\xe2\x80\xa2 它没有注释 @Vetoed 或在注释 @Vetoed 的包中。\n\xe2\x80\xa2 它有一个适当的构造函数,或者:该类有一个构造函数不带参数,或者类声明一个带@Inject注释的构造函数。

\n

所有满足这些条件的 Java 类都是托管 Bean,因此不需要特殊声明来定义托管 Bean。或者

\n

如果任何其他 Java EE 规范将其定义为托管 bean,并且如果

\n

\xe2\x80\xa2 它没有使用 EJB 组件定义注释进行注释,也没有在 ejb-jar.xml 中声明为 EJB bean 类。

\n

Bean 构造函数可以具有简单类型参数,因为可以使用 @Inject 注释注入简单类型。

\n

EJB

\n

EJB 在 EJB 容器中运行。EJB规范规定: \xe2\x80\x9cA 会话 bean 组件是托管 Bean。” \xe2\x80\x9c 该类必须有一个不带参数的公共构造函数,\xe2\x80\x9d 它表示会话 bean 和消息驱动bean。此外,它还说,\xe2\x80\x9c会话bean类不需要实现SessionBean接口或Serialized接口。\xe2\x80\x9d 与JSF bean相同的原因,EJB3依赖注入基本上是资源注入,JSF beans不支持带参数的构造函数,即通过依赖注入。但是,如果EJB容器实现CDI,\xe2\x80\x9c可选:该类可能有一个用Inject注释注释的附加构造函数, \xe2\x80\x9c 它表示会话 bean 和消息驱动 bean,因为 \xe2\x80\x9c 打包到 CDI bean 存档中且未使用 javax.enterprise.inject.Vetoed 注释进行注释的 EJB 被视为 CDI -启用的bean。\xe2\x80\x9d

\n

  • 这个答案值得更多的赞成。它不仅澄清了对 JavaBeans 的一些误解(例如,公共零参数构造函数只是约定,而不是规范允许的唯一选项),而且它将 JavaBeans 与许多其他常见的 bean 进行了比较,以提供更广泛的上下文。总结得很好。 (3认同)

Bil*_*l K 11

只是关于 bean 概念的一些背景/更新。许多其他答案实际上有什么,但没有那么多为什么。

它们是早期在 Java 中作为构建 GUI 的一部分而发明的。它们遵循易于工具拆分的模式,让它们创建一个属性面板,以便您可以编辑 Bean 的属性。一般来说,Bean 属性代表屏幕上的一个控件(想想 x,y,width,height,text,..)

您也可以将其视为强类型数据结构。

随着时间的推移,这些对于使用相同类型访问的许多工具变得有用(例如,将数据结构持久化到数据库的 Hibernate)

随着工具的发展,他们更多地转向注释,而不是将 setter/getter 名称分开。现在大多数系统不需要 bean,它们可以使用任何带有注释属性的普通旧 Java 对象来告诉它们如何操作它们。

现在我将 bean 视为带注释的属性球——它们实际上只对它们携带的注释有用。

豆类本身并不是一种健康的模式。它们本质上破坏了封装,因为它们将所有属性暴露给外部操作,并且在使用它们时,有一种趋势(绝不是要求)创建代码来从外部操作 bean,而不是在 bean 内部创建代码(违反“don不是要求一个对象的价值,而是要求一个对象为你做某事”)。使用带有最少 getter 且没有 setter 的带注释的 POJO 更像是 OO 恢复封装和具有不变性的可能性。

顺便说一句,随着所有这些事情的发生,有人将这个概念扩展到称为 Enterprise Java Beans 的东西。这些是……不同的。而且它们非常复杂,以至于很多人觉得他们没有理解整个 Bean 的概念并停止使用这个术语。我认为,这就是为什么您通常会听到 bean 被称为 POJO(因为每个 Java 对象都是 POJO,这在技术上是可以的,但是当您听到有人说 POJO 时,他们通常会想到遵循 bean 模式的东西)


Dig*_*nta 9

根据维基百科:

  1. 该类必须具有公共默认构造函数(不带参数).这允许在编辑和激活框架内轻松实例化.

  2. 根据标准命名约定,必须使用get,set,is(可用于布尔属性而不是get)以及其他方法(所谓的访问器方法和mutator方法)来访问类属性.这允许在框架内轻松自动检查和更新bean状态,其中许多包括用于各种类型属性的自定义编辑器.Setter可以有一个或多个参数.

  3. 该类应该是可序列化的.[这允许应用程序和框架以独立于VM和平台的方式可靠地保存,存储和恢复bean的状态.

有关更多信息,请点击此链接.

  • 我很确定OP(和我们大多数人)来这里是为了解释而不是复制粘贴文本 (3认同)

Vic*_*tor 9

Java Bean是一种标准,其基本语法要求已由其他答案清楚地解释.

但是,IMO,它不仅仅是一个简单的语法标准.Java Bean的真正含义或预期用途是与标准周围的各种工具支持一起,以促进代码重用和基于组件的软件工程,即使开发人员能够通过组装现有组件(类)来构建应用程序,而无需编写任何代码(或只需编写一些胶水代码).不幸的是,这种技术被业界低估和利用不足,可以从这个问题的答案中得知.

如果您阅读Oracle 关于Java Bean教程,您可以更好地理解它.


Mik*_*ike 7

关于问题的第二部分,序列化是一种持久性机制,用于将对象存储为一系列带符号的字节.不太正式,它存储对象的状态,以便您可以稍后通过反序列化来检索它.


Rag*_*tra 7

Java Bean是一个java类[概念],应遵循以下约定:

  1. 它应该有一个无参数的构造函数.
  2. 它应该是Serializable.
  3. 它应该提供设置和获取属性值的方法,称为getter和setter方法.

它是一个可重用的软件组件.它可以将许多对象封装到一个对象中,这样就可以从多个位置访问同一个对象,这是向容易维护代码迈出的一步.


Bal*_*wat 6

它们是可序列化的,具有零参数构造函数,并允许使用getter和setter方法访问属性."Bean"这个名称包含了这个标准,旨在为Java创建可重用的软件组件.according to 维基

构成应用程序主干并由Spring IoC容器管理的对象称为bean.bean是一个由Spring IoC容器实例化,组装和管理的对象.否则,bean只是应用程序中许多对象之一. according to 春天io.


vle*_*leo 6

上面重复了 6 或 7 次,JavaBean 需要无参构造函数。

这是错误的,没有这样的要求,特别是在 Java Spring 的上下文中。

描述 JavaBeanns API 的规范版本 (1.01) 中也没有提及该要求 ( https://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/)。更重要的是 - 本规范在以下上下文中仅提到“空构造函数”两次:“每个定制器都应该有一个空构造函数。” “每个 PropertyEditor 都应该有一个 null 构造函数。”

因此,规范的作者似乎并不知道或不愿意使用术语“空构造函数”,但仍然没有在 JavaBeans 中提及它。