在搜索关于 Java Bean 的相关知识,在知乎上看到一篇非常不错回答。 这个回答有点类似于之类 WY 的博客中看到的,那里面的事例也很好的讲述了关于 Java Bean 的概念,虽然作者没有说明那是 Java Bean ,那其实那就是 Java Bean 的定义。
知乎:
问题:Java bean 是个什么概念?
回答一:
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;
}
JavaIntList myList = new JavaIntList();
System.out.println(myList.size);
有一天,作者决定要节省内存,不要缓存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;
}
}
这个故事告诉我们,如果不想被暴打致死,你就必须保持向后兼容性。太阳公司在设计Java语言时,也懂得这个道理。所以Java标准库中,绝对不会出现public int size这样的代码,而一定会一开始就写成:
private int size;
public int getSize() { return size; }
现在是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的var或val改为final def的话,无论源代码级的向后兼容性,还是二进制级的向后兼容性,都不遭受破坏。但C#的字段改为属性的话,虽然不破坏源代码级的向后兼容性,但是会破坏二进制级的向后兼容性。这是C#的设计缺陷,导致微软的编码规范不得不禁止使用公有字段。
回答二:
简单来讲,JavaBean本身就是Java类,只不过要按照一定的格式书写:
- 实现了java.io.Serializable接口
- 提供无参数的构造器
- 使用getter 和 setter方法访问它的属性
public class Person implements java.io.Serializable {
/* Properties */
private String name = null;
private int age = 0;
/* Empty Constructor */
public Person() {}
/* Getter and Setter Methods */
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public int getAge() {
return age;
}
public void setAge(int i) {
age = i;
}
}
这就是一个简单的JavaBean 。
这样写有什么好处呢?(对于你理解的范围来讲,)当你后端写了Person这样一个Bean的时候,你就可以在前端的jsp页面里:
用标记:
jsp:useBean id="zhangsan" class="Person"来创建Bean的一个实例;用标记
jsp:getProperty name="zhangsan" property="age"来取得这个实例的age属性。
回答三:
Stack Overflow看到的答案,我觉得应该能完美回答你:
主要区分三个:JavaBean,EJB,POJO。
JavaBean
JavaBean是公共Java类,但是为了编辑工具识别,需要满足至少三个条件:
- 有一个public默认构造器(例如无参构造器,)
- 属性使用public 的get,set方法访问,也就是说设置成private,同时get,set方法与属性名的大小也需要对应。例如属性name,get方法就要写成,public String getName(){},N大写。
- 需要序列化。这个是框架,工具跨平台反映状态必须的
EJB
在企业开发中,需要可伸缩的性能和事务、安全机制,这样能保证企业系统平滑发展,而不是发展到一种规模重新更换一套软件系统。 然后有提高了协议要求,就出现了Enterprise Bean。
EJB在javabean基础上又提了一些要求,当然更复杂了。
POJO
有个叫Josh MacKenzie人觉得,EJB太复杂了,完全没必要每次都用,所以发明了个POJO,POJO是普通的javabean,什么是普通,就是和EJB对应的。
总之,区别就是,你先判断是否满足javabean的条件,然后如果再实现一些要求,满足EJB条件就是EJB,否则就是POJO。
王垠在他的博客中讲到面向对象编程语言时候的一些观点:
如果你看透了表面现象就会发现,其实“面向对象编程”本身没有引入很多新东西。所谓“面向对象语言”,其实就是经典的“过程式语言”(比如Pascal),加上一点点抽象能力。所谓“类”和“对象”,基本是过程式语言里面的记录(record,或者叫结构,structure),它的本质就是一个从名字到数据的“映射表”(map)。你可以用名字从这个表里面提取相应的数据。比如point.x,就是用名字'x'从记录point里面提取相应的数据。这比起数组来是一件很方便的事情,因为你不需要记住存放数据的下标。即使你插入了新的数据成员,仍然可以用原来的名字来访问已有的数据,而不用担心下标错位的问题。
所谓“对象思想”(区别于“面向对象”),实际上就是对这种数据访问方式的进一步抽象。一个经典的例子就是平面点的数据结构。如果你把一个点存储为:
struct Point { double x; double y; }
那么你用point.x和point.y可以直接访问它的X和Y坐标。但你也可以把它存储为极坐标方式:
struct Point { double r; double angle; }
那么你可以用point.r和point.angle访问它的模和角度。可是现在问题来了,如果你的代码开头把Point定义为第一种XY的方式,使用point.x, point.y访问X和Y坐标,可是后来你决定改变Point的存储方式,用极坐标,你却不想修改已有的含有point.x和point.y的代码,怎么办呢?
这就是“对象思想”的价值,它让你通过更进一步的“间接”(indirection,或者叫做“抽象”)来改变point.x和point.y的语义,从而让使用它们的代码完全不需要修改。虽然你的实际数据结构里面根本没有x和y这两个成员,由于.x和.y可以被重新定义,你可以通过改变.x和.y的含义来模拟它们。在你使用point.x和point.y的时候,系统内部其实在运行两片代码,它们的作用是从r和angle计算出x和y的值。这样你的代码就感觉好像x和y是实际存在的成员一样,而其实它们是被临时算出来的。在Python之类的语言里面,你可以通过定义“property”来直接改变point.x和point.y的语义。在Java里稍微麻烦一些,你需要使用point.getX()和point.getY()这样的写法。然而它们最后的目的其实都是一样的——它们为数据访问提供了一层“间接”(抽象)。
这种抽象是非常好的想法,它甚至可以跟量子力学的所谓“不可观测性”扯上关系。你觉得这个原子里面有10个电子?也许它们只是像point.x给你的幻觉一样,也许宇宙里根本就没有电子这种东西,也许你每次看到所谓的电子,它都是临时生成出来逗你玩的呢?然而,这就是对象思想的一切。你见过的所谓“面向对象思想”,几乎无一例外可以从这个想法推广出来。面向对象语言的绝大部分特性,其实是过程式语言早就提供的。因此我觉得,其实没有语言可以叫做“面向对象语言”。就像一个人为一个公司贡献了一点点代码,并不足以让公司以他的名字命名一样!