我认为“Bean”是一个具有属性和Getter/Setter的Java类。据我所知,它相当于C语言中的结构体。这是真的吗?
此外,JavaBean与普通类之间是否存在真正的语法区别?
是否有特殊的定义或接口?
基本上,为什么会有这个术语?
另外,“Serializable”接口是什么意思?
我认为“Bean”是一个具有属性和Getter/Setter的Java类。据我所知,它相当于C语言中的结构体。这是真的吗?
此外,JavaBean与普通类之间是否存在真正的语法区别?
是否有特殊的定义或接口?
基本上,为什么会有这个术语?
另外,“Serializable”接口是什么意思?
class
,但它遵循某些约定:
Serializable
。Serializable
,来自API文档:
换句话说,可序列化对象可以写入流,因此可以写入文件、对象数据库等任何地方。类的可序列化由类实现java.io.Serializable接口启用。没有实现此接口的类将不会序列化或反序列化其任何状态。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
这个术语是有的,因为标准允许库以预定义的方式编程处理您定义的类实例。例如,如果一个库想要流式传输您传递给它的任何对象,它知道可以这样做,因为您的对象是可序列化的(假设该库要求您的对象是正确的JavaBeans)。
这个术语让它听起来很特别,但实际上并没有那么神秘。
基本上,一个“Bean”:
java.io.Serializable
接口,并且正确地执行了该操作),它具有getFoo()
是“Foo”属性的getter)的方法,以及至于Serializable
:那只是一个“标记接口”(一个不声明任何函数的接口),告诉Java实现类同意(并暗示其能力)进行“序列化”--将一个实例转换为字节流。 这些字节可以存储在文件中,通过网络连接发送等,并且具有足够的信息以允许JVM(至少是知道对象类型的JVM)稍后重构该对象--可能在应用程序的另一个实例甚至整个其他计算机上!
当然,为了做到这一点,该类必须遵守某些限制。 其中最重要的是,所有实例字段必须是原始类型(int,bool等),某些也可序列化的类的实例,或标记为transient
以使Java不尝试包括它们。 (这当然意味着transient
字段无法通过流进行旅行。具有transient
字段的类应准备根据需要重新初始化它们。)
不能遵守这些限制的类不应实现Serializable
(并且,如果我没记错的话,Java编译器甚至不会允许它这样做。)
transient
部分必须是可序列化类型。” - cHaoJavaBeans是符合极其简单的编码规范的Java类。
java.io.Serializable
接口 - 用于保存对象的状态JavaBean的属性
JavaBean是一个满足特定编程约定的Java对象:
JavaBean类必须实现Serializable
或Externalizable
接口
JavaBean类必须有一个无参构造函数
所有JavaBean属性必须具有公共的setter和getter方法
所有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;
}
}
举个例子来解释。
1. 导入java.io.Serializable
关于序列化,可以查看文档。
2. 私有字段
字段应该是私有的,以防止外部类轻易地修改这些字段。通常使用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;
}
}
setId(int id)
方法的方法体,我猜你想说的是 this.id = id;
而不是 this.id = is;
。 - steven7mwesigwaJava Beans 被用来实现少代码多工作的方法...
Java Beans 在 Java EE 中被广泛地用作运行时发现和访问的通用契约。例如,JavaServer Pages (JSP) 使用 Java Beans 作为页面或 servlet 与 JSP 之间数据传输对象的一种方式。Java EE 的 JavaBeans Activation Framework 利用 Java Beans 将对 MIME 数据类型的支持集成到 Java EE 中。Java EE 管理 API 则将 JavaBeans 作为在 Java EE 环境中管理资源仪表化的基础。
关于序列化:
在对象序列化中,一个对象可以被表示为一个字节序列,包括了对象的数据以及关于对象类型和存储在对象中的数据类型的信息。
当一个序列化对象已经被写入文件后,它可以从文件中读取并进行反序列化,即使用类型信息和代表对象及其数据的字节来重新创建对象。
对于Bean概念的一些背景和更新说明。其他答案通常涵盖了Bean的"是什么",但缺乏足够的"为什么"。
早期Java中的GUI构建过程中,Bean被发明出来。它们遵循易于工具拆分的模式,可以创建属性面板,以便您可以编辑Bean的属性。总的来说,Bean属性代表屏幕上的控件(例如x、y、width、height、text等)。
您还可以将其视为强类型数据结构。
随着时间的推移,这些Bean变得对许多使用相同类型访问的工具非常有用(例如,Hibernate将数据结构持久化到数据库中)。
随着工具的演变,它们更趋向于注释,而不是分离setter/getter名称。现在大多数系统不需要Beans,它们可以使用带有注释属性的任何普通的Java对象告诉它们如何操作。
现在我将Bean视为带注释的属性球——它们实际上只有携带注释时才有用。
本身,Java Beans 并不是一种健康的模式,因为它们的本质破坏了封装性,由于将所有属性暴露给外部操作,使用时往往会倾向于创建用于外部操纵 bean 的代码而非在 bean 内部创建代码(违反了“不要问一个对象的值,而是要求对象为你做某事”的原则)。使用带注释的 POJOs(简单 Java 对象)并最小化 getter 函数和不使用 setter 函数更符合面向对象的设计思想,恢复了封装性并提供了不可变性。
顺便说一下,在所有这些事情发生时,有人将这个概念扩展到被称为企业级 JavaBeans 的东西。这些是……不同的。它们足够复杂,以至于许多人觉得他们不理解整个 Bean 概念,因此停止使用该术语。我认为这就是为什么通常听到 beans 被称为 POJOs(由于每个 Java 对象都是 POJO,因此从技术上讲这是可以接受的,但当你听到有人说 POJO 时,他们大多数时候在思考遵循 bean 模式的某些东西)。
在将您的项目部署到多个服务器时,您会发现序列化非常有用,因为bean将被持久化并在它们之间传输。
public class Trivial implements java.io.Serializable {}
到目前为止的描述是Java SE版本(JavaBeans)。下面所述的beans是Java EE版本。这些版本基于上面解释的基本思想构建而成。特别地,它们考虑的一个主要思想是,如果一个bean构造函数有一些参数怎么办。这些参数可以是简单类型、类/接口类型或两者都有。应该有一种方式让容器知道可以替代参数的值,当实例化bean时。程序员可以通过注解、XML配置文件或两者混合来进行配置(指定值)。JSF管理的bean在Web容器中运行。它们可以通过@ManagedBean注释或应用程序配置资源文件managed-bean.xml进行配置。JSF规范仅支持通过资源注入(不是类型安全的)进行注入。此注入不适合构造函数注入。无论如何,规范要求JSF管理的bean必须具有公共的零参数构造函数。此外,规范指出:“从本规范的2.3版开始,强烈不建议使用本节中指定的托管bean工具。解决同样问题的更好、更具凝聚力的集成方案是使用上下文和依赖注入(CDI),如JSR-365中所指定。”换句话说,应该使用CDI托管的bean,其提供类似于Spring bean的构造函数类型安全依赖注入。CDI规范采用了托管bean规范,该规范适用于JEE平台的所有容器,而不仅仅是Web层。因此,Web容器需要实现CDI规范。
托管Bean
这是托管Bean规范的一部分摘录:“托管Bean是最小要求的容器管理对象,也被称为“POJOs”(普通旧Java对象)……它们可以被看作是在Java SE平台上找到的JavaBeans组件模型的Java EE平台增强版本……读者不会错过托管Bean在JavaServer Faces(JSF)技术中发现的同名设施的前身……在本规范中定义的托管Bean代表了JSF中发现的托管Bean的泛化;特别是,托管Bean可以在Java EE应用程序的任何地方使用,而不仅仅是在Web模块中。例如,在基本组件模型中,托管Bean必须提供一个无参数构造函数,但是建立在托管Bean之上的规范(如CDI(JSR-299))可以放松该要求,并允许托管Bean提供具有更复杂签名的构造函数,只要它们遵循一些明确定义的规则……托管Bean不能是:final类、抽象类或非静态内部类。与常规JavaBean组件不同,托管Bean可能不可序列化。”因此,托管Bean的规范,也被称为POJOs或POJO Bean,允许像CDI这样的扩展。 CDI规范重新定义托管Bean为:在Java EE中运行时,顶级Java类满足以下要求,则为托管Bean:• 它不是内部类。 • 它是一个非抽象类,或者被标注为@Decorator。 • 它没有实现javax.enterprise.inject.spi.Extension。 • 它没有被标注为@Vetoed,或者在被标注为@Vetoed的包中。 • 它有一个合适的构造函数,要么:这个类有一个没有参数的构造函数,要么这个类声明了一个被标注为@Inject的构造函数。
所有符合这些条件的Java类都是托管Bean,因此不需要特殊声明来定义托管Bean。或者
如果它被任何其他Java EE规范定义为托管Bean,并且如果
• 它没有被EJB组件定义注释标注或在ejb-jar.xml中声明为EJB bean类。
Bean构造函数可以具有简单类型参数,因为简单类型可以使用@Inject注释进行注入。
EJBs
EJB运行在EJB容器中。EJB规范指出:“会话Bean组件是托管Bean。”“对于会话Bean和消息驱动Bean,它说:‘该类必须有一个不带参数的公共构造函数。’ 此外,它说:“会话Bean类不需要实现SessionBean接口或Serializable接口。”由于JSF Bean相同的原因,即EJB3依赖注入基本上是资源注入,JSF Bean不支持带有参数的构造函数,即通过依赖注入。然而,如果EJB容器实现了CDI,“可选地:该类可以具有使用@Inject注释的附加构造函数,”它对于会话Bean和消息驱动Bean都有所说明,因为“打包到CDI bean存档中且未注释javax.enterprise.inject.Vetoed注释的EJB被视为启用CDI的bean。”JavaBeans是一种标准,其基本语法要求已经被其他答案清晰地解释过了。
然而,在我看来,它不仅仅是一个简单的语法标准。JavaBeans的真正含义或旨在使用,与该标准周围的各种工具支持一起,是为了促进代码重用和组件化软件工程,即使开发人员能够通过组装现有组件(类)来构建应用程序,而无需编写任何代码(或只需要编写少量粘合代码)。不幸的是,这项技术在工业界被严重低估和低效利用,这可以从本文中的回答中得知。
如果您阅读Oracle的JavaBeans教程,您就可以更好地了解它。