JavaScript OOP

1. 什么是JavaScript
JavaScript 是一种描述性的脚本语言(Script Language),它可以非常自由地被嵌入到HTML 的文件之中。使用JavaScript 可以做什么呢?它的作用很简单,就是对网页浏览者当前所触发的事件进行处理或对网页进行初始化工作。它是事先在网页中编写好代码(或叫做“脚本”),然后 此代码伴随Html文件一起传送到客户端的浏览器上,由浏览器对这些代码进行解释执行,而其执行期间并没有劳驾服务器帮忙,这样就减轻了服务器的负担。
许多编程高手都瞧不起JavaScript编程,认为只是小孩子的玩意。的确,JavaScript作为一种脚本语言,比起其他语言来说,显得非常简单,没有很复杂的语法,没有庞杂的体系架构。
2. 面向对象编程(Object-Oriented Programming)
一个世界,可以完全由对象组成,而将算法所基于的世界只用对象表现出来,再进行后续代码的编写,这种编程方法就被称作面向对象的编程思想。
OOP的三大要素:
1. 封装
2. 继承
3. 多态
3. JavaScript如何实现OOP
3.1. 封装(Wrap)
JavaScript的对象封装,主要依靠function来实现。以下是一个简单的示例:
//*********************************************

// 定义Pet(宠物)对象
//*********************************************
function Pet() {
//名称
this.name = null;
//颜色
this.color = null;
//获取名称
this.getName = function() {
return this.name;
};
//设置名称
this.setName = function(newName) {
this.name = newName;
};
//获取颜色
this.getColor = function() {
return this.color;
};
//设置颜色
this.setColor = function(newColor) {
this.color = newColor;
};
//定义一个需要实现的方法
this.getFood = null;
//获取宠物的描述信息
this.toString = function() {
return "The pet is " + this.name +",it's "+this.color+",and it likes "+this.getFood()+".";
};
}
3.2. 继承(inheritance)
JavaScript的继承的实现主要依靠prototype(原型)来实现,下面为Pet类编写一个子类。
//*********************************************

// 定义Cat(猫)对象
//*********************************************
function Cat() {
//实现Pet中定义的getFood方法
this.getFood = function() {
return "fish";
};
}

//声明Cat的原型,即Cat的父类
Cat.prototype = new Pet;

多层次继承
//*********************************************
// 定义PersianCat(波斯猫)对象
//*********************************************
function PersianCat() {
}

//声明PersianCat的原型,即PersianCat的父类
PersianCat.prototype = new Cat;
3.3. 重载(override)与多态(Polymorphism)
//重载Pet的toString方法
PersianCat.prototype.toString = function() {
return "It's just a persian cat.";
};

注意:Override和Overload的区别,JavaScript是不支持Overload的,原因是……你自己想想吧。

JavaScript是一种弱类型的语言,所以不要把它与C++、JAVA等语言进行比较。
4. 附录
4.1. 完整的示例
4.1.1. Pet.js
//*********************************************

// 定义Pet(宠物)对象
//*********************************************
function Pet() {
//名称
this.name = null;
//颜色
this.color = null;
//获取名称
this.getName = function() {
return this.name;
};
//设置名称
this.setName = function(newName) {
this.name = newName;
};
//获取颜色
this.getColor = function() {
return this.color;
};
//设置颜色
this.setColor = function(newColor) {
this.color = newColor;
};
//定义一个需要实现的方法
this.getFood = null;
//获取宠物的描述信息
this.toString = function() {
return "The pet is " + this.name +",it's "+this.color+",and it likes "+this.getFood()+".";
};
}

//*********************************************
// 定义Cat(猫)对象
//*********************************************
function Cat() {
//实现Pet中定义的getFood方法
this.getFood = function() {
return "fish";
};
}

//声明Cat的原型,即Cat的父类
Cat.prototype = new Pet;

//*********************************************
// 定义PersianCat(波斯猫)对象
//*********************************************
function PersianCat() {
}

//声明PersianCat的原型,即PersianCat的父类
PersianCat.prototype = new Cat;

//重载Pet的toString方法
PersianCat.prototype.toString = function() {
return "It's just a persian cat.";
};

//*********************************************
// 定义Dog(狗)对象
//*********************************************
function Dog() {
//实现Pet中定义的getFood方法
this.getFood = function() {
return "bone";
};
}

//声明Dog的原型,即Dog的父类
Dog.prototype = new Pet;
4.1.2. Pet.htm


4.1.3. 运行结果

弹出三个对话框,分别如下:
The pet is MiMi,it's white,and it likes fish.
The pet is WangWang,it's yellow,and it likes bone.
It's just a persian cat.
本示例在IE6.0下测试通过。

JS 面向对象编程基础

翻译说明:本文是我从Prado框架的《快速入门指南》翻译中摘录出来的,感觉对JavaScript的学习很有帮助,特贴出备忘。
Javascript简介

本指引基于Sergio Pereira的 Quick guide to somewhat advanced JavaScript tour of some OO features。
嘿,我不知道你能那样做

如果你是一个Web开发者而且与我来自同一个地方,你也许在你的Web页面中使用过相当多的Javascript,大部分用来作用户界面(UI)的粘合。

直到现在,我才知道Javascript具有比我过去使用的更多的面向对象能力,只是我没有如我所需的去使用它。当浏览器开始支持更标准的Javascript和DOM的功能集时,要为客户端上的运行而编写更复杂和多功能的代码就变得可行了。它助长了AJAX现象的产生。

当我们都开始学习它适合编写什么酷的AJAX应用时,我们开始关注到我们过去知道的Javascript不过只是冰山一角而已。我们现在知道Javascript不仅仅被用于象输入校验等简单的用户界面杂务和其他琐碎任务。现在的客户端代码更高级和分层,更象一个真正的桌面应用或一个客户端-服务器的富客户端。我们在其中看到了过去仅在服务器端的代码中见到的类库、对象模型、继承关系、模式和许多其他的东西。

突然在我们能讲到的许多方面被放到了比以前更高的位置。要为新的Web编写应用,我们必需提高我们的Javascript水平来跟上它而且要更加熟练。假如你尝试运用许多现有的javascript库,如:Prototype.js、Scriptaculous、moo.fx、Behaviour、YUI等,你最终会发现自己要阅读JS代码。或许因为你想要学习它们如何实现,或因为你的好奇,或通常因为那是知道如何使用它的唯一办法,大多数这些库象是不太注重文档。无论个案会是什么,假如你之前不了解那样的东西,你将要面对一些引起恐慌的外部技术。

本文的目的正好是解说许多我们还不熟悉的构造类型。

JSON (JavaScript Object Notation-Javascript对象表示法)

Javascript对象表示法(JSON),是围绕AJAX主题突然出现的一个新的时髦词。JSON,简单的说就是一种在Javascript中定义对象的方法。让我们马上来看看一个实例并体会它如何简单。

var myPet = { color: 'black', leg_count: 4, communicate: function(repeatCount){
for(i=0;i
就让我们加入些许格式让它看起来象我们平常所认识的那样:

var myPet =
{
color: 'black',
legCount: 4,
communicate: function(repeatCount)
{
for(i=0;i
alert('Woof!');
}
};
在这我们创建了一个带两个属性(color和legCount)和一个方法(communicate)的对象引用。不难发现,该对象的属性和方法用一个逗号区隔的列表来定义。每个成员通过名称来引入,接着是冒号和定义。对于属性来说很容易,仅仅是属性值。方法通过指派一个匿名函数来创建,我们下面会更好地说明。在该对象被创建并指派给变量myPet之后,我们可以如下使用它:

alert('my pet is ' + myPet.color);
alert('my pet has ' + myPet.legCount + ' legs');
//if you are a dog, bark three times:
myPet.communicate(3);
You'll see JSON used pretty much everywhere in JS these days, as arguments to functions, as return values, as server responses (in strings,) etc.

你想说什么?函数也是一个对象?

对于开发者来说这可能与众不同,但在JS中一个函数也是一个对象。你可以象参数一样把一个函数传送给另一个函数,就象你可以传送一个字符串一样。这些被广泛应用而且非常便利。

看看这个实例。我们将把函数传送到另一个使用它们的函数去。

var myDog =
{
bark: function()
{
alert('Woof!');
}
};

var myCat =
{
meow: function()
{
alert('I am a lazy cat. I will not meow for you.');
}
};

function annoyThePet(petFunction)
{
//let's see what the pet can do
petFunction();
}

//annoy the dog:
annoyThePet(myDog.bark);
//annoy the cat:
annoyThePet(myCat.meow);
注意,我们把没有添加"()"的myDog.bark和myCat.meow传送给它们。假如我们那样做了,我们不是传送函数,而是调用那些方法并传送它们的返回值,这里的两个个案中都未定义。

要是你想另我的懒猫起来嗥叫,你可以简单地这样做:

myCat.meow = myDog.bark;
myCat.meow(); //alerts 'Woof!'
数组、项目和对象成员

在JS中下列两行做了同样的事。

var a = new Array();
var b = [];
正如我确定你已经知道的那样,你可以通过使用方括号在一个数组中访问个别项目:

var a = ['first', 'second', 'third'];
var v1 = a[0];
var v2 = a[1];
var v3 = a[2];
但你还不限于数字索引。你可以通过使用它的名字以字符串来访问一个JS对象的任何成员。下面的例子创建了一个空对象,并通过名字加入了一些成员。

var obj = {}; //new, empty object
obj['member_1'] = 'this is the member value';
obj['flag_2'] = false;
obj['some_function'] = function(){ /* do something */};
上述代码的作用与下面的相同:

var obj =
{
member_1:'this is the member value',
flag_2: false,
some_function: function(){ /* do something */}
};
在许多情形下,在JS中对象的概念和关联的数组(杂凑)没有区别。下面两行代码都做了同样的事情。

obj.some_function();
obj['some_function']();
关于对象已经够了,我现在能有一个类了吗?

面向对象编程语言的巨大力量来源于类的使用。我不认为仅应用我之前使用其他语言的经验就能推测出在JS中如何定义类。这由你自己来判断。

//defining a new class called Pet
var Pet = function(petName, age)
{
this.name = petName;
this.age = age;
};

//let's create an object of the Pet class
var famousDog = new Pet('Santa\'s Little Helper', 15);
alert('This pet is called ' + famousDog.name);
让我们看看如何加入一个方法到我们的Pet类。我们将使用所有类都具有的prototype属性。prototype属性是一个包含任何对象的类会具有的所有成员的对象。甚至默认的JS类,如String、Number和Date拥有一个的prototype对象,它能让我们可以添加方法和属性并使那个类的任何对象自动获取这个新成员。

Pet.prototype.communicate = function()
{
alert('I do not know what I should say, but my name is ' + this.name);
};
那就是一个类似于prototype.js的库会派上用场的时候。如果我们使用prototype.js,我们能使我们的代码看起来更清晰(至少在我看来是这样)。

var Pet = Class.create();
Pet.prototype =
{
//our 'constructor'
initialize: function(petName, age)
{
this.name = petName;
this.age = age;
},

communicate: function()
{
alert('I do not know what I should say, but my name is ' + this.name);
}
};
函数作为参数,一个有趣的模式

假如你从来没有接触过支持闭合的语言,你也许会发现下面的惯用法太令人震惊了。

var myArray = ['first', 'second', 'third'];
myArray.each( function(item, index)
{
alert('The item in the position #' + index + ' is:' + item);
});
哇!在你断定我已经离题太远并且想转去比这篇更好点的文章之前,让我们在这解释一下要继续干些什么。

首先,在上述实例中我们使用了prototype.js库,它添加了each函数到Array类。该each函数接到一个函数对象的参数。这个函数对于数组中的每个项目都将被依次调用一次,对于当前项目调用时传送两个参数,item和index。让我们称这个函数为iterator函数。我们也能象这样编写代码:

function myIterator(item, index)
{
alert('The item in the position #' + index + ' is:' + item);
}

var myArray = ['first', 'second', 'third'];
myArray.each( myIterator );
我们不会象那些学校里的那些天真孩子那样做的,对吧?虽然更严格地说,后面的形式更易于理解但导致我们要进入代码中四处找寻myIterator函数。最好在它调用的同一个地方那里有迭代函数的逻辑。在本案例中,我们也不会在其他任何地方需要迭代函数,所以我们无损地把它转化成一个匿名函数。

这是this,但有时this也是那个

当使用JS开始编写我们的代码时,我们最普遍的一个麻烦就是this关键字的使用。它是一个真正的牵绊。

就象我们之前提及的那样,在JS中一个函数也是一个对象,而且有时候我们不注意我们正在传出一个函数。

拿这小段代码举个例:

function buttonClicked()
{
alert('button ' + this.id + ' was clicked');
}

var myButton = document.getElementById('someButtonID');
var myButton2 = document.getElementById('someOtherButtonID');
myButton.onclick = buttonClicked;
myButton2.onclick = buttonClicked;
由于buttonClicked函数在任何对象之外被定义,我们也许以为this关键字会包含一个window或document对象(假设这些代码位于一个在浏览器中被浏览的HTML页面中间)的引用。

但是当我们运行这段代码时,我们看到它如愿工作并显示被点击按钮的id。究竟其中发生了什么另我们使每个按钮的onclick方法包含buttonClicked对象引用,而无论之前那里有什么。现在无论按钮什么时候被点击,浏览器都会运行一些类似下行的东西:

myButton.onclick();
那毕竟不是这么混乱,是吧?只要你了解有别的对象要进行处理并想在这些对象的事件上,如点击按钮,进行什么行动后发生了什么就行了。

var myHelper =
{
formFields: [ ],
emptyAllFields: function()
{
for(i=0; i < this.formFields.length; i++)
{
var elementID = this.formFields[i];
var field = document.getElementById(elementID);
field.value = '';
}
}
};

//tell which form fields we want to work with
myHelper.formFields.push('txtName');
myHelper.formFields.push('txtEmail');
myHelper.formFields.push('txtAddress');

//clearing the text boxes:
myHelper.emptyAllFields();

var clearButton = document.getElementById('btnClear');
clearButton.onclick = myHelper.emptyAllFields;
因此你想:好了,现在我可以在我的页面上点击Clear按钮,那三个文本框就将被清空。然后你尝试点击该按钮后仅得到一个运行时错误。该错误将涉及(猜猜是什么?)this关键字。该问题是this.formFields没被定义即便this包含了一个到按钮的引用,那正是现在所发生的。一个快速的解决方案是重写我们最后一行的代码。

clearButton.onclick = function()
{
myHelper.emptyAllFields();
};
我们创建一个全新的函数,那种方法在协助对象的场景中调用了我们的协助方法。

IE6 png 透明 (三种解决方法)

第 1 种方法:定义一个样式,给某个div应用这个样式后,div的透明png背景图片自动透明了。(注意两处图片的路径写法不一样,本例中,icon_home.png图片与html文件在相同目录)

http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
http://www.w3.org/1999/xhtml">


无标题文档


第 2 种方法: 给img定义样式,页面上所有透明png即自动透明了。(这方法只对直接插入的图片有效,对背景图无效注意,要准备一个透明的小图片transparent.gif,大小不限。必须放在和html相同的目录
请勿大量使用,否则会导致页面打开很慢!!!)

http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
http://www.w3.org/1999/xhtml">


无标题文档


换成你的png图片







第 3 种方法:用JS实现,加上一段js代码后,所有插入的透明png自动透明了.(注意,这方法也是只对直接插入的图片有效,对背景图无效

http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
http://www.w3.org/1999/xhtml">


无标题文档


把图片换成你自己的图片




javascript 获取窗口大小

var x = document.body.scrollLeft; var y = document.body.scrollTop;//获取屏幕宽度 availWidth = parseInt(window.screen.availWidth); availHeight = parseInt(window.screen.availHeight);
//获取可见区域 宽度 高度 availWidth = parseInt(document.body.clientWidth); availHeight = parseInt(document.body.clientHeight); 可见区域高度:document.body.clientHeight总高度:document.body.scrollHeight可见区域宽度:document.body.clientWidth总宽度:document.body.scrollWidth==============================================================var getWindowInfo=function(){var scrollX=0,scrollY=0,width=0,height=0,contentWidth=0,contentHeight=0;if(typeof(window.pageXOffset)=='number'){ scrollX=window.pageXOffset; scrollY=window.pageYOffset;}else if(document.body&&(document.body.scrollLeftdocument.body.scrollTop)){ scrollX=document.body.scrollLeft; scrollY=document.body.scrollTop;}else if(document.documentElement&&(document.documentElement.scrollLeftdocument.documentElement.scrollTop)){ scrollX=document.documentElement.scrollLeft; scrollY=document.documentElement.scrollTop;}
if(typeof(window.innerWidth)=='number'){ width=window.innerWidth; height=window.innerHeight;}else if(document.documentElement&&(document.documentElement.clientWidthdocument.documentElement.clientHeight)){ width=document.documentElement.clientWidth; height=document.documentElement.clientHeight;}else if(document.body&&(document.body.clientWidthdocument.body.clientHeight)){ width=document.body.clientWidth; height=document.body.clientHeight;}
if(document.documentElement&&(document.documentElement.scrollHeightdocument.documentElement.offsetHeight)){ if(document.documentElement.scrollHeight>document.documentElement.offsetHeight){ contentWidth=document.documentElement.scrollWidth; contentHeight=document.documentElement.scrollHeight; } else { contentWidth=document.documentElement.offsetWidth; contentHeight=document.documentElement.offsetHeight; }}else if(document.body&&(document.body.scrollHeightdocument.body.offsetHeight)){ if(document.body.scrollHeight>document.body.offsetHeight) { contentWidth=document.body.scrollWidth; contentHeight=document.body.scrollHeight; }else{ contentWidth=document.body.offsetWidth; contentHeight=document.body.offsetHeight; }}else{ contentWidth=width; contentHeight=height;} if(height>contentHeight) height=contentHeight; if(width>contentWidth) width=contentWidth; var rect=new Object(); rect.ScrollX=scrollX; rect.ScrollY=scrollY; rect.Width=width; rect.Height=height; rect.ContentWidth=contentWidth; rect.ContentHeight=contentHeight; return rect;}

JAVA相关基础知识


1
、面向对象的特征有哪些方面   
1.
抽象:
抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。
2.
继承:
继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
3.
封装:
封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
4. 
多态性:
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
2
String是最基本的数据类型吗?
基本数据类型包括byteintcharlongfloatdoublebooleanshort
java.lang.String
类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer
3
int  Integer 有什么区别
Java 
提供两种不同的类型:引用类型和原始类型(或内置类型)。Intjava的原始数据类型,Integerjavaint提供的封装类。Java为每个原始类型提供了封装类。
原始类型封装类
boolean     Boolean
char           Character
byte           Byte
short          Short
int              Integer
long           Long
float           Float
double       Double
引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。
4
String StringBuffer的区别
JAVA
平台提供了两个类:StringStringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。String str1 = “java”; str1.replace(‘j’,’2’);//此后str1还是java,只是replace可以重新返回一个2ava!
5
、运行时异常与一般异常有何异同?
异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。级别不一样...       
  
一般异常都是Exception的子类,   运行期异常与System.err平级的 
  
一般异常值得捕获,运行期异常就管部了,无能为力地.

运行时异常与运行时环境有关,一般异常与原代码有关!
6
、说出Servlet的生命周期,并说出ServletCGI的区别。
Servlet
被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGetdoPost)等,当服务器决定将实例销毁的时候调用其destroy方法。
cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet
7
、说出ArrayList,Vector, LinkedList的存储性能和特性
ArrayList
Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
8
EJB是基于哪些技术实现的?并说出SessionBeanEntityBean的区别,StatefulBeanStatelessBean的区别。
    EJB
包括Session BeanEntity BeanMessage Driven Bean,基于JNDIRMIJAT等技术实现。
SessionBean
J2EE应用程序中被用来完成一些服务器端的业务操作,例如访问数据库、调用其他EJB组件。EntityBean被用来代表应用系统中用到的数据。
对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。
对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的实体。
Session Bean 
还可以再细分为 Stateful Session Bean  Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会有一个相对应的 Stateful Session Bean 的实体。Stateless Session Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用者呼叫 Stateless Session Bean 的时候,EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method。换言之,很可能数个使用者在执行某个 Stateless Session Bean  methods 时,会是同一个 Bean  Instance 在执行。从内存方面来看, Stateful Session Bean  Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。
9
Collection  Collections的区别。 
  Collection是集合类的上级接口,继承与他的接口主要有Set List.
Collections
是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
10
&&&的区别。 
    &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。
11
HashMapHashtable的区别。 
    HashMapHashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key,由于非线程安全,效率上可能高于Hashtable
HashMap
允许将null作为一个entrykey或者value,而Hashtable不允许。
HashMap
Hashtablecontains方法去掉了,改成containsvaluecontainsKey。因为contains方法容易让人引起误解。 
Hashtable
继承自Dictionary类,而HashMapJava1.2引进的Map interface的一个实现。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 
Hashtable
HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
12
final, finally, finalize的区别。 
  final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
finally
是异常处理语句结构的一部分,表示总是执行。
finalize
Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
13
sleep()  wait() 有什么区别
    sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait
Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
14
OverloadOverride的区别。Overloaded的方法是否可以改变返回值的类型?
方法的重写Overriding和重载OverloadingJava多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)Overloaded的方法是可以改变返回值的类型。
15
errorexception有什么区别?
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。
    exception 
表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。
16
、同步和异步有何异同,在什么情况下分别使用他们?举例说明。
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
17
abstract classinterface有什么区别?
声明方法的存在而不去实现它的类被叫做抽象类(span)

JavaBean

 JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,必须是具体的和公共的,并且具有无参数的构造器。JavaBeans 通过提供符合一致性设计模式的公共方法将内部域暴露称为属性。众所周知,属性名称符合这种模式,其他Java 类可以通过自省机制发现和操作这些JavaBean 属性。

      用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。

      JavaBean是Sun微系统的一个面向对象的编程接口,它可以让你建可重用应用程序或能在网络中任何主流操作系统平台上配置的程序块,称作组件。像Java applet一样,JavaBeans组件(或“Beans”)能够给予万维网页面交互的能力,例如:计算感兴趣的比率或是根据用户或浏览器的特性改变页面内容。

      从用户的观点来看,一个组件可以是一个与你交互的按钮或是一个当你按下按钮它便开始的小计算程序。从一个开发者的观点来看,那个按钮组件和计算器组件是分别被创建的,并且他们可以一起使用或是在不同的应用程序或情况下和不同的组件产生不同的组合来使用。

      当组件或Beans在使用过程中,Bean的性质(比如,一个窗口的背景色)对于其他Bean来说是可见的,并且,之前没“碰到”过的Bean也可以动态地获悉彼此的特性并从而进行交互。 

      Bean是随Sun的Bean开发包(BDK)开发出来的,并且能在任何主流操作系统平台的许多应用程序环境(人们所说的“容器”,container)中运行,包括浏览器,文字处理软件,以及一些其他应用。 

      要想用JavaBeans建一个组件,你必须用Sun的Java编程语言来写程序,并且在程序中包括描述组件特性的JavaBeans语句,这些组件特性例如:用户接口的特性,以及触发一个bean和在同一个容器中或网络其他地方的其他的bean交流的事件。  

      Bean也有持续性,持续性就是一种把一个组件的状态存在一个安全处的机制。有了这种持续性,它能使,比如说,一个组件(bean)“记住”某个特定用户在早些时候的用户对话中所输入的数据。 

      JavaBeans给Java应用程序提供了OpenDoc和ActiveX接口已提供的这种复合文档的能力。

一、JavaBean的历史

      最初,JavaBean的目的是为了将可以重复使用的软件代码打包标准。特别是用与帮助厂家开发在综合开发环境(IDE)下使用的java软件部件。这些包括如Grid控件,用户可以将该部件拖放到开发环境中。从此,JavaBean就可以扩展为一个java web 应用的标准部件,并且JavaBean部件框架已经扩展为企业版的 Bean(EJB)。

二、JavaBean和企业Bean的区别

      JavaBean 和 Server Bean(通常称为 Enterprise JavaBean (EJB))有一些基本相同之处。它们都是用一组特性创建,以执行其特定任务的对象或组件。它们还有从当前所驻留服务器上的容器获得其它特性的能力。这使得 bean 的行为根据特定任务和所在环境的不同而有所不同。

      Enterprise Bean 与 JavaBean 不同。JavaBean 是使用 java.beans 包开发的,它是 Java 2 标准版的一部分。JavaBean 是一台机器上同一个地址空间中运行的组件。JavaBean 是进程内组件。Enterprise Bean 是使用 javax.ejb 包开发的,它是标准 JDK 的扩展,是 Java 2 Enterprise Edition 的一部分。Enterprise Bean 是在多台机器上跨几个地址空间运行的组件。因此 Enterprise Bean 是进程间组件。JavaBean 通常用作 GUI 窗口小部件,而 Enterprise Bean 则用作分布式商业对象.


三、JavaBean 的发展

      最初,JavaBean的目的是为了将可以重复使用的软件代码打包标准。特别是用与帮助厂家开发在综合开发环境(IDE)下使用的java软件部件。这些包括如Grid控件,用户可以将该部件拖放到开发环境中。从此,JavaBean就可以扩展为一个java web 应用的标准部件,并且JavaBean部件框架已经扩展为企业版的 Bean(EJB)。

四、JavaBean需求

      avaBean是java类,属于某些特定的译码知道方针,并且扩展了适应性和范围,允许用户访问内部的属性和方法。通过这些,JavaBean类可以用于下列方法:

      1.在IDE中,JavaBean的功能允许应用开发者浏览其中的方法,即使JavaBean是被编译的,并且无法利用原始的源文件
      2.在 Remote Method Invocation(RMI) 的分布式风格中,这项功能听起来并不让人兴奋,但是在未来的包含企业版的JavaBean后,将改变这种情况。
      3.为了JavaBean的属性值和状态可以保存到磁盘上。

      这里说的有些简单,如果想了解更多的东西,可以查阅一些资料。


五、JavaBean设计注意事项

      实际应用中,在表现对象或者处理前扩展JavaBean的设计非常有用。通常认为如果提供信息,web开发者将在功能上满足拥护对JavaBean的需求。例如: HTML中显示敏感的数据时,用户可以屏蔽的条目,如密码、电话号码等。

      良好规划设计的JavaBean是值得信赖的。

      Java 中的 null 不同于 SQL 中的 null

      看这样一道测试程序:

public class NullTest
{
public static void main(String[] args)
{
int I = 0;
// int I = null; // not a valid initialization 
String str = null;
String strZeroOutValue = “”;
StringBuffer sb = new StringBuffer(“Null test: String initialized as null = “);
sb.append(str);
sb.append(“\n String representing a Zero Out Value:”);
sb.append(strZeroOutValue);
System.out.println(sb.toString());
}
}
      这个程序将产生下面的结果:

Null test: String initialized as null = null
String representing a Zero Out Value:

      在JavaBean中, 我们将 I 变量声明为一个 int, 我们必须处理与该变量相关的值,因为I 默认的没有值,int 类型无法初始化为 null, 如果int 值没有进行明确的初始化,编译器将提示错误。 
执行 NullTest 程序,将验证在文本中空字符串是空值的替代,用于显示 SQL 的插入和更新。如果我们需要删除一些信息,通过删除表单区域的文本,需要将数据库发送长度为0的字符串。
尽管大多数数据库将空字符串作为空值进行操作,如果我们使用的数据库不支持处理空字符串的话,我们必须写入附加的java代码,来创建自己的SQL插入声明。
例如:
if(test.length==0)
{
sb.append(“null”);
}
else
{
sb.append(test);
}

      JavaBean 的范围:


      JavaBean 的范围。 Scope 是一个具有生命时间的变量。JavaBean的范围在
标志中右边进行表示。将产生一个JavaBean的快捷参考。

      说明:jsp服务器引擎将剥离

      存在下面四种范围: 页面、 请求、 对话、 应用。


      对话范围:
      对话范围的JavaBean 主要应用与跨多个页面和时间段: 例如填充 用户信息。 添加信息并且接受回馈,保存用户最近执行页面的轨迹。对话范围JavaBean保留一些和用户对话 ID 相关的信息。这些信息来自临时的对话cookie,并在当用户关闭浏览器时,这个cookie将从客户端和服务器删除。


      页面/请求范围:
      页面和请求范围的JavaBean有时类似表单 的bean , 这是因为 他们大豆用与处理表单。表单需要很长的时间来处理用户的输入,通常情况下用于页面接受HTTP/POST或者GET请求。另外页面和请求范围的bean可以用于减少大型站点服务器上的负载,如果使用对话bean,耽搁的处理就可能会消耗掉很多资源。


      应用:

      应用范围通常应用于服务器的部件,例如 JDBC 连接池、应用监视、拥护计数和其他参与用户行为的类。


      在Bean中限制HTML的产生:

      理论上,JavaBean 将不会产生任何HTML,因为这是jsp层负责的工作;然而,为了动态消息提供一些预先准备的格式是非常有用的。产生的HTML将被标注的 JavaBean方法返回。

      这里有一些非常重要的事情:

      1.不要试图在JavaBean返回的HTML中放置任何字体尺寸。
      并不是所有的浏览器都相同。很多浏览器无法处理完整的字体尺寸。 
      2.不要试图在JavaBean返回的HTML中放置任何脚本或者DHTML。
      向页面直接输出脚本或者DHTML相当于自我毁灭,因为某些浏览器版本在处理不正确的脚本时会崩溃(非常少但是有)。如果用户的JavaBean在运行时是动态的推出复杂的HTML语言,用户将陷入调试的噩梦。另外,复杂的HTML将限制JavaBean的寿命和灵活性。
      3.不要提供任何的选择。
      如果用户使用不同的系统浏览页面,可以提供一种可以替换的方法。

六、JavaBean的任务

      JavaBean的任务就是: “Write once, run anywhere, reuse everywhere”,即“一次性编写,任何地方执行,任何地方重用”。这个任何实际上就是要解决困扰软件工业的日益增加的复杂性,提供一个简单的、紧凑的和优秀的问题解决方案。

      1. 一个开发良好的软件组件应该是一次性地编写,而不需要再重新编写代码以增强或完善功能。因此,JavaBean应该提供一个实际的方法来增强现有代码的利用率,而不再需要在原有代码上重新进行编程。除了在节约开发资源方面的意义外,一次性地编写JavaBean组件也可以在版本控制方面起到非常好的作用。开发者可以不断地对组件进行改进,而不必从头开始编写代码。这样就可以在原有基础上不断提高组件功能,而不会犯相同的错误。

      2. JavaBean组件在任意地方运行是指组件可以在任何环境和平台上使用,这可以满足各种交互式平台的需求。由于JavaBean是基于Java的,所以它可以很容易地得到交互式平台的支持。JavaBean组件在任意地方执行不仅是指组件可以在不同的操作平台上运行,还包括在分布式网络环境中运行。

      3.JavaBean组件在任意地方的重用说的是它能够在包括应用程序、其他组件、文档、Web站点和应用程序构造器工具的多种方案中再利用。这也许是JavaBean组件的最为重要的任务了,因为它正是JavaBean组件区别于Java程序的特点之一。Java程序的任务就是JavaBean组件所具有的前两个任务,而这第3个任务却是JavaBean组件独有的。


七、JavaBean的设计目标及其如何被实现

      现在我们来看一实现JavaBean的一些具体的主要设计目标:

      1.紧凑而方便的创建和使用

      JavaBean紧凑性的需求是基于JavaBean组件常常用于分布式计算环境中,这使得JavaBean组件常常需要在有限的带宽连接环境下进行传输。显然,为了适应传送的效率和速度,JavaBean组件必须是越紧凑越好。另外,为了更好地创建和使用组件,就应该使其越简单越好。通常为了提高组件的简易性和紧凑性,设计过程需要投入相对较大的功夫。

      现在已有的组件软件技术通常是使用复杂的API,这常常搞得开发者在创建组件时晕头转向。因此,JavaBean组件必须不仅容易使用,而且必须便于开发。这对于组件开发者而言是至关重要的,因为这可以使得开发者不必花大量功夫在使用API进行程序设计上,从而更好地对组件进行润饰,提高组件的可观赏性。

      JavaBean组件大部分是基于已有的传统Java编程的类结构上的,这对于那些已经可以熟练地使用Java语言的开发者非常有利。而且这可以使得JavaBean组件更加紧凑,因为Java语言在编程上吸收了以前的编程语言中的大量优点,已经使开发出来的程序变得相当有效率。

      2.完全的可移植性

      JavaBean API与操作基础的独立于平台的Java系统相结合,提供了独立于平台的组件解决方案。因此,组件开发者就可以不必再为带有Java applet平台特有的类库而担心了。最终的结果都将是计算机界共享可重复使用的组件,并在任何支持Java的系统中无需修改地执行。

      3.继承Java的强大功能

      现有的Java结构已经提供了多种易于应用于组件的功能。其中一个比较重要的是Java本身的内置类发现功能,它可以使得对象在运行时彼此动态地交互作用,这样对象就可以从开发系统或其开发历史中独立出来。

      对于JavaBean而言,由于它是基于Java语言的,所以它就自然地继承了这个对于组件技术而言非常重要的功能,而不再需要任何额外开销来支持它。

      JavaBean继承在现有Java功能中还有一个重要的方面,就是持久性,它保存对象并获得对象的内部状态。通过Java提供的序列化(serialization)机制,持久性可以由JavaBean自动进行处理。当然,在需要的时候,开发者也可以自己建立定制的持久性方案。

      4.应用程序构造器支持

      JavaBean的另一个设计目标是设计环境的问题和开发者如何使用JavaBean创建应用程序。JavaBean体系结构支持指定设计环境属性和编辑机制以便于JavaBean组件的可视化编辑。这样开发者可以使用可视化应用程序构造器无缝地组装和修改JavaBean组件。就像Windows平台上的可视化开发工具VBX或OCX控件处理组件一样。通过这种方法,组件开发者可以指定在开发环境中使用和操作组件的方法。

      5.分布式计算支持

      支持分布式计算虽然不是JavaBean体系结构中的核心元素,但也是JavaBean中的一个主要问题。

      JavaBean使得开发者可以在任何时候使用分布式计算机制,但不使用分布式计算的核心支持来给自己增加额外负担。这正是出于JavaBean组件的紧凑性考虑的,无疑分布式计算需要大量的额外开销。


八、JavaBean和Java

      虽然JavaBean和Java之间已经有了明确的界限,但在某些方面JavaBean和Java之间仍然存在着非常明显的混淆。Java确实是能够为用户创建可重用的对象,但它却没有管理这些对象相互作用的规则或标准。JavaBean通过指定定义对象之间交互作用的机制,以及大部分对象需要支持的常用行为,如持久性和实际处理等,建立了自己需要的组件模型。

      虽然当前的Java组件模型也可以运行得很好,但在传送真正的可重用性和交互操作性上仍然非常有限,Java用户需要做的最多的一件事就是创建applet并使得它们在Web 页面上相互通讯,这并非易事。JavaBean提供了一个框架包,使用这个包进行通讯就容易得多了。

      JavaBean组件能够通过定义好的标准属性改进性能。总体而言,JavaBean充分发展了Java applet的功能,并结合了Java AWT组件的紧凑性和可重用性。


九、JavaBean组件的基本概念

      JavaBean是可复用的平台独立的软件组件,开发者可以在软件构造器工具中其直接进行可视化操作。
      软件构造器工具可以是Web页面构造器、可视化应用程序构造器、CUI设计构造器或服务器应用程序构造器。有时,构造器工具也可以是一个包含子一些bean的复合文档的文档编辑器。
      JavaBean可以是简单的CUI要素,如按钮或滚动条;也可以是复杂的可视化软件组件,如数据库视图,有些JavaBean是没有GUI表现形式的,但这些JavaBean仍然可以使用应用程序构造器可视化地进行组合。
      一个JavaBean和一个Javaapplet相似,是一个非常简单的遵循某种严格协议的Java类。每个JavaBean的功能都可能不一样,但它们都必须支持以下特征。
      一个bean没有必须继承的特定的基类或接口。可视化的bean必须继承的类是java.awt.Component,这样它们才能添加到可视化容器中去,非可视化bean则不需要继承这个类。有许多bean,无论是在应用程序构造器工具中,还是在最后创建好的应用程序中,都具有很强的可视化特征,但这并非每个bean必须的特征。
      在使用Java编程时,并不是所有软件模块都需要转换成bean。Bean比较适合于那些具有可视化操作和定制特性的软件组件。
      从基本上说,JavaBean可以看成是一个黑盒子,即只需要知道其功能而不必管其内部结构的软件设备。黑盒子只介绍和定义其外部特征和与其他部分的接口,如按钮、窗口、颜色、形状、句柄等。
      通过将系统看成使用黑盒子关联起来的通讯网络,我们可以忽略黑盒子内部的系统细节,从而有效地控制系统的整体性能。作为一个黑盒子的模型,JavaBean有3个接口面,可以独立进行开发。
      1. JavaBean可以调用的方法。
      2. JavaBean提供的可读写的属性。
      3. JavaBean向外部发送的或从外部接收的事件。


九、JavaBean组件的开发环境


      普通JavaBean组件是要分布在各自环境中,所以它们应该能够适应各种环境。虽然我们无法事先预知JavaBean要运行的确切环境,但以下两点是可以确定的:
      1. bean必须能够在一个应用程序构造器工具中运行。
      2. bean必须可以在产生的应用程序的运行环境中使用。

      设计环境

      第一点说明的是bean必须可以在设计环境(design environment)中运行。在设计环境中,bean应该提供设计信息给应用程序构造器工具并允许终端用户制定bean的外  观和行为。
在传统的软件构造活动中,必须通过编译、链接之后才能看到应用程序的最终运行结果;而利用JavaBean设计的软件中,则没有这种明确的界限。使用JavaBean,就可以非常直观地设计应用程序软件,在设计过程中赋予软件生机。而且,这个过程更加容易重复开发,设计思想更加容易变成原型。

      运行环境

      第二点说明的是bean必须可以在运行环境(run-time environment)中使用。在这个环境中,对设计信息和定制的需求并不重要。一个组件的设计环境信息和设计环境中编写的代码通常可能是非常巨大的。
      因此,我们可能需要在bean的设计环境方面和运行环境方面作一个明确的区分,这样,就可能需要在运行环境中不使用bean的任何设计环境代码来配置这个bean。所以,JavaBean就必须分别支持运行环境接口的类库和设计环境接口的类库。

 

十、JavaBean入门


一般要求
首先,您必须有一个不带有参数的公用构造器。此构造器也应该通过调用各个特性的设置方法来设置特性的缺省值,例如:

public Fireworks()
{
setAutoStart(true);
setBackground(Color.black);
setSpeed(10);
setRadius(40);
.
.
.
}

如果 bean 是一个从 java.awt.Component 类继承而来的可视 bean,您就应该为 bean 定义一个缺省的首选大小,例如:

public Dimension getPreferredSize()
{
return (new Dimension(radius*3, radius*3));
}

public Dimension getMinimumSize()
{
return getPreferredSize();
}


特性
对于您需要的每个特性,您应该有一个带有匹配公用 getter 和 setter 方法的专用实例变量,例如:

private int speed;
.
.
.
public int getSpeed()
{
return speed;
}

public void setSpeed(int s)
{
speed = s;
}

此 get 和 set 方法必须有与实例变量相同的名称,但是第一个字母要大写并以 get 和 set 开头。

由于连接而在任何时候更改它们的特性时,确认 Bean 在运行时行为正确也是很重要的。如果特性的更改影响到 Bean 的可视外观,您应该以此特性设置的方法来调用

repaint();。


同样,如果特性的更改影响到 bean 的大小和位置,您需要确认获得验证的事物。我们建议编写您自己的 validateAll 方法,如下所示:

private void validateAll()
{
if (isValid())
{
Component self = this;
self.invalidate();
Component myParent = self.getParent();
if (myParent != null)
{
myParent.invalidate();
self = myParent;
}
self.validate();
}
}

然后以此特性设置的方法调用

validateAll();。


 

bean 类将无法进行关于调用特性设置方法命令的假设。您应该写 bean 以便可以初始构造它,然后在不引起错误的同时在任何命令中设置其特性。


操作
对于每个您需要的操作,您应该有一个公用方法,例如:

public void start()
{
if(thread==null)
{
thread=new Thread(this);
thread.start();
}
}

您为操作写的方法应该在无须期待用户创建连接或设置很多特性的情况下独立操作。 例如,如果您写了一个音频 Bean,您希望通过播放操作处理打开声音的所有步骤、完成您需要的所有设置并播放声音。同样,即使声音未播放,停止操作也应起作用。


事件
对于您需要的每个事件或事件设置,您应该定义事件和侦听器类。对于此例,查看 FireworksEvent.java 源文件以及 Fireworks.java 文件。此事件类的源应该如同这样:

import java.awt.*;
import java.util.*;

public class FireworksEvent extends EventObject
{
public static final int EXPLODED = 1;

int id = 0;

public FireworksEvent(Component source, int id)
{
super(source);
this.id = id;
}

public int getID()
{
return id;
}
}

您应该为此事件设置中的每个事件定义一个公用静态结束事件标识符,例如在此例子中的 EXPLODED。

对于侦听器类的源,查看 FireworksListener.java 源文件:

import java.util.*;

public interface FireworksListener extends EventListener
{
public abstract void exploded(FireworksEvent e);
}

您应该为此事件设置中的每个事件定义一个公用抽象方法,例如在此例子中的 exploded。 而且,侦听器类必须扩展 EventListener ,以使 JAR 向导能够找到它。

然后,如果由 bean 类播送事件,它必须跟踪侦听事件的对象。要这样做,您需要定义侦听器实例变量以及 addListener 和 removeListener 方法。返回 Fireworks.java 源,例如,您将查看到:

private Vector listeners = new Vector();
.
.
.
public void addFireworksListener(FireworksListener f)
{
listeners.addElement(f);
}

public void removeFireworksListener(FireworksListener f)
{
listeners.removeElement(f);
}

最后,bean 类需要以正确的次数将事件实际播送到所有的侦听器。要这样做,您需要定义 processEvent 方法并以适当的次数调用它,例如:

public void processFireworksEvent(FireworksEvent e)
{
for (Enumeration enum = listeners.elements(); enum.hasMoreElements(); )
((FireworksListener)enum.nextElement()).exploded(e);
}

public void run()
{
.
.
.
processFireworksEvent(new FireworksEvent(this, FireworksEvent.EXPLODED));
}

(来源:www.seasky.biz;www.daima.com.cn;www.cnpaf.net)

J2EE Java2平台企业版 详细解释

J2EE Java2平台企业版(Java 2 Platform,Enterprise Edition)

J2EE是一套全然不同于传统应用开发的技术架构,包含许多组件,主要可简化且规范应用系统的开发与部署,进而提高可移植性、安全与再用价值。

J2EE核心是一组技术规范与指南,其中所包含的各类组件、服务架构及技术层次,均有共通的标准及规格,让各种依循J2EE架构的不同平台之间,存在良好的兼容性,解决过去企业后端使用的信息产品彼此之间无法兼容,导致企业内部或外部难以互通的窘境。

在J2EE架构下,开发人员可依循规范基础,进而开发企业级应用;而不同J2EE供货商,同会支持不同J2EE版本内所拟定的标准,以确保不同J2EE平台与产品之间的兼容性。换言之,植基J2EE架构的应用系统,基本上可部署在不同的应用服务器之上,无需或者只须要进行少量的代码修改,即能大幅提高应用系统的可移植性(Portability)。

J2EE主由升阳与IBM等厂商协同业界共同拟定而成的技术规范,以企业与企业之间的运算为导向的JAVA开发环境。J2EE架构定义各类不同组件,如Web Component、EJB Component…等,而各类组件可以再用(reuse),让已开发完成的组件,或者是经由市面采购而得的组件,均能进一步组装成不同的系统。

对于开发人员而言,只需要专注于各种应用系统的商业逻辑与架构设计,至于底层繁琐的程序撰写工作,可搭配不同的开发平台,以让应用系统的开发与部署效率大幅提升。

J2EE的核心规范是 Enterprise Java Beans(EJBs)。EJB依照特性的不同,目前共分为三种,分别是Session Bean、Entity Bean,以及 Message Driven Bean 。其中 Session Bean 与Entity Bean 算是EJB的始祖,这两种EJB规格在EJB 1.x版本推出时就已经存在,而Message Driven Bean则是出现在EJB 2.0的规格之中。

目前业界许多程序设计师,或者是网页设计人员,多利用JSP/Servlet的便利性,进而在J2EE服务器之上开发相关的应用,或是整合公司内部的各种资源。

Java 2平台依照应用领域的不同,共分为三大版本,分别是J2EE、标准版本J2SE(Java 2 Platform, Standard Edition)、微型版本J2ME(Java 2 Platform, Micro Edition),以及Java Card等。

从整体上讲,J2EE是使用Java技术开发企业级应用的一种事实上的工业标准(Sun公司出于其自身利益的考虑,至今没有将Java及其相关技术纳入标准化组织的体系),它是Java技术不断适应和促进企业级应用过程中的产物。Sun推出J2EE的目的是为了克服传统Client/Server模式的弊病,迎合Browser/Server架构的潮流,为应用Java技术开发服务器端应用提供一个平台独立的、可移植的、多用户的、安全的和基于标准的企业级平台,从而简化企业应用的开发、管理和部署。J2EE是一个标准,而不是一个现成的产品。各个平台开发商按照J2EE规范分别开发了不同的J2EE应用服务器,J2EE应用服务器是J2EE企业级应用的部署平台。由于它们都遵循了J2EE规范,因此,使用J2EE技术开发的企业级应用可以部署在各种J2EE应用服务器上。

为了推广并规范化使用J2EE架构企业级应用的体系架构,Sun同时给出了一个建议性的J2EE应用设计模型:J2EE Blueprints。J2EE Blueprints提供了实施J2EE企业级应用的体系架构、设计模式和相关的代码,通过应用J2EE Blueprints所描述的体系模型,能够部分简化架构企业级应用这项复杂的工作。J2EE Blueprints是开发人员设计和优化J2EE组件的基本原则,同时为围绕开发工作进行职能分工给出了指导性策略,以帮助应用开发设计人员合理地分配技术资源。??

J2EE组成了一个完整企业级应用的不同部分纳入不同的容器(Container),每个容器中都包含若干组件(这些组件是需要部署在相应容器中的),同时各种组件都能使用各种J2EE Service/API。J2EE容器包括:

◆ Web容器 服务器端容器,包括两种组件JSP和Servlet,JSP和Servlet都是Web服务器的功能扩展,接受Web请求,返回动态的Web页面。Web容器中的组件可使用EJB容器中的组件完成复杂的商务逻辑。

◆ EJB容器 服务器端容器,包含的组件为EJB(Enterprise JavaBeans),它是J2EE的核心之一,主要用于服务器端的商业逻辑的实现。EJB规范定义了一个开发和部署分布式商业逻辑的框架,以简化企业级应用的开发,使其较容易地具备可伸缩性、可移植性、分布式事务处理、多用户和安全性等。

◆ Applet容器 客户端容器,包含的组件为Applet。Applet是嵌在浏览器中的一种轻量级客户端,一般而言,仅当使用Web页面无法充分地表现数据或应用界面的时候,才使用它。Applet是一种替代Web页面的手段,我们仅能够使用J2SE开发Applet,Applet无法使用J2EE的各种Service和API,这是为了安全性的考虑。

◆ Application Client容器 客户端容器,包含的组件为Application Client。Application Client相对Applet而言是一种较重量级的客户端,它能够使用J2EE的大多数Service和API。

通过这四个容器,J2EE能够灵活地实现前面描述的企业级应用的架构。

在View部分,J2EE提供了三种手段:Web容器中的JSP(或Servlet)、Applet和Application Client,分别能够实现面向浏览器的数据表现和面向桌面应用的数据表现。Web容器中的Servlet是实现Controller部分业务流程控制的主要手段;而EJB则主要针对Model部分的业务逻辑实现。至于与各种企业资源和企业级应用相连接,则是依靠J2EE的各种服务和API。

在J2EE的各种服务和API中,JDBC和JCA用于企业资源(各种企业信息系统和数据库等)的连接,JAX-RPC、JAXR和SAAJ则是实现Web Services和Web Services连接的基本支持。

J2EE的各种组件 
我们就J2EE的各种组件、服务和API,进行更加详细的阐述,看看在开发不同类型的企业级应用时,根据各自需求和目标的不同,应当如何灵活使用并组合不同的组件和服务。

· Servlet 
Servlet是Java平台上的CGI技术。Servlet在服务器端运行,动态地生成Web页面。与传统的CGI和许多其它类似CGI的技术相比,Java Servlet具有更高的效率并更容易使用。对于Servlet,重复的请求不会导致同一程序的多次转载,它是依靠线程的方式来支持并发访问的。

· JSP 
JSP(Java Server Page)是一种实现普通静态HTML和动态页面输出混合编码的技术。从这一点来看,非常类似Microsoft ASP、PHP等技术。借助形式上的内容和外观表现的分离,Web页面制作的任务可以比较方便地划分给页面设计人员和程序员,并方便地通过JSP来合成。在运行时态,JSP将会被首先转换成Servlet,并以Servlet的形态编译运行,因此它的效率和功能与Servlet相比没有差别,一样具有很高的效率。

· EJB 
EJB定义了一组可重用的组件:Enterprise Beans。开发人员可以利用这些组件,像搭积木一样建立分布式应用。在装配组件时,所有的Enterprise Beans都需要配置到EJB服务器(一般的Weblogic、WebSphere等J2EE应用服务器都是EJB服务器)中。EJB服务器作为容器和低层平台的桥梁管理着EJB容器,并向该容器提供访问系统服务的能力。所有的EJB实例都运行在EJB容器中。EJB容器提供了系统级的服务,控制了EJB的生命周期。EJB容器为它的开发人员代管了诸如安全性、远程连接、生命周期管理及事务管理等技术环节,简化了商业逻辑的开发。EJB中定义了三种Enterprise Beans: 
◆ Session Beans 
◆ Entity Beans 
◆ Message-driven Beans

· JDBC 
JDBC(Java Database Connectivity,Java数据库连接)API是一个标准SQL(Structured Query Language,结构化查询语言)数据库访问接口,它使数据库开发人员能够用标准Java API编写数据库应用程序。JDBC API主要用来连接数据库和直接调用SQL命令执行各种SQL语句。利用JDBC API可以执行一般的SQL语句、动态SQL语句及带IN和OUT参数的存储过程。Java中的JDBC相当与Microsoft平台中的ODBC(Open Database Connectivity)。

· JMS 
JMS(Java Message Service,Java消息服务)是一组Java应用接口,它提供创建、发送、接收、读取消息的服务。JMS API定义了一组公共的应用程序接口和相应语法,使得Java应用能够和各种消息中间件进行通信,这些消息中间件包括IBM MQ-Series、Microsoft MSMQ及纯Java的SonicMQ。通过使用JMS API,开发人员无需掌握不同消息产品的使用方法,也可以使用统一的JMS API来操纵各种消息中间件。通过使用JMS,能够最大限度地提升消息应用的可移植性。 JMS既支持点对点的消息通信,也支持发布/订阅式的消息通信。

· JNDI 
由于J2EE应用程序组件一般分布在不同的机器上,所以需要一种机制以便于组件客户使用者查找和引用组件及资源。在J2EE体系中,使用JNDI(Java Naming and Directory Interface)定位各种对象,这些对象包括EJB、数据库驱动、JDBC数据源及消息连接等。JNDI API为应用程序提供了一个统一的接口来完成标准的目录操作,如通过对象属性来查找和定位该对象。由于JNDI是独立于目录协议的,应用还可以使用JNDI访问各种特定的目录服务,如LDAP、NDS和DNS等。

· JTA 
JTA(Java Transaction API)提供了J2EE中处理事务的标准接口,它支持事务的开始、回滚和提交。同时在一般的J2EE平台上,总提供一个JTS(Java Transaction Service)作为标准的事务处理服务,开发人员可以使用JTA来使用JTS。

· JCA 
JCA(J2EE Connector Architecture)是J2EE体系架构的一部分,为开发人员提供了一套连接各种企业信息系统(EIS,包括ERP、SCM、CRM等)的体系架构,对于EIS开发商而言,它们只需要开发一套基于JCA的EIS连接适配器,开发人员就能够在任何的J2EE应用服务器中连接并使用它。基于JCA的连接适配器的实现,需要涉及J2EE中的事务管理、安全管理及连接管理等服务组件。

· JMX 
JMX(Java Management Extensions)的前身是JMAPI。JMX致力于解决分布式系统管理的问题。JMX是一种应用编程接口、可扩展对象和方法的集合体,可以跨越各种异构操作系统平台、系统体系结构和网络传输协议,开发无缝集成的面向系统、网络和服务的管理应用。JMX是一个完整的网络管理应用程序开发环境,它同时提供了厂商需要收集的完整的特性清单、可生成资源清单表格、图形化的用户接口;访问SNMP的网络API;主机间远程过程调用;数据库访问方法等。

· JAAS 
JAAS(Java Authentication and Authorization Service)实现了一个Java版本的标准Pluggable Authentication Module(PAM)的框架。JAAS可用来进行用户身份的鉴定,从而能够可靠并安全地确定谁在执行Java代码。同时JAAS还能通过对用户进行授权,实现基于用户的访问控制。

· JACC 
JACC(Java Authorization Service Provider Contract for Containers)在J2EE应用服务器和特定的授权认证服务器之间定义了一个连接的协约,以便将各种授权认证服务器插入到J2EE产品中去。

· JAX-RPC 
通过使用JAX-RPC(Java API for XML-based RPC),已有的Java类或Java应用都能够被重新包装,并以Web Services的形式发布。JAX-RPC提供了将RPC参数(in/out)编码和解码的API,使开发人员可以方便地使用SOAP消息来完成RPC调用。同样,对于那些使用EJB(Enterprise JavaBeans)的商业应用而言,同样可以使用JAX-RPC来包装成Web服务,而这个Web Servoce的WSDL界面是与原先的EJB的方法是对应一致的。JAX-RPC为用户包装了Web服务的部署和实现,对Web服务的开发人员而言,SOAP/WSDL变得透明,这有利于加速Web服务的开发周期。

· JAXR 
JAXR(Java API for XML Registries)提供了与多种类型注册服务进行交互的API。JAXR运行客户端访问与JAXR规范相兼容的Web Servcices,这里的Web Services即为注册服务。一般来说,注册服务总是以Web Services的形式运行的。JAXR支持三种注册服务类型:JAXR Pluggable Provider、Registry-specific JAXR Provider、JAXR Bridge Provider(支持UDDI Registry和ebXML Registry/Repository等)。

· SAAJ 
SAAJ(SOAP with Attachemnts API for Java)是JAX-RPC的一个增强,为进行低层次的SOAP消息操纵提供了支持。

企业级应用示例

下面我们通过假设一个企业应用的J2EE实现,来了解各种组件和服务的应用。假设应用对象是计算机产品的生产商/零售商的销售系统,这个销售系统能够通过自己的网站发布产品信息,同时也能将产品目录传送给计算机产品交易市场。销售系统能够在线接受订单(来自自己的Web网站或者来自计算机产品交易市场),并随后转入内部企业管理系统进行相关的后续处理。

参见图3,这个企业应用可以这种方式架构。该企业应用的核心是产品目录管理和产品定购管理这两个业务逻辑,使用EJB加以实现,并部署在EJB容器中。由于产品目录和定购信息都需要持久化,因此使用JDBC连接数据库,并使用JTA来完成数据库存取事务。

图3 J2EE应用示例

然后使用JSP/Servlet来实现应用的Web表现:在线产品目录浏览和在线定购。为了将产品目录发送给特定的交易市场,使用JMS实现异步的基于消息的产品目录传输。为了使得更多的其它外部交易市场能够集成产品目录和定购业务,需要使用Web Services技术包装商业逻辑的实现。由于产品定购管理需要由公司内部雇员进行处理,因此需要集成公司内部的用户系统和访问控制服务以方便雇员的使用,使用JACC集成内部的访问控制服务,使用JNDI集成内部的用户目录,并使用JAAS进行访问控制。由于产品订购事务会触发后续的企业ERP系统的相关操作(包括仓储、财务、生产等),需要使用JCA连接企业ERP。

最后为了将这个应用纳入到企业整体的系统管理体系中去,使用Application Client架构了一个管理客户端(与其它企业应用管理应用部署在一台机器上),并通过JMX管理这个企业应用。

RF-SIM卡简介

RF-SIM卡简介
RFSIM卡是可实现中近距离无线通信的手机智能卡,专利技术是一个可代替钱包、钥匙和身份证的全方位服务平台。它的最大特点是不需换手机,现有手机换一张智能卡后就成了类 NFC手机,但使用的频率是2.4G,不是13.56M,通信距离可在10-500CM自动调整,单向支持100M(数据广播)


SIM 卡部分用于正常的手机移动通讯、鉴权,仅用作与手机的物理连接;
内置软件用于管理高安全度的RF-ID、 内置e-credit电子信用卡、EMV电子钱包以及其他基于mifare 逻辑的VIP会员卡;
使用微型RF模块并通过内置的天线与外部设备通讯。
通讯特征:
使用2.4G频段, 自动选频
通信速率1M,高可靠性连接与通信
支持自动感应和主动出发连接两种通信方法
双向通信距离10CM-500CM,可以根据应用调整
单向数据广播(半径100M)
刷卡感应功能可自行启闭(节电)
数据空中传输自动TDES加密, 防窃听数据,刷卡时双向认证
RF-SIM卡主要功能包括:
• 标准SIM功能(GSM 11.11,11.14),
• 电子钱包功能(模拟Mifare数据逻辑结构并符合PBOC2.0以及EMV电子信用卡的规范要求,支持空中开卡和充值),
• 远程支付功能(Rsa),
• 超级VIP卡功能(CRM 、积分、打折、交易),
• 电子票据功能,可以应用RF-SIM卡
• 电子证件功能,
• 名片交换功能,
• 现场组网隐身聊天功能(QQ),
• 彩票功能,
• 门禁功能,
• 情景OTA。

Java 工厂模式

工厂模式定义:提供创建对象的接口.

为何使用?
工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。

为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

我们以类Sample为例, 如果我们要创建Sample的实例对象:

Sample sample=new Sample();

可是,实际情况是,通常我们都要在创建sample实例时做点初始化的工作,比如赋值 查询数据库等。

首先,我们想到的是,可以使用Sample的构造函数,这样生成实例就写成:

Sample sample=new Sample(参数);

但是,如果创建sample实例时所做的初始化工作不是象赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,那你的代码很难看了(就需要Refactor重整)。

为什么说代码很难看,初学者可能没有这种感觉,我们分析如下,初始化工作如果是很长一段代码,说明要做的工作很多,将很多工作装入一个方法中,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有背于Java面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间偶合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。

在本例中,首先,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。

这时我们就需要Factory工厂模式来生成对象了,不能再用上面简单new Sample(参数)。还有,如果Sample有个继承如MySample, 按照面向接口编程,我们需要将Sample抽象成一个接口.现在Sample是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:

Sample mysample=new MySample();
Sample hissample=new HisSample();

随着项目的深入,Sample可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的.

但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了.

工厂方法
你会建立一个专门生产Sample实例的工厂:

public class Factory{

  public static Sample creator(int which){

  //getClass 产生Sample 一般可使用动态类装载装入类。
  if (which==1)
    return new SampleA();
  else if (which==2)
    return new SampleB();

  }

}

那么在你的程序中,如果要实例化Sample时.就使用

Sample sampleA=Factory.creator(1);

这样,在整个就不涉及到Sample的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻:就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,范错误可能性就越少.好象我们从编程序中也能悟出人生道理?呵呵.

使用工厂方法 要注意几个角色,首先你要定义产品接口,如上面的Sample,产品接口下有Sample接口的实现类,如SampleA,其次要有一个factory类,用来生成产品Sample,如下图,最右边是生产的对象Sample:

进一步稍微复杂一点,就是在工厂类上进行拓展,工厂类也有继承它的实现类concreteFactory了

抽象工厂
工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory).

这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法中是创建一个对象Sample,如果我们还有新的产品接口Sample2.

这里假设:Sample有两个concrete类SampleA和SamleB,而Sample2也有两个concrete类Sample2A和SampleB2

那么,我们就将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现,下面就是将上例中的Factory拓展成抽象工厂:

public abstract class Factory{

  public abstract Sample creator();

  public abstract Sample2 creator(String name);

}

public class SimpleFactory extends Factory{

  public Sample creator(){
    .........
    return new SampleA

  }

  public Sample2 creator(String name){
    .........
    return new Sample2A

  }

}

public class BombFactory extends Factory{

  public Sample creator(){
    ......
    return new SampleB
 
  }

  public Sample2 creator(String name){
    ......
    return new Sample2B
  }

}

 

从上面看到两个工厂各自生产出一套Sample和Sample2,也许你会疑问,为什么我不可以使用两个工厂方法来分别生产Sample和Sample2?

抽象工厂还有另外一个关键要点,是因为 SimpleFactory内,生产Sample和生产Sample2的方法之间有一定联系,所以才要将这两个方法捆绑在一个类中,这个工厂类有其本身特征,也许制造过程是统一的,比如:制造工艺比较简单,所以名称叫SimpleFactory。

在实际应用中,工厂方法用得比较多一些,而且是和动态类装入器组合在一起应用,

举例

我们以Jive的ForumFactory为例,这个例子在前面的Singleton模式中我们讨论过,现在再讨论其工厂模式:

public abstract class ForumFactory {

  private static Object initLock = new Object();
  private static String className = "com.jivesoftware.forum.database.DbForumFactory";
  private static ForumFactory factory = null;

  public static ForumFactory getInstance(Authorization authorization) {
    //If no valid authorization passed in, return null.
    if (authorization == null) {
      return null;
    }
    //以下使用了Singleton 单态模式
    if (factory == null) {
      synchronized(initLock) {
        if (factory == null) {
            ......

          try {
              //动态转载类
              Class c = Class.forName(className);
              factory = (ForumFactory)c.newInstance();
          }
          catch (Exception e) {
              return null;
          }
        }
      }
    }

    //Now, 返回 proxy.用来限制授权对forum的访问
    return new ForumFactoryProxy(authorization, factory,
                    factory.getPermissions(authorization));
  }

  //真正创建forum的方法由继承forumfactory的子类去完成.
  public abstract Forum createForum(String name, String description)
  throws UnauthorizedException, ForumAlreadyExistsException;

  ....

}

 

 

因为现在的Jive是通过数据库系统存放论坛帖子等内容数据,如果希望更改为通过文件系统实现,这个工厂方法ForumFactory就提供了提供动态接口:

private static String className = "com.jivesoftware.forum.database.DbForumFactory";

你可以使用自己开发的创建forum的方法代替com.jivesoftware.forum.database.DbForumFactory就可以.

在上面的一段代码中一共用了三种模式,除了工厂模式外,还有Singleton单态模式,以及proxy模式,proxy模式主要用来授权用户对forum的访问,因为访问forum有两种人:一个是注册用户 一个是游客guest,那么那么相应的权限就不一样,而且这个权限是贯穿整个系统的,因此建立一个proxy,类似网关的概念,可以很好的达到这个效果.  

看看Java宠物店中的CatalogDAOFactory:

public class CatalogDAOFactory {

  /**

  * 本方法制定一个特别的子类来实现DAO模式。
  * 具体子类定义是在J2EE的部署描述器中。
  */

  public static CatalogDAO getDAO() throws CatalogDAOSysException {

    CatalogDAO catDao = null;

    try {

      InitialContext ic = new InitialContext();
      //动态装入CATALOG_DAO_CLASS
      //可以定义自己的CATALOG_DAO_CLASS,从而在无需变更太多代码
      //的前提下,完成系统的巨大变更。

      String className =(String) ic.lookup(JNDINames.CATALOG_DAO_CLASS);

      catDao = (CatalogDAO) Class.forName(className).newInstance();

    } catch (NamingException ne) {

      throw new CatalogDAOSysException("
        CatalogDAOFactory.getDAO: NamingException while 
          getting DAO type : \n" + ne.getMessage());

    } catch (Exception se) {

      throw new CatalogDAOSysException("
        CatalogDAOFactory.getDAO: Exception while getting 
          DAO type : \n" + se.getMessage());

    }

    return catDao;

  }

}


CatalogDAOFactory是典型的工厂方法,catDao是通过动态类装入器className获得CatalogDAOFactory具体实现子类,这个实现子类在Java宠物店是用来操作catalog数据库,用户可以根据数据库的类型不同,定制自己的具体实现子类,将自己的子类名给与CATALOG_DAO_CLASS变量就可以。

由此可见,工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制,只要我们更换一下具体的工厂方法,系统其他地方无需一点变换,就有可能将系统功能进行改头换面的变化。