Java解析网络数据流的三种特殊方法
发贴日期:
2008-06-25 [ 0人评论过 ]
Java解析网络数据流的三种特殊方法
介绍用Java解析网络数据的三种特殊方法,希望对正在寻求这方面问题答案的读者有所帮助。
UTF8转换成GB2312 当我们在基于HTTP协议的JSP或Servlet的应用中获取数据或发送请求时,JVM会把输送的数据编码成UTF8格式。如果我们直接从HTTP流中提取中文数据,提取的结果为“????”(可能更多问号),为转换成我们能够理解的中文字符,我们需要把UTF8转换成GB2312,借助ISO-8859-1标准编码能够轻易的实现,下面的代码实现了这一功能: qq:253490497
以下是引用片段:
byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP流中取"NAME"的UTF8数据
b = utf8_value.getBytes("8859_1"); //中间用ISO-8859-1过渡
String name = new String(b, "GB2312"); //转换成GB2312字符
在知道流长度的情况下将输入流转换成字节数组 Java中的输入流抽象类InputStream有int read(byte[] b, int off, int len)方法,参数中byte[] b是用来存放从InputStream中读取的数据,int off指定数组b的偏移地址,也就是数组b的起始下标,int len指定需要读取的长度,方法返回实际读取的字节数。刚学Java的朋友可能要说:先定义一个与流长度等长的字节数组,调用read方法,指定起始下标为0,指定读取长度与数组长度等长,不是一下子可以读出来了吗?说的没错,笔者曾经也试着这样读取数据,但后来发现在读取网络数据时很不安全,我们想想在网络上获取数据可能并没那么流畅,数据流的传送可能会断断续续,所以并不能保证一次就能读取全部数据,特别是在读取大容量数据时更是如此,所以我们必须在读取数据时检测实际读到的长度,如果没有读完已知长度的数据就应该再次读取,以此循环检测,直到实际读取的长度累加与已知的长度相等,下面的代码实现了这一功能: www.createedu.com
以下是引用片段:
ServletInputStream inStream = request.getInputStream(); //取HTTP请求流
int size = request.getContentLength(); //取HTTP请求流长度
byte[] buffer = new byte[size]; //用于缓存每次读取的数据
byte[] in_b = new byte[size]; //用于存放结果的数组
int count = 0;
int rbyte = 0;
while (count < size) { //循环读取
rbyte = inStream.read(buffer); //每次实际读取长度存于rbyte中
for(int i=0;i
in_b[count + i] = buffer[i];
}
count += rbyte;
}
介绍用Java解析网络数据的三种特殊方法,希望对正在寻求这方面问题答案的读者有所帮助。
UTF8转换成GB2312 当我们在基于HTTP协议的JSP或Servlet的应用中获取数据或发送请求时,JVM会把输送的数据编码成UTF8格式。如果我们直接从HTTP流中提取中文数据,提取的结果为“????”(可能更多问号),为转换成我们能够理解的中文字符,我们需要把UTF8转换成GB2312,借助ISO-8859-1标准编码能够轻易的实现,下面的代码实现了这一功能: qq:253490497
以下是引用片段:
byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP流中取"NAME"的UTF8数据
b = utf8_value.getBytes("8859_1"); //中间用ISO-8859-1过渡
String name = new String(b, "GB2312"); //转换成GB2312字符
在知道流长度的情况下将输入流转换成字节数组 Java中的输入流抽象类InputStream有int read(byte[] b, int off, int len)方法,参数中byte[] b是用来存放从InputStream中读取的数据,int off指定数组b的偏移地址,也就是数组b的起始下标,int len指定需要读取的长度,方法返回实际读取的字节数。刚学Java的朋友可能要说:先定义一个与流长度等长的字节数组,调用read方法,指定起始下标为0,指定读取长度与数组长度等长,不是一下子可以读出来了吗?说的没错,笔者曾经也试着这样读取数据,但后来发现在读取网络数据时很不安全,我们想想在网络上获取数据可能并没那么流畅,数据流的传送可能会断断续续,所以并不能保证一次就能读取全部数据,特别是在读取大容量数据时更是如此,所以我们必须在读取数据时检测实际读到的长度,如果没有读完已知长度的数据就应该再次读取,以此循环检测,直到实际读取的长度累加与已知的长度相等,下面的代码实现了这一功能: www.createedu.com
以下是引用片段:
ServletInputStream inStream = request.getInputStream(); //取HTTP请求流
int size = request.getContentLength(); //取HTTP请求流长度
byte[] buffer = new byte[size]; //用于缓存每次读取的数据
byte[] in_b = new byte[size]; //用于存放结果的数组
int count = 0;
int rbyte = 0;
while (count < size) { //循环读取
rbyte = inStream.read(buffer); //每次实际读取长度存于rbyte中
for(int i=0;i
in_b[count + i] = buffer[i];
}
count += rbyte;
}
Java解析网络数据流的三种特殊方法
发贴日期:
2008-06-25 [ 0人评论过 ]
Java解析网络数据流的三种特殊方法
介绍用Java解析网络数据的三种特殊方法,希望对正在寻求这方面问题答案的读者有所帮助。
UTF8转换成GB2312 当我们在基于HTTP协议的JSP或Servlet的应用中获取数据或发送请求时,JVM会把输送的数据编码成UTF8格式。如果我们直接从HTTP流中提取中文数据,提取的结果为“????”(可能更多问号),为转换成我们能够理解的中文字符,我们需要把UTF8转换成GB2312,借助ISO-8859-1标准编码能够轻易的实现,下面的代码实现了这一功能: qq:253490497
以下是引用片段:
byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP流中取"NAME"的UTF8数据
b = utf8_value.getBytes("8859_1"); //中间用ISO-8859-1过渡
String name = new String(b, "GB2312"); //转换成GB2312字符
在知道流长度的情况下将输入流转换成字节数组 Java中的输入流抽象类InputStream有int read(byte[] b, int off, int len)方法,参数中byte[] b是用来存放从InputStream中读取的数据,int off指定数组b的偏移地址,也就是数组b的起始下标,int len指定需要读取的长度,方法返回实际读取的字节数。刚学Java的朋友可能要说:先定义一个与流长度等长的字节数组,调用read方法,指定起始下标为0,指定读取长度与数组长度等长,不是一下子可以读出来了吗?说的没错,笔者曾经也试着这样读取数据,但后来发现在读取网络数据时很不安全,我们想想在网络上获取数据可能并没那么流畅,数据流的传送可能会断断续续,所以并不能保证一次就能读取全部数据,特别是在读取大容量数据时更是如此,所以我们必须在读取数据时检测实际读到的长度,如果没有读完已知长度的数据就应该再次读取,以此循环检测,直到实际读取的长度累加与已知的长度相等,下面的代码实现了这一功能: www.createedu.com
以下是引用片段:
ServletInputStream inStream = request.getInputStream(); //取HTTP请求流
int size = request.getContentLength(); //取HTTP请求流长度
byte[] buffer = new byte[size]; //用于缓存每次读取的数据
byte[] in_b = new byte[size]; //用于存放结果的数组
int count = 0;
int rbyte = 0;
while (count < size) { //循环读取
rbyte = inStream.read(buffer); //每次实际读取长度存于rbyte中
for(int i=0;i
in_b[count + i] = buffer[i];
}
count += rbyte;
}
介绍用Java解析网络数据的三种特殊方法,希望对正在寻求这方面问题答案的读者有所帮助。
UTF8转换成GB2312 当我们在基于HTTP协议的JSP或Servlet的应用中获取数据或发送请求时,JVM会把输送的数据编码成UTF8格式。如果我们直接从HTTP流中提取中文数据,提取的结果为“????”(可能更多问号),为转换成我们能够理解的中文字符,我们需要把UTF8转换成GB2312,借助ISO-8859-1标准编码能够轻易的实现,下面的代码实现了这一功能: qq:253490497
以下是引用片段:
byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP流中取"NAME"的UTF8数据
b = utf8_value.getBytes("8859_1"); //中间用ISO-8859-1过渡
String name = new String(b, "GB2312"); //转换成GB2312字符
在知道流长度的情况下将输入流转换成字节数组 Java中的输入流抽象类InputStream有int read(byte[] b, int off, int len)方法,参数中byte[] b是用来存放从InputStream中读取的数据,int off指定数组b的偏移地址,也就是数组b的起始下标,int len指定需要读取的长度,方法返回实际读取的字节数。刚学Java的朋友可能要说:先定义一个与流长度等长的字节数组,调用read方法,指定起始下标为0,指定读取长度与数组长度等长,不是一下子可以读出来了吗?说的没错,笔者曾经也试着这样读取数据,但后来发现在读取网络数据时很不安全,我们想想在网络上获取数据可能并没那么流畅,数据流的传送可能会断断续续,所以并不能保证一次就能读取全部数据,特别是在读取大容量数据时更是如此,所以我们必须在读取数据时检测实际读到的长度,如果没有读完已知长度的数据就应该再次读取,以此循环检测,直到实际读取的长度累加与已知的长度相等,下面的代码实现了这一功能: www.createedu.com
以下是引用片段:
ServletInputStream inStream = request.getInputStream(); //取HTTP请求流
int size = request.getContentLength(); //取HTTP请求流长度
byte[] buffer = new byte[size]; //用于缓存每次读取的数据
byte[] in_b = new byte[size]; //用于存放结果的数组
int count = 0;
int rbyte = 0;
while (count < size) { //循环读取
rbyte = inStream.read(buffer); //每次实际读取长度存于rbyte中
for(int i=0;i
in_b[count + i] = buffer[i];
}
count += rbyte;
}
Java解析网络数据流的三种特殊方法
发贴日期:
2008-06-25 [ 0人评论过 ]
Java解析网络数据流的三种特殊方法
介绍用Java解析网络数据的三种特殊方法,希望对正在寻求这方面问题答案的读者有所帮助。
UTF8转换成GB2312 当我们在基于HTTP协议的JSP或Servlet的应用中获取数据或发送请求时,JVM会把输送的数据编码成UTF8格式。如果我们直接从HTTP流中提取中文数据,提取的结果为“????”(可能更多问号),为转换成我们能够理解的中文字符,我们需要把UTF8转换成GB2312,借助ISO-8859-1标准编码能够轻易的实现,下面的代码实现了这一功能: qq:253490497
以下是引用片段:
byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP流中取"NAME"的UTF8数据
b = utf8_value.getBytes("8859_1"); //中间用ISO-8859-1过渡
String name = new String(b, "GB2312"); //转换成GB2312字符
在知道流长度的情况下将输入流转换成字节数组 Java中的输入流抽象类InputStream有int read(byte[] b, int off, int len)方法,参数中byte[] b是用来存放从InputStream中读取的数据,int off指定数组b的偏移地址,也就是数组b的起始下标,int len指定需要读取的长度,方法返回实际读取的字节数。刚学Java的朋友可能要说:先定义一个与流长度等长的字节数组,调用read方法,指定起始下标为0,指定读取长度与数组长度等长,不是一下子可以读出来了吗?说的没错,笔者曾经也试着这样读取数据,但后来发现在读取网络数据时很不安全,我们想想在网络上获取数据可能并没那么流畅,数据流的传送可能会断断续续,所以并不能保证一次就能读取全部数据,特别是在读取大容量数据时更是如此,所以我们必须在读取数据时检测实际读到的长度,如果没有读完已知长度的数据就应该再次读取,以此循环检测,直到实际读取的长度累加与已知的长度相等,下面的代码实现了这一功能: www.createedu.com
以下是引用片段:
ServletInputStream inStream = request.getInputStream(); //取HTTP请求流
int size = request.getContentLength(); //取HTTP请求流长度
byte[] buffer = new byte[size]; //用于缓存每次读取的数据
byte[] in_b = new byte[size]; //用于存放结果的数组
int count = 0;
int rbyte = 0;
while (count < size) { //循环读取
rbyte = inStream.read(buffer); //每次实际读取长度存于rbyte中
for(int i=0;i
in_b[count + i] = buffer[i];
}
count += rbyte;
}
介绍用Java解析网络数据的三种特殊方法,希望对正在寻求这方面问题答案的读者有所帮助。
UTF8转换成GB2312 当我们在基于HTTP协议的JSP或Servlet的应用中获取数据或发送请求时,JVM会把输送的数据编码成UTF8格式。如果我们直接从HTTP流中提取中文数据,提取的结果为“????”(可能更多问号),为转换成我们能够理解的中文字符,我们需要把UTF8转换成GB2312,借助ISO-8859-1标准编码能够轻易的实现,下面的代码实现了这一功能: qq:253490497
以下是引用片段:
byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP流中取"NAME"的UTF8数据
b = utf8_value.getBytes("8859_1"); //中间用ISO-8859-1过渡
String name = new String(b, "GB2312"); //转换成GB2312字符
在知道流长度的情况下将输入流转换成字节数组 Java中的输入流抽象类InputStream有int read(byte[] b, int off, int len)方法,参数中byte[] b是用来存放从InputStream中读取的数据,int off指定数组b的偏移地址,也就是数组b的起始下标,int len指定需要读取的长度,方法返回实际读取的字节数。刚学Java的朋友可能要说:先定义一个与流长度等长的字节数组,调用read方法,指定起始下标为0,指定读取长度与数组长度等长,不是一下子可以读出来了吗?说的没错,笔者曾经也试着这样读取数据,但后来发现在读取网络数据时很不安全,我们想想在网络上获取数据可能并没那么流畅,数据流的传送可能会断断续续,所以并不能保证一次就能读取全部数据,特别是在读取大容量数据时更是如此,所以我们必须在读取数据时检测实际读到的长度,如果没有读完已知长度的数据就应该再次读取,以此循环检测,直到实际读取的长度累加与已知的长度相等,下面的代码实现了这一功能: www.createedu.com
以下是引用片段:
ServletInputStream inStream = request.getInputStream(); //取HTTP请求流
int size = request.getContentLength(); //取HTTP请求流长度
byte[] buffer = new byte[size]; //用于缓存每次读取的数据
byte[] in_b = new byte[size]; //用于存放结果的数组
int count = 0;
int rbyte = 0;
while (count < size) { //循环读取
rbyte = inStream.read(buffer); //每次实际读取长度存于rbyte中
for(int i=0;i
in_b[count + i] = buffer[i];
}
count += rbyte;
}
Java编程思想:面向对象的逻辑思维方法
发贴日期:
2008-06-23 [ 0人评论过 ]
Java编程思想:面向对象的逻辑思维方法
什么是面向对象的设计思想?也许有不少初学者对这个概念还有许多不明白的地方,特别是这个处于新旧思想交替的时代,许多人刚刚学完现在看来是快要淘汰的只是面向过程的语言。他们的脑子还没有脱离面向过程思想的束缚,抬头却发现,“面向对象”早已经流行开来,这个陌生的词漫天飞舞。随便拿起一本流行计算机技术书籍,那里会没有“面向对象”的字眼!于是心中便惶惑了:什么叫“面向对象”?不感兴趣者,一带而过;有志于在这方面发展的,匆忙找到一本有关书籍来啃究竟什么是“面向对象”。然而,要突破思想的束缚,说难也不难,说到要深刻认识却也不容易。笔者在做了一些轻量级的工作后,颇以为有点心得,不怕贻笑大方,写出已供广大同行批评指正。Qq:253490497
“对象(Object)”一词,早在十九世纪就有现象学大师胡塞尔提出并定义。对象是世界中的物体在人脑中的映象,是人的意识之所以为意识的反映,是做为一种概念而存在的先念的东西,它还包括了人的意愿。举例说明吧。当我们认识到一种新的物体,它叫树,于是在我们的意识当中就形成了树的概念。这个概念会一直存在于我们的思维当中,并不会因为这棵树被砍掉而消失。这个概念就是现实世界当中的物体在我们意识当中的映象。我们对它还可以有我们自己的意愿,虽然我们并不需要付诸实现——只要在你的脑中想着把这棵树砍掉做成桌子、凳子等——我们就把它叫做意向。于是,对象就是客观世界中物体在人脑中的映象及人的意向。只要这个对象存在我们的思维意识当中,我们就可以籍此判断同类的东西。譬如,当我们看到另外一棵树是,并不会因为所见的第一棵树不在了失去了供参照的模板而不认识这棵树了。当我们接触某些新事物时,我们的意识就会为这些事物确立一个对象。当然这个过程是怎么形成的,那就不是我们所能讨论的问题了。上面所说的对象研究的是一般意义上的问题,因而它可以外推到一切事物。我们经常所说的“对象”,一班指的是解决信息领域内所遇到问题的方法。特别是应用软件技术来决问题的方法。如我们经常碰到的面向对象的编程(Object-Oriented Programming)、面向对象的分析(Object-Oriented Analysis)、面向对象的设计(Object-Oriented Design)等。应用前面所介绍的关于对象的概念,可以对这些问题做进一步的分析。在面对较复杂的系统,我们可以将它作为一个对象来进行分析。一个系统(解决某个问题的全套解决方案)作为一个对象,可以由多个部分组成。同样,这个对象也可以由多个对象组成。对于同类的事物,可以由一个对象来表示。这样做的益处是显而易见的,它灵活而高效,可以大大减轻设计人员的工作量,简化实际的模型。举一个例子。在关系型数据库的设计当中,我们可以把一个元组当作对象,给它定义一组操作方法。这些方法将适用于所有元组,从而我们不必在更大的范围内去细致的考虑不同的元组(如判断一个元素是否合法):因为它们有一组公共的面向本身的方法,它们“自己”可以“解决”自己的问题。更上一层的对象可以是一个表、视图等。表对象在元组对象的基础上又有它们自己的方法,如增加、删除等。从这个层面上讲,它也只需要做“自己”的事情,因为有元组对象的支持,它无须去考虑像元素是否合法这类的事情。甚至,有时为了满足我们还可以将元素或表群当作时对象并定义它们自己的方法。这样,更能显示面向对象的优势。www.createedu.com
上面所讨论的可以说是面向对象的分析方法。在具体的设计过程当中,还应该采用适当的方式。因为面向对象的思想固然很先进,如果做得不好的话,同样不能达到预期的效果。这主要表现在处理对象与对象的关系上没有做好,对象与对象的层次不分明。如上面所举得关系型数据库得例子,如果在元组层面上得对象过多得考虑一个表对象得因素,或一个表层面上对象过多地考虑一个元组对象的因素,甚至去考虑元素层面上的因素,这些都不是好的面向对象的设计方法。这一点,在语言实现方面,Java比C++更有优势,因为它不允许多重继承,从而使对象之间的关系更明确。谁也不会否认C++的功能更强大,但是它也要由次付出巨大代价——当现在代码库发展到一定程度、一定规模时,个对象之间的层次关系将变得异常复杂,给后继使用者得学习、理解带来很大的困难,应用上很难把握。另外,虽然C++具备面向对象的处理能力,但它还是保留了很多面向过程的东西。用C++完全可以不用面向对象的思想来进行程序设计,当然人们不会这样去做——除了那些只是把C++看成是C扩充的初学者,这就为以后的发展埋下了隐患。在者一方面,Java的限制更多一点。就者一点还远远不够。搞开发的是人,开发方法是由人决定的。要应用面向对象的方法开发出优秀的软件,必须要求开发人员具有良好的面向对象的思想。好的工程师可以利用适当的工具开发出优秀的软件——而不在乎他所使用的语言工具——Java、C++、Object Pascal、Ada等。
什么是面向对象的设计思想?也许有不少初学者对这个概念还有许多不明白的地方,特别是这个处于新旧思想交替的时代,许多人刚刚学完现在看来是快要淘汰的只是面向过程的语言。他们的脑子还没有脱离面向过程思想的束缚,抬头却发现,“面向对象”早已经流行开来,这个陌生的词漫天飞舞。随便拿起一本流行计算机技术书籍,那里会没有“面向对象”的字眼!于是心中便惶惑了:什么叫“面向对象”?不感兴趣者,一带而过;有志于在这方面发展的,匆忙找到一本有关书籍来啃究竟什么是“面向对象”。然而,要突破思想的束缚,说难也不难,说到要深刻认识却也不容易。笔者在做了一些轻量级的工作后,颇以为有点心得,不怕贻笑大方,写出已供广大同行批评指正。Qq:253490497
“对象(Object)”一词,早在十九世纪就有现象学大师胡塞尔提出并定义。对象是世界中的物体在人脑中的映象,是人的意识之所以为意识的反映,是做为一种概念而存在的先念的东西,它还包括了人的意愿。举例说明吧。当我们认识到一种新的物体,它叫树,于是在我们的意识当中就形成了树的概念。这个概念会一直存在于我们的思维当中,并不会因为这棵树被砍掉而消失。这个概念就是现实世界当中的物体在我们意识当中的映象。我们对它还可以有我们自己的意愿,虽然我们并不需要付诸实现——只要在你的脑中想着把这棵树砍掉做成桌子、凳子等——我们就把它叫做意向。于是,对象就是客观世界中物体在人脑中的映象及人的意向。只要这个对象存在我们的思维意识当中,我们就可以籍此判断同类的东西。譬如,当我们看到另外一棵树是,并不会因为所见的第一棵树不在了失去了供参照的模板而不认识这棵树了。当我们接触某些新事物时,我们的意识就会为这些事物确立一个对象。当然这个过程是怎么形成的,那就不是我们所能讨论的问题了。上面所说的对象研究的是一般意义上的问题,因而它可以外推到一切事物。我们经常所说的“对象”,一班指的是解决信息领域内所遇到问题的方法。特别是应用软件技术来决问题的方法。如我们经常碰到的面向对象的编程(Object-Oriented Programming)、面向对象的分析(Object-Oriented Analysis)、面向对象的设计(Object-Oriented Design)等。应用前面所介绍的关于对象的概念,可以对这些问题做进一步的分析。在面对较复杂的系统,我们可以将它作为一个对象来进行分析。一个系统(解决某个问题的全套解决方案)作为一个对象,可以由多个部分组成。同样,这个对象也可以由多个对象组成。对于同类的事物,可以由一个对象来表示。这样做的益处是显而易见的,它灵活而高效,可以大大减轻设计人员的工作量,简化实际的模型。举一个例子。在关系型数据库的设计当中,我们可以把一个元组当作对象,给它定义一组操作方法。这些方法将适用于所有元组,从而我们不必在更大的范围内去细致的考虑不同的元组(如判断一个元素是否合法):因为它们有一组公共的面向本身的方法,它们“自己”可以“解决”自己的问题。更上一层的对象可以是一个表、视图等。表对象在元组对象的基础上又有它们自己的方法,如增加、删除等。从这个层面上讲,它也只需要做“自己”的事情,因为有元组对象的支持,它无须去考虑像元素是否合法这类的事情。甚至,有时为了满足我们还可以将元素或表群当作时对象并定义它们自己的方法。这样,更能显示面向对象的优势。www.createedu.com
上面所讨论的可以说是面向对象的分析方法。在具体的设计过程当中,还应该采用适当的方式。因为面向对象的思想固然很先进,如果做得不好的话,同样不能达到预期的效果。这主要表现在处理对象与对象的关系上没有做好,对象与对象的层次不分明。如上面所举得关系型数据库得例子,如果在元组层面上得对象过多得考虑一个表对象得因素,或一个表层面上对象过多地考虑一个元组对象的因素,甚至去考虑元素层面上的因素,这些都不是好的面向对象的设计方法。这一点,在语言实现方面,Java比C++更有优势,因为它不允许多重继承,从而使对象之间的关系更明确。谁也不会否认C++的功能更强大,但是它也要由次付出巨大代价——当现在代码库发展到一定程度、一定规模时,个对象之间的层次关系将变得异常复杂,给后继使用者得学习、理解带来很大的困难,应用上很难把握。另外,虽然C++具备面向对象的处理能力,但它还是保留了很多面向过程的东西。用C++完全可以不用面向对象的思想来进行程序设计,当然人们不会这样去做——除了那些只是把C++看成是C扩充的初学者,这就为以后的发展埋下了隐患。在者一方面,Java的限制更多一点。就者一点还远远不够。搞开发的是人,开发方法是由人决定的。要应用面向对象的方法开发出优秀的软件,必须要求开发人员具有良好的面向对象的思想。好的工程师可以利用适当的工具开发出优秀的软件——而不在乎他所使用的语言工具——Java、C++、Object Pascal、Ada等。
Java程序开发中代理技术的使用方法
发贴日期:
2008-06-20 [ 0人评论过 ]
Java程序开发中代理技术的使用方法
如果你这样的需求:在运行时创建实现一组给定接口的类,注意这个类是在运行时创建的,你就需要使用JAVA中的代理类来达成你的要求。
代理类提供在运行时创建类的能力,这个新建的类能实现你指定的接口。 当然你不能在运行时为要实现的接口中的方法定义新代码,而是提供一个调用处理器来实现。调用处理器是实现了InvocationHandler接口的类的对象,此接口只有一个方法:
以下是引用片段:
Object invoke(Object proxy,Method mtd,Object[] args)
其中proxy是代理对象;mtd是描述方法的类的对象,此对象执行它的invoke(Object obj,Object[] args)方法可以调用封装在Mthod对象中的方法;args是存储了此方法参数的数组。www.createedu.com qq:253490497
建立代理对象:使用Proxy类的newProxyInstance方法,其格式如下:
以下是引用片段:
Object proxy=Proxy.newProxyInstance(null,interfaces,handler);
其中第一个参数是一个类加载器,这里使用默认加载器,用null表示;第二个参数是一个Class的数组,其每个元素是一个接口,这就是用来指定要实现的一组接口,哪怕只有一个接口也要通过数组来传递;第三个参数就是调用处理器。
在代理对象上调用方法时,调用处理器的invoke方法会被自动调用,正在调用的方法和参数自动传递给inboke方法的jmtdt args形式参数中,同时也会用args参数数组中的参数去调用mtd对象中指定的方法。
代理的应用:方法调用跟踪(把要跟踪的对象包装成代理类对象);为远程调用方法提供路由;用户接口事件与动作关联(C#中有类似的功能)。
如果你这样的需求:在运行时创建实现一组给定接口的类,注意这个类是在运行时创建的,你就需要使用JAVA中的代理类来达成你的要求。
代理类提供在运行时创建类的能力,这个新建的类能实现你指定的接口。 当然你不能在运行时为要实现的接口中的方法定义新代码,而是提供一个调用处理器来实现。调用处理器是实现了InvocationHandler接口的类的对象,此接口只有一个方法:
以下是引用片段:
Object invoke(Object proxy,Method mtd,Object[] args)
其中proxy是代理对象;mtd是描述方法的类的对象,此对象执行它的invoke(Object obj,Object[] args)方法可以调用封装在Mthod对象中的方法;args是存储了此方法参数的数组。www.createedu.com qq:253490497
建立代理对象:使用Proxy类的newProxyInstance方法,其格式如下:
以下是引用片段:
Object proxy=Proxy.newProxyInstance(null,interfaces,handler);
其中第一个参数是一个类加载器,这里使用默认加载器,用null表示;第二个参数是一个Class的数组,其每个元素是一个接口,这就是用来指定要实现的一组接口,哪怕只有一个接口也要通过数组来传递;第三个参数就是调用处理器。
在代理对象上调用方法时,调用处理器的invoke方法会被自动调用,正在调用的方法和参数自动传递给inboke方法的jmtdt args形式参数中,同时也会用args参数数组中的参数去调用mtd对象中指定的方法。
代理的应用:方法调用跟踪(把要跟踪的对象包装成代理类对象);为远程调用方法提供路由;用户接口事件与动作关联(C#中有类似的功能)。
面试时,您将面对哪些问题?
发贴日期:
2008-06-14 [ 1人评论过 ]
面试时,您将面对哪些问题?
面试,是每一个求职者都要面对的过程。有备才能无患。面试前要做的准备工作有许多,但许多人却忽视可能面对的提问作出必要的“预习”,因为他们不知道主考官将怎样问和问些什么问题。(国信蓝点—顶级java培训)
下面这些问题是在面试中经常会被问到的,如果您对它早有准备,就不会临阵慌忙,不妨试一试。
1、您父母的职业是什么?
2、您在业余时间主要干些什么?
3、您为什么要(不再)读书? www.createedu.com
4、您主要缺点是什么?准备如何克服?
5、您有哪些职业发展计划?
6、您认为您最适合干什么?javaqq:326473669
7、您为什么至今没有找到满意的工作?
8、您为什么要离开原单位?
9、这是您辞职的唯一原因吗?
10、您为什么要进我们公司?(0312-3339702)
11、您最引以为自豪的成就是什么?
12、如果您想招聘人,喜欢怎样的人?
13、您有多少时间可以用来出差?
14、对枯燥单调的工作您也愿意干吗?
15、您希望您的工资是多少?
16、您觉得您与其他求职者有何不同?
17、为什么我们应该首先选择您?
18、有没有别的公司愿意聘用您?www.createedu.com
19、如果本公司与另一家公司同时要聘用您,您如何选择?
20、您还有什么想问的?
当您第一次听到这些问题时会感到很棘手,好在您现在已度过了每一次窘境,当您再次面对主考官时,您可能早已“胸有成竹” 了。
面试,是每一个求职者都要面对的过程。有备才能无患。面试前要做的准备工作有许多,但许多人却忽视可能面对的提问作出必要的“预习”,因为他们不知道主考官将怎样问和问些什么问题。(国信蓝点—顶级java培训)
下面这些问题是在面试中经常会被问到的,如果您对它早有准备,就不会临阵慌忙,不妨试一试。
1、您父母的职业是什么?
2、您在业余时间主要干些什么?
3、您为什么要(不再)读书? www.createedu.com
4、您主要缺点是什么?准备如何克服?
5、您有哪些职业发展计划?
6、您认为您最适合干什么?javaqq:326473669
7、您为什么至今没有找到满意的工作?
8、您为什么要离开原单位?
9、这是您辞职的唯一原因吗?
10、您为什么要进我们公司?(0312-3339702)
11、您最引以为自豪的成就是什么?
12、如果您想招聘人,喜欢怎样的人?
13、您有多少时间可以用来出差?
14、对枯燥单调的工作您也愿意干吗?
15、您希望您的工资是多少?
16、您觉得您与其他求职者有何不同?
17、为什么我们应该首先选择您?
18、有没有别的公司愿意聘用您?www.createedu.com
19、如果本公司与另一家公司同时要聘用您,您如何选择?
20、您还有什么想问的?
当您第一次听到这些问题时会感到很棘手,好在您现在已度过了每一次窘境,当您再次面对主考官时,您可能早已“胸有成竹” 了。
大学毕业后的第一份工作,你找对了吗?
发贴日期:
2008-06-14 [ 1人评论过 ]
大学毕业后的第一份工作,你找对了吗?
现在有很多大学生畏惧严峻的就业压力,在投出一份又一份的简历而仍旧没有任何一家公司肯接纳自己后,往往缺乏对自身起码的责任心和自信心,把自己看得太廉价,把工作看得太随便。碰到一家公司肯要自己,就忙不迭的答应下来了,也不管自己是否喜欢,也不管是否适合自己。因此,在“巨无霸”的阴影下,不少大学生选择洗脚工这一职业也就不足为怪了。
人的第一份工作它奠定了一个人很多的思考习惯和行为习惯。在高效率的公司工作过,到了低效率的公司也能适应。不过要是在一个小公司养成了一身坏毛病,以后的发展就会受到极大的限制。大公司之所以能成为大公司,肯定有其过人之处。进一个好公司相当于上一个好大学,不知不觉中就出息起来了。
很多大学生怀揣“先就业后择业”的糊涂想法,这种做法给很多企业在成本输出上造成了莫大的损失,如此一来,一些饱受伤害的用人单位甚至做出“拒绝聘用应届毕业生”的决定,令大学生就业市场雪上加霜。随便找个公司挂靠的“先就业后择业”做法,无疑是“治标不治本”的错误之举,对自身定位不准,难以人尽其才,久而久之会让你的职业生涯陷入恶性循环。
在就业难的压力下,很多大学生对自己的职业生涯没有一个良好的规划,不清楚自己适合干什么,找工作盲目而缺乏目标性,在社会上晃荡了两年之后,发现自己依然无法适应社会的需求。而此时,若再想回头,却早已错过了锻造职业生涯的黄金时期。
因为,在人生事业的起跳点,你早已纵身于深渊之中;在职业列车的始发站,你的列车早已驶错方向。
比之这些失败者,身边一些成功者的鲜活案例值得我们警醒和深思:小李同学(Java程序员),2007级应届毕业生,现就职于三星数据公司。
是什么让他在尚未毕业就具备如此竞争力呢?机遇?能力?命运?或许,李同学下面一番话可以向我们揭示谜团所在。
“在学校学习的过程中,我参加社会实践的机会很少,所以在经验的积累上就很欠缺,不能做到专业学习与就业有机结合,以致在面试的过程中屡屡碰壁。我开始冷静思考该如何迅速提升自身竞争力。后来我来到到蓝点世纪参加职业培训,之所以选择这家公司,比较吸引我的是他们的项目驱动式培训模式,讲练相结合的教学模式更有利于我自己知识的巩固,超强度的编程练习和项目实战演练,弥补了我在经验上的不足,经过这样一个再教育的过程,现在我的能力相当于一个拥有一年工作经验的工程师的水平,但我比他们更大的优势在于,自己在接受职业培训的过程中,也积累了很广泛的人脉资源。
毕业后蓝点世纪的老师也给了我很多无偿的技术支持。我能取得今天的成功,正因为我充分认识到第一份工作对我职业生涯的影响,也充分验证了积极进行职业规划的正确性。现在我还没有毕业,就已经被三星数据公司优先录用了,比之身边的同学,我简直太幸运了!”
相比一些游离于社会边缘的求职者,李同学的确是非常幸运的,但是这样的幸运并非偶然。在就业这个问题上,如果你从一开始就自暴自弃,那么谁也拯救不了你;相反,如果你能够做到运筹帷幄积极应对,那么连上帝都阻止不了你前进的脚步。对于迈出校园的第一份工作,大学生自身要承担起最终的责任,因为只有你自己才是找到一个好工作的最终受益者。不要说在论文设计和求职两者间存在时间上的落差,如果你足够聪明,并且愿意对自己的前途负责,我想你明白如何使两者兼容从而并行不悖。
记住,没有人会为你的职业前程买单。成功无他途,只有努力干。
参考:www.createedu.com
现在有很多大学生畏惧严峻的就业压力,在投出一份又一份的简历而仍旧没有任何一家公司肯接纳自己后,往往缺乏对自身起码的责任心和自信心,把自己看得太廉价,把工作看得太随便。碰到一家公司肯要自己,就忙不迭的答应下来了,也不管自己是否喜欢,也不管是否适合自己。因此,在“巨无霸”的阴影下,不少大学生选择洗脚工这一职业也就不足为怪了。
人的第一份工作它奠定了一个人很多的思考习惯和行为习惯。在高效率的公司工作过,到了低效率的公司也能适应。不过要是在一个小公司养成了一身坏毛病,以后的发展就会受到极大的限制。大公司之所以能成为大公司,肯定有其过人之处。进一个好公司相当于上一个好大学,不知不觉中就出息起来了。
很多大学生怀揣“先就业后择业”的糊涂想法,这种做法给很多企业在成本输出上造成了莫大的损失,如此一来,一些饱受伤害的用人单位甚至做出“拒绝聘用应届毕业生”的决定,令大学生就业市场雪上加霜。随便找个公司挂靠的“先就业后择业”做法,无疑是“治标不治本”的错误之举,对自身定位不准,难以人尽其才,久而久之会让你的职业生涯陷入恶性循环。
在就业难的压力下,很多大学生对自己的职业生涯没有一个良好的规划,不清楚自己适合干什么,找工作盲目而缺乏目标性,在社会上晃荡了两年之后,发现自己依然无法适应社会的需求。而此时,若再想回头,却早已错过了锻造职业生涯的黄金时期。
因为,在人生事业的起跳点,你早已纵身于深渊之中;在职业列车的始发站,你的列车早已驶错方向。
比之这些失败者,身边一些成功者的鲜活案例值得我们警醒和深思:小李同学(Java程序员),2007级应届毕业生,现就职于三星数据公司。
是什么让他在尚未毕业就具备如此竞争力呢?机遇?能力?命运?或许,李同学下面一番话可以向我们揭示谜团所在。
“在学校学习的过程中,我参加社会实践的机会很少,所以在经验的积累上就很欠缺,不能做到专业学习与就业有机结合,以致在面试的过程中屡屡碰壁。我开始冷静思考该如何迅速提升自身竞争力。后来我来到到蓝点世纪参加职业培训,之所以选择这家公司,比较吸引我的是他们的项目驱动式培训模式,讲练相结合的教学模式更有利于我自己知识的巩固,超强度的编程练习和项目实战演练,弥补了我在经验上的不足,经过这样一个再教育的过程,现在我的能力相当于一个拥有一年工作经验的工程师的水平,但我比他们更大的优势在于,自己在接受职业培训的过程中,也积累了很广泛的人脉资源。
毕业后蓝点世纪的老师也给了我很多无偿的技术支持。我能取得今天的成功,正因为我充分认识到第一份工作对我职业生涯的影响,也充分验证了积极进行职业规划的正确性。现在我还没有毕业,就已经被三星数据公司优先录用了,比之身边的同学,我简直太幸运了!”
相比一些游离于社会边缘的求职者,李同学的确是非常幸运的,但是这样的幸运并非偶然。在就业这个问题上,如果你从一开始就自暴自弃,那么谁也拯救不了你;相反,如果你能够做到运筹帷幄积极应对,那么连上帝都阻止不了你前进的脚步。对于迈出校园的第一份工作,大学生自身要承担起最终的责任,因为只有你自己才是找到一个好工作的最终受益者。不要说在论文设计和求职两者间存在时间上的落差,如果你足够聪明,并且愿意对自己的前途负责,我想你明白如何使两者兼容从而并行不悖。
记住,没有人会为你的职业前程买单。成功无他途,只有努力干。
参考:www.createedu.com
大学毕业后的第一份工作,你找对了吗?
发贴日期:
2008-06-14 [ 0人评论过 ]
大学毕业后的第一份工作,你找对了吗?
现在有很多大学生畏惧严峻的就业压力,在投出一份又一份的简历而仍旧没有任何一家公司肯接纳自己后,往往缺乏对自身起码的责任心和自信心,把自己看得太廉价,把工作看得太随便。碰到一家公司肯要自己,就忙不迭的答应下来了,也不管自己是否喜欢,也不管是否适合自己。因此,在“巨无霸”的阴影下,不少大学生选择洗脚工这一职业也就不足为怪了。
人的第一份工作它奠定了一个人很多的思考习惯和行为习惯。在高效率的公司工作过,到了低效率的公司也能适应。不过要是在一个小公司养成了一身坏毛病,以后的发展就会受到极大的限制。大公司之所以能成为大公司,肯定有其过人之处。进一个好公司相当于上一个好大学,不知不觉中就出息起来了。
很多大学生怀揣“先就业后择业”的糊涂想法,这种做法给很多企业在成本输出上造成了莫大的损失,如此一来,一些饱受伤害的用人单位甚至做出“拒绝聘用应届毕业生”的决定,令大学生就业市场雪上加霜。随便找个公司挂靠的“先就业后择业”做法,无疑是“治标不治本”的错误之举,对自身定位不准,难以人尽其才,久而久之会让你的职业生涯陷入恶性循环。
在就业难的压力下,很多大学生对自己的职业生涯没有一个良好的规划,不清楚自己适合干什么,找工作盲目而缺乏目标性,在社会上晃荡了两年之后,发现自己依然无法适应社会的需求。而此时,若再想回头,却早已错过了锻造职业生涯的黄金时期。
因为,在人生事业的起跳点,你早已纵身于深渊之中;在职业列车的始发站,你的列车早已驶错方向。
比之这些失败者,身边一些成功者的鲜活案例值得我们警醒和深思:小李同学(Java程序员),2007级应届毕业生,现就职于三星数据公司。
是什么让他在尚未毕业就具备如此竞争力呢?机遇?能力?命运?或许,李同学下面一番话可以向我们揭示谜团所在。
“在学校学习的过程中,我参加社会实践的机会很少,所以在经验的积累上就很欠缺,不能做到专业学习与就业有机结合,以致在面试的过程中屡屡碰壁。我开始冷静思考该如何迅速提升自身竞争力。后来我来到到蓝点世纪参加职业培训,之所以选择这家公司,比较吸引我的是他们的项目驱动式培训模式,讲练相结合的教学模式更有利于我自己知识的巩固,超强度的编程练习和项目实战演练,弥补了我在经验上的不足,经过这样一个再教育的过程,现在我的能力相当于一个拥有一年工作经验的工程师的水平,但我比他们更大的优势在于,自己在接受职业培训的过程中,也积累了很广泛的人脉资源。
毕业后蓝点世纪的老师也给了我很多无偿的技术支持。我能取得今天的成功,正因为我充分认识到第一份工作对我职业生涯的影响,也充分验证了积极进行职业规划的正确性。现在我还没有毕业,就已经被三星数据公司优先录用了,比之身边的同学,我简直太幸运了!”
相比一些游离于社会边缘的求职者,李同学的确是非常幸运的,但是这样的幸运并非偶然。在就业这个问题上,如果你从一开始就自暴自弃,那么谁也拯救不了你;相反,如果你能够做到运筹帷幄积极应对,那么连上帝都阻止不了你前进的脚步。对于迈出校园的第一份工作,大学生自身要承担起最终的责任,因为只有你自己才是找到一个好工作的最终受益者。不要说在论文设计和求职两者间存在时间上的落差,如果你足够聪明,并且愿意对自己的前途负责,我想你明白如何使两者兼容从而并行不悖。
记住,没有人会为你的职业前程买单。成功无他途,只有努力干。
参考:www.createedu.com
现在有很多大学生畏惧严峻的就业压力,在投出一份又一份的简历而仍旧没有任何一家公司肯接纳自己后,往往缺乏对自身起码的责任心和自信心,把自己看得太廉价,把工作看得太随便。碰到一家公司肯要自己,就忙不迭的答应下来了,也不管自己是否喜欢,也不管是否适合自己。因此,在“巨无霸”的阴影下,不少大学生选择洗脚工这一职业也就不足为怪了。
人的第一份工作它奠定了一个人很多的思考习惯和行为习惯。在高效率的公司工作过,到了低效率的公司也能适应。不过要是在一个小公司养成了一身坏毛病,以后的发展就会受到极大的限制。大公司之所以能成为大公司,肯定有其过人之处。进一个好公司相当于上一个好大学,不知不觉中就出息起来了。
很多大学生怀揣“先就业后择业”的糊涂想法,这种做法给很多企业在成本输出上造成了莫大的损失,如此一来,一些饱受伤害的用人单位甚至做出“拒绝聘用应届毕业生”的决定,令大学生就业市场雪上加霜。随便找个公司挂靠的“先就业后择业”做法,无疑是“治标不治本”的错误之举,对自身定位不准,难以人尽其才,久而久之会让你的职业生涯陷入恶性循环。
在就业难的压力下,很多大学生对自己的职业生涯没有一个良好的规划,不清楚自己适合干什么,找工作盲目而缺乏目标性,在社会上晃荡了两年之后,发现自己依然无法适应社会的需求。而此时,若再想回头,却早已错过了锻造职业生涯的黄金时期。
因为,在人生事业的起跳点,你早已纵身于深渊之中;在职业列车的始发站,你的列车早已驶错方向。
比之这些失败者,身边一些成功者的鲜活案例值得我们警醒和深思:小李同学(Java程序员),2007级应届毕业生,现就职于三星数据公司。
是什么让他在尚未毕业就具备如此竞争力呢?机遇?能力?命运?或许,李同学下面一番话可以向我们揭示谜团所在。
“在学校学习的过程中,我参加社会实践的机会很少,所以在经验的积累上就很欠缺,不能做到专业学习与就业有机结合,以致在面试的过程中屡屡碰壁。我开始冷静思考该如何迅速提升自身竞争力。后来我来到到蓝点世纪参加职业培训,之所以选择这家公司,比较吸引我的是他们的项目驱动式培训模式,讲练相结合的教学模式更有利于我自己知识的巩固,超强度的编程练习和项目实战演练,弥补了我在经验上的不足,经过这样一个再教育的过程,现在我的能力相当于一个拥有一年工作经验的工程师的水平,但我比他们更大的优势在于,自己在接受职业培训的过程中,也积累了很广泛的人脉资源。
毕业后蓝点世纪的老师也给了我很多无偿的技术支持。我能取得今天的成功,正因为我充分认识到第一份工作对我职业生涯的影响,也充分验证了积极进行职业规划的正确性。现在我还没有毕业,就已经被三星数据公司优先录用了,比之身边的同学,我简直太幸运了!”
相比一些游离于社会边缘的求职者,李同学的确是非常幸运的,但是这样的幸运并非偶然。在就业这个问题上,如果你从一开始就自暴自弃,那么谁也拯救不了你;相反,如果你能够做到运筹帷幄积极应对,那么连上帝都阻止不了你前进的脚步。对于迈出校园的第一份工作,大学生自身要承担起最终的责任,因为只有你自己才是找到一个好工作的最终受益者。不要说在论文设计和求职两者间存在时间上的落差,如果你足够聪明,并且愿意对自己的前途负责,我想你明白如何使两者兼容从而并行不悖。
记住,没有人会为你的职业前程买单。成功无他途,只有努力干。
参考:www.createedu.com
Java编程中异常处理的优劣之道
发贴日期:
2008-06-09 [ 3人评论过 ]
Java编程中的异常处理是一个很常见的话题了,几乎任何一门介绍性的Java课程都会提到异常处理。不过,我认为很多人其实并没有真正掌握正确处理异常情况的方法和策略,最多也就不过了解个大概,知道点概念。本文就对三种不同程度和质量的Java异常处理进行了讨论,所阐述的处理异常的方式按手法的高下分为:
好,不好和恶劣三种。
同时向你提供了一些解决这些问题的技巧。
首先解释一些java异常处理中必须搞清楚的定义和机制。Java语言规范将自Error类或RuntimeException类衍生出来的任何违例都称作“不可检查”(Unchecked)异常;其他所有异常则称作“可检查”(Checked)异常。
所谓可检查异常,是指我们应该自行处理的异常。至于处理的手段,要么加以控制(try catch),要么通告(throws)他们有可能产生。通常,应捕捉那些已知如何处理的异常,而通告那些不知如何处理的异常。
而对那些不可检查异常来说,他们要么在我们的控制之外(Error),要么是我们首先就不该允许的情况(RuntimeException). www.createedu.com qq:253490497
至于异常的指定,Java的规则非常简单:一个方法必须通告自己可能产生的所有可检查异常。编写自己的方法时,并不一定要通告出方法实际可能产生的每一个异常对象,要想理解什么时候必须要方法的throws丛句来通告异常,就必须知道对一个异常来说,他只有可能在下面四种情况下才会产生:
1.调用了可能产生异常的方法。比如BufferedReader类的readLine方法。该方法通告java.io.IOException异常
2.侦测到一个错误,并用throw语句产生异常。
3.出现一个编程错误。比如a[-1] = 0。
4.Java产生内部错误。
如果出现头两种情况之一,必须告诉打算使用自己方法的人:假如使用这个方法,可能造成一个异常的产生(即在方法头上使用throws),一个简单的记忆方法:
只要含有throw,就要通告throws。如果一个方法必须同时处理多个异常,就必须在头内指出所有异常。就像下例展示的那样,用逗号对他们进行分割:
1
2
3
4
5
6
7 class Animation
{
public Image loadImage(Strint s) throws EOFException,MalformedURLException
{
…………
}
}
然而,我们不需要通告内部java错误,也不应该通告自RuntimeException衍生出来的异常。
好的异常处理
好异常处理提供了处理程序错误的统一机制。事实上,Java语言通过向调用者提出异常警告的方式而显著地提升了软件开发中的异常处理能力。这种方式把Java语言中的“方法(method)”进行了扩展和增强,使之包括了自身的错误条件。下面就让我们看一个例子,这个例子说明了这种情况。
以下是FileInputStream构造器之一的原型:
public FileInputStream(String name) throws FileNotFoundException Java
的方法和构造器必须声明他们在被调用时可能“扔出”的异常,采用的关键字就是“throws”。这种在方法原型中出现的异常提示增加了编程的可靠性。
显而易见,这种方式是向方法的调用者提示了可能出现的异常条件,这样调用者就可以对这些异常作出适当的相应处理。以下代码示意我们是如何捕获并且处理FileNotFoundException 这一异常的:
1
2
3
4
5
6
7
8
9
10
11 try
{
FileInputStream fis = new FileInputStream(args[0]);
// other code here ...
}
catch (FileNotFoundException fnfe)
{
System.out.println("File: " + args[0] + " not found. Aborting.");
System.exit(1);
}
Java异常处理还有其他一些优秀的特性,这就是可检查异常、用户定义异常和在JDK 1.4中推出的新型Java记录API(Java Logging API)。java.lang.Exception的所有子类都属于可检查异常。可检查异常(checked exception)是扔出该异常的方法所必须提示的异常,这种异常必须被捕获或者向调用者提示。用户定义异常(User-defined exceptions)是定制的异常类,这种异常类扩展了java.lang.Exception类。优良的Java程序规定定制异常封装、报告和处理他们自己独有的情况。最新的Java记录API(logging API)则可以集中记录异常。
好,不好和恶劣三种。
同时向你提供了一些解决这些问题的技巧。
首先解释一些java异常处理中必须搞清楚的定义和机制。Java语言规范将自Error类或RuntimeException类衍生出来的任何违例都称作“不可检查”(Unchecked)异常;其他所有异常则称作“可检查”(Checked)异常。
所谓可检查异常,是指我们应该自行处理的异常。至于处理的手段,要么加以控制(try catch),要么通告(throws)他们有可能产生。通常,应捕捉那些已知如何处理的异常,而通告那些不知如何处理的异常。
而对那些不可检查异常来说,他们要么在我们的控制之外(Error),要么是我们首先就不该允许的情况(RuntimeException). www.createedu.com qq:253490497
至于异常的指定,Java的规则非常简单:一个方法必须通告自己可能产生的所有可检查异常。编写自己的方法时,并不一定要通告出方法实际可能产生的每一个异常对象,要想理解什么时候必须要方法的throws丛句来通告异常,就必须知道对一个异常来说,他只有可能在下面四种情况下才会产生:
1.调用了可能产生异常的方法。比如BufferedReader类的readLine方法。该方法通告java.io.IOException异常
2.侦测到一个错误,并用throw语句产生异常。
3.出现一个编程错误。比如a[-1] = 0。
4.Java产生内部错误。
如果出现头两种情况之一,必须告诉打算使用自己方法的人:假如使用这个方法,可能造成一个异常的产生(即在方法头上使用throws),一个简单的记忆方法:
只要含有throw,就要通告throws。如果一个方法必须同时处理多个异常,就必须在头内指出所有异常。就像下例展示的那样,用逗号对他们进行分割:
1
2
3
4
5
6
7 class Animation
{
public Image loadImage(Strint s) throws EOFException,MalformedURLException
{
…………
}
}
然而,我们不需要通告内部java错误,也不应该通告自RuntimeException衍生出来的异常。
好的异常处理
好异常处理提供了处理程序错误的统一机制。事实上,Java语言通过向调用者提出异常警告的方式而显著地提升了软件开发中的异常处理能力。这种方式把Java语言中的“方法(method)”进行了扩展和增强,使之包括了自身的错误条件。下面就让我们看一个例子,这个例子说明了这种情况。
以下是FileInputStream构造器之一的原型:
public FileInputStream(String name) throws FileNotFoundException Java
的方法和构造器必须声明他们在被调用时可能“扔出”的异常,采用的关键字就是“throws”。这种在方法原型中出现的异常提示增加了编程的可靠性。
显而易见,这种方式是向方法的调用者提示了可能出现的异常条件,这样调用者就可以对这些异常作出适当的相应处理。以下代码示意我们是如何捕获并且处理FileNotFoundException 这一异常的:
1
2
3
4
5
6
7
8
9
10
11 try
{
FileInputStream fis = new FileInputStream(args[0]);
// other code here ...
}
catch (FileNotFoundException fnfe)
{
System.out.println("File: " + args[0] + " not found. Aborting.");
System.exit(1);
}
Java异常处理还有其他一些优秀的特性,这就是可检查异常、用户定义异常和在JDK 1.4中推出的新型Java记录API(Java Logging API)。java.lang.Exception的所有子类都属于可检查异常。可检查异常(checked exception)是扔出该异常的方法所必须提示的异常,这种异常必须被捕获或者向调用者提示。用户定义异常(User-defined exceptions)是定制的异常类,这种异常类扩展了java.lang.Exception类。优良的Java程序规定定制异常封装、报告和处理他们自己独有的情况。最新的Java记录API(logging API)则可以集中记录异常。
Java编程中异常处理的优劣之道
发贴日期:
2008-06-09 [ 3人评论过 ]
Java编程中的异常处理是一个很常见的话题了,几乎任何一门介绍性的Java课程都会提到异常处理。不过,我认为很多人其实并没有真正掌握正确处理异常情况的方法和策略,最多也就不过了解个大概,知道点概念。本文就对三种不同程度和质量的Java异常处理进行了讨论,所阐述的处理异常的方式按手法的高下分为:
好,不好和恶劣三种。
同时向你提供了一些解决这些问题的技巧。
首先解释一些java异常处理中必须搞清楚的定义和机制。Java语言规范将自Error类或RuntimeException类衍生出来的任何违例都称作“不可检查”(Unchecked)异常;其他所有异常则称作“可检查”(Checked)异常。
所谓可检查异常,是指我们应该自行处理的异常。至于处理的手段,要么加以控制(try catch),要么通告(throws)他们有可能产生。通常,应捕捉那些已知如何处理的异常,而通告那些不知如何处理的异常。
而对那些不可检查异常来说,他们要么在我们的控制之外(Error),要么是我们首先就不该允许的情况(RuntimeException). www.createedu.com qq:253490497
至于异常的指定,Java的规则非常简单:一个方法必须通告自己可能产生的所有可检查异常。编写自己的方法时,并不一定要通告出方法实际可能产生的每一个异常对象,要想理解什么时候必须要方法的throws丛句来通告异常,就必须知道对一个异常来说,他只有可能在下面四种情况下才会产生:
1.调用了可能产生异常的方法。比如BufferedReader类的readLine方法。该方法通告java.io.IOException异常
2.侦测到一个错误,并用throw语句产生异常。
3.出现一个编程错误。比如a[-1] = 0。
4.Java产生内部错误。
如果出现头两种情况之一,必须告诉打算使用自己方法的人:假如使用这个方法,可能造成一个异常的产生(即在方法头上使用throws),一个简单的记忆方法:
只要含有throw,就要通告throws。如果一个方法必须同时处理多个异常,就必须在头内指出所有异常。就像下例展示的那样,用逗号对他们进行分割:
1
2
3
4
5
6
7 class Animation
{
public Image loadImage(Strint s) throws EOFException,MalformedURLException
{
…………
}
}
然而,我们不需要通告内部java错误,也不应该通告自RuntimeException衍生出来的异常。
好的异常处理
好异常处理提供了处理程序错误的统一机制。事实上,Java语言通过向调用者提出异常警告的方式而显著地提升了软件开发中的异常处理能力。这种方式把Java语言中的“方法(method)”进行了扩展和增强,使之包括了自身的错误条件。下面就让我们看一个例子,这个例子说明了这种情况。
以下是FileInputStream构造器之一的原型:
public FileInputStream(String name) throws FileNotFoundException Java
的方法和构造器必须声明他们在被调用时可能“扔出”的异常,采用的关键字就是“throws”。这种在方法原型中出现的异常提示增加了编程的可靠性。
显而易见,这种方式是向方法的调用者提示了可能出现的异常条件,这样调用者就可以对这些异常作出适当的相应处理。以下代码示意我们是如何捕获并且处理FileNotFoundException 这一异常的:
1
2
3
4
5
6
7
8
9
10
11 try
{
FileInputStream fis = new FileInputStream(args[0]);
// other code here ...
}
catch (FileNotFoundException fnfe)
{
System.out.println("File: " + args[0] + " not found. Aborting.");
System.exit(1);
}
Java异常处理还有其他一些优秀的特性,这就是可检查异常、用户定义异常和在JDK 1.4中推出的新型Java记录API(Java Logging API)。java.lang.Exception的所有子类都属于可检查异常。可检查异常(checked exception)是扔出该异常的方法所必须提示的异常,这种异常必须被捕获或者向调用者提示。用户定义异常(User-defined exceptions)是定制的异常类,这种异常类扩展了java.lang.Exception类。优良的Java程序规定定制异常封装、报告和处理他们自己独有的情况。最新的Java记录API(logging API)则可以集中记录异常。
好,不好和恶劣三种。
同时向你提供了一些解决这些问题的技巧。
首先解释一些java异常处理中必须搞清楚的定义和机制。Java语言规范将自Error类或RuntimeException类衍生出来的任何违例都称作“不可检查”(Unchecked)异常;其他所有异常则称作“可检查”(Checked)异常。
所谓可检查异常,是指我们应该自行处理的异常。至于处理的手段,要么加以控制(try catch),要么通告(throws)他们有可能产生。通常,应捕捉那些已知如何处理的异常,而通告那些不知如何处理的异常。
而对那些不可检查异常来说,他们要么在我们的控制之外(Error),要么是我们首先就不该允许的情况(RuntimeException). www.createedu.com qq:253490497
至于异常的指定,Java的规则非常简单:一个方法必须通告自己可能产生的所有可检查异常。编写自己的方法时,并不一定要通告出方法实际可能产生的每一个异常对象,要想理解什么时候必须要方法的throws丛句来通告异常,就必须知道对一个异常来说,他只有可能在下面四种情况下才会产生:
1.调用了可能产生异常的方法。比如BufferedReader类的readLine方法。该方法通告java.io.IOException异常
2.侦测到一个错误,并用throw语句产生异常。
3.出现一个编程错误。比如a[-1] = 0。
4.Java产生内部错误。
如果出现头两种情况之一,必须告诉打算使用自己方法的人:假如使用这个方法,可能造成一个异常的产生(即在方法头上使用throws),一个简单的记忆方法:
只要含有throw,就要通告throws。如果一个方法必须同时处理多个异常,就必须在头内指出所有异常。就像下例展示的那样,用逗号对他们进行分割:
1
2
3
4
5
6
7 class Animation
{
public Image loadImage(Strint s) throws EOFException,MalformedURLException
{
…………
}
}
然而,我们不需要通告内部java错误,也不应该通告自RuntimeException衍生出来的异常。
好的异常处理
好异常处理提供了处理程序错误的统一机制。事实上,Java语言通过向调用者提出异常警告的方式而显著地提升了软件开发中的异常处理能力。这种方式把Java语言中的“方法(method)”进行了扩展和增强,使之包括了自身的错误条件。下面就让我们看一个例子,这个例子说明了这种情况。
以下是FileInputStream构造器之一的原型:
public FileInputStream(String name) throws FileNotFoundException Java
的方法和构造器必须声明他们在被调用时可能“扔出”的异常,采用的关键字就是“throws”。这种在方法原型中出现的异常提示增加了编程的可靠性。
显而易见,这种方式是向方法的调用者提示了可能出现的异常条件,这样调用者就可以对这些异常作出适当的相应处理。以下代码示意我们是如何捕获并且处理FileNotFoundException 这一异常的:
1
2
3
4
5
6
7
8
9
10
11 try
{
FileInputStream fis = new FileInputStream(args[0]);
// other code here ...
}
catch (FileNotFoundException fnfe)
{
System.out.println("File: " + args[0] + " not found. Aborting.");
System.exit(1);
}
Java异常处理还有其他一些优秀的特性,这就是可检查异常、用户定义异常和在JDK 1.4中推出的新型Java记录API(Java Logging API)。java.lang.Exception的所有子类都属于可检查异常。可检查异常(checked exception)是扔出该异常的方法所必须提示的异常,这种异常必须被捕获或者向调用者提示。用户定义异常(User-defined exceptions)是定制的异常类,这种异常类扩展了java.lang.Exception类。优良的Java程序规定定制异常封装、报告和处理他们自己独有的情况。最新的Java记录API(logging API)则可以集中记录异常。
我的视频,你做主
发贴日期:
2008-06-02 [ 1人评论过 ]
我的视频,你做主
国信蓝点(保定凯瑞艾特)授权培训中心,面向所有java爱好者朋友隆重推出“我的视频,你做主”的活动。活动的具体内容如下:
活动对象:所有河北地区的大专以上学历的java爱好者。
活动目的:吸引所有喜欢java的朋友参与此活动并为学员进一步了解我中心提供机会。
活动规则:1.报名申请(详细填写报名登记表并将其发送至zhaoliangcreateedu@126.com)我们就给您提供我们的全真java视频教程(由北京总部提供)。
2.您在观看视频以后,给我们写一个详细的听课感受的案例,案例写作的要求是实话实说,可以是好的,也可以是不好的,要求对课程内容的评价,对我中心的印象以及建议等等。字数限制在500字以上。
3.收到您的案例以后,我们会给您送上u盘或者键盘作为礼品,以及我们的VIP学生卡,这张卡含100元代金卷!(要求把案例挂到自己的博客上)
4.本活动名额有限,先申请先得,每位朋友只能申请一次!
联系方式:0312-3339703 QQ:809012047 邮箱:zhaoliangcreateedu@126.com
备注:根据您的报名登记表以及案例的情况决定您的礼品是u盘还是键盘,所以一定要认真填写真实信息。
详情查询可登陆网站:www.createedu.com
报名登记表
姓 名 性 别
年 龄 籍 贯
学 历 专 业
是否在职 电 话
兴趣爱好 Q Q
学 校
E - Mail
博客网址
国信蓝点(保定凯瑞艾特)授权培训中心,面向所有java爱好者朋友隆重推出“我的视频,你做主”的活动。活动的具体内容如下:
活动对象:所有河北地区的大专以上学历的java爱好者。
活动目的:吸引所有喜欢java的朋友参与此活动并为学员进一步了解我中心提供机会。
活动规则:1.报名申请(详细填写报名登记表并将其发送至zhaoliangcreateedu@126.com)我们就给您提供我们的全真java视频教程(由北京总部提供)。
2.您在观看视频以后,给我们写一个详细的听课感受的案例,案例写作的要求是实话实说,可以是好的,也可以是不好的,要求对课程内容的评价,对我中心的印象以及建议等等。字数限制在500字以上。
3.收到您的案例以后,我们会给您送上u盘或者键盘作为礼品,以及我们的VIP学生卡,这张卡含100元代金卷!(要求把案例挂到自己的博客上)
4.本活动名额有限,先申请先得,每位朋友只能申请一次!
联系方式:0312-3339703 QQ:809012047 邮箱:zhaoliangcreateedu@126.com
备注:根据您的报名登记表以及案例的情况决定您的礼品是u盘还是键盘,所以一定要认真填写真实信息。
详情查询可登陆网站:www.createedu.com
报名登记表
姓 名 性 别
年 龄 籍 贯
学 历 专 业
是否在职 电 话
兴趣爱好 Q Q
学 校
E - Mail
博客网址
我的视频,你做主
发贴日期:
2008-06-02 [ 1人评论过 ]
我的视频,你做主
国信蓝点(保定凯瑞艾特)授权培训中心,面向所有java爱好者朋友隆重推出“我的视频,你做主”的活动。活动的具体内容如下:
活动对象:所有河北地区的大专以上学历的java爱好者。
活动目的:吸引所有喜欢java的朋友参与此活动并为学员进一步了解我中心提供机会。
活动规则:1.报名申请(详细填写报名登记表并将其发送至zhaoliangcreateedu@126.com)我们就给您提供我们的全真java视频教程(由北京总部提供)。
2.您在观看视频以后,给我们写一个详细的听课感受的案例,案例写作的要求是实话实说,可以是好的,也可以是不好的,要求对课程内容的评价,对我中心的印象以及建议等等。字数限制在500字以上。
3.收到您的案例以后,我们会给您送上u盘或者键盘作为礼品,以及我们的VIP学生卡,这张卡含100元代金卷!(要求把案例挂到自己的博客上)
4.本活动名额有限,先申请先得,每位朋友只能申请一次!
联系方式:0312-3339703 QQ:809012047 邮箱:zhaoliangcreateedu@126.com
备注:根据您的报名登记表以及案例的情况决定您的礼品是u盘还是键盘,所以一定要认真填写真实信息。
详情查询可登陆网站:www.createedu.com
报名登记表
姓 名 性 别
年 龄 籍 贯
学 历 专 业
是否在职 电 话
兴趣爱好 Q Q
学 校
E - Mail
博客网址
国信蓝点(保定凯瑞艾特)授权培训中心,面向所有java爱好者朋友隆重推出“我的视频,你做主”的活动。活动的具体内容如下:
活动对象:所有河北地区的大专以上学历的java爱好者。
活动目的:吸引所有喜欢java的朋友参与此活动并为学员进一步了解我中心提供机会。
活动规则:1.报名申请(详细填写报名登记表并将其发送至zhaoliangcreateedu@126.com)我们就给您提供我们的全真java视频教程(由北京总部提供)。
2.您在观看视频以后,给我们写一个详细的听课感受的案例,案例写作的要求是实话实说,可以是好的,也可以是不好的,要求对课程内容的评价,对我中心的印象以及建议等等。字数限制在500字以上。
3.收到您的案例以后,我们会给您送上u盘或者键盘作为礼品,以及我们的VIP学生卡,这张卡含100元代金卷!(要求把案例挂到自己的博客上)
4.本活动名额有限,先申请先得,每位朋友只能申请一次!
联系方式:0312-3339703 QQ:809012047 邮箱:zhaoliangcreateedu@126.com
备注:根据您的报名登记表以及案例的情况决定您的礼品是u盘还是键盘,所以一定要认真填写真实信息。
详情查询可登陆网站:www.createedu.com
报名登记表
姓 名 性 别
年 龄 籍 贯
学 历 专 业
是否在职 电 话
兴趣爱好 Q Q
学 校
E - Mail
博客网址
我的视频,你做主
发贴日期:
2008-06-02 [ 0人评论过 ]
我的视频,你做主
国信蓝点(保定凯瑞艾特)授权培训中心,面向所有java爱好者朋友隆重推出“我的视频,你做主”的活动。活动的具体内容如下:
活动对象:所有河北地区的大专以上学历的java爱好者。
活动目的:吸引所有喜欢java的朋友参与此活动并为学员进一步了解我中心提供机会。
活动规则:1.报名申请(详细填写报名登记表并将其发送至zhaoliangcreateedu@126.com)我们就给您提供我们的全真java视频教程(由北京总部提供)。
2.您在观看视频以后,给我们写一个详细的听课感受的案例,案例写作的要求是实话实说,可以是好的,也可以是不好的,要求对课程内容的评价,对我中心的印象以及建议等等。字数限制在500字以上。
3.收到您的案例以后,我们会给您送上u盘或者键盘作为礼品,以及我们的VIP学生卡,这张卡含100元代金卷!(要求把案例挂到自己的博客上)
4.本活动名额有限,先申请先得,每位朋友只能申请一次!
联系方式:0312-3339703 QQ:809012047 邮箱:zhaoliangcreateedu@126.com
备注:根据您的报名登记表以及案例的情况决定您的礼品是u盘还是键盘,所以一定要认真填写真实信息。
详情查询可登陆网站:www.createedu.com
报名登记表
姓 名 性 别
年 龄 籍 贯
学 历 专 业
是否在职 电 话
兴趣爱好 Q Q
学 校
E - Mail
博客网址
国信蓝点(保定凯瑞艾特)授权培训中心,面向所有java爱好者朋友隆重推出“我的视频,你做主”的活动。活动的具体内容如下:
活动对象:所有河北地区的大专以上学历的java爱好者。
活动目的:吸引所有喜欢java的朋友参与此活动并为学员进一步了解我中心提供机会。
活动规则:1.报名申请(详细填写报名登记表并将其发送至zhaoliangcreateedu@126.com)我们就给您提供我们的全真java视频教程(由北京总部提供)。
2.您在观看视频以后,给我们写一个详细的听课感受的案例,案例写作的要求是实话实说,可以是好的,也可以是不好的,要求对课程内容的评价,对我中心的印象以及建议等等。字数限制在500字以上。
3.收到您的案例以后,我们会给您送上u盘或者键盘作为礼品,以及我们的VIP学生卡,这张卡含100元代金卷!(要求把案例挂到自己的博客上)
4.本活动名额有限,先申请先得,每位朋友只能申请一次!
联系方式:0312-3339703 QQ:809012047 邮箱:zhaoliangcreateedu@126.com
备注:根据您的报名登记表以及案例的情况决定您的礼品是u盘还是键盘,所以一定要认真填写真实信息。
详情查询可登陆网站:www.createedu.com
报名登记表
姓 名 性 别
年 龄 籍 贯
学 历 专 业
是否在职 电 话
兴趣爱好 Q Q
学 校
E - Mail
博客网址
动态调用动态语言之Java脚本API
发贴日期:
2008-05-28 [ 1人评论过 ]
我们不需要将动态语言编译为 Java字节码就可以在 Java 应用程序中使用它们。使用 Java Platform, Standard Edition 6 (Java SE)中添加的脚本包(并且向后兼容 Java SE 5),Java 代码可以在运行时以一种简单的、统一的方式调用多种动态语言。本系列文章共分两个部分,第 1 部分将介绍 Java 脚本 API 的各种特性。文章将使用一个简单的 Hello World 应用程序展示 Java 代码如何执行脚本代码以及脚本如何反过来执行 Java 代码。第 2 部分将深入研究 Java 脚本 API 的强大功能。
Java 开发人员清楚 Java 并不是在任何情况下都是最佳的语言。今年,1.0 版本的 JRuby 和 Groovy 的发行引领了一场热潮,促使人们纷纷在自己的 Java 应用程序中添加动态语言。Groovy、JRuby、Rhino、Jython 和一些其他的开源项目使在所谓的脚本语言中编写代码并在 JVM 中运行成为了可能(请参阅 参考资料)。通常,在 Java 代码中集成这些语言需要对各种解释器所特有的 API 和特性有所了解。
Java SE 6 中添加的 javax.script 包使集成动态语言更加容易。通过使用一小组接口和具体类,这个包使我们能够简单地调用多种脚本语言。但是,Java 脚本 API 的功能不只是在应用程序中编写脚本;这个脚本包使我们能够在运行时读取和调用外部脚本,这意味着我们可以动态地修改这些脚本从而更改运行应用程序的行为。
Java 脚本 APIwww.createedu.com qq:253490497
脚本与动态的对比
术语脚本 通常表示在解释器 shell 中运行的语言,它们往往没有单独的编译步骤。术语动态 通常表示等到运行时判断变量类型或对象行为的语言,往往具有闭包和连续特性。一些通用的编程语言同时具有这两种特性。此处首选脚本语言 是因为本文的着重点是 Java 脚本 API,而不是因为提及的语言缺少动态特性。
2006 年 10 月,Java 语言添加了脚本包,从而提供了一种统一的方式将脚本语言集成到 Java 应用程序中去。对于语言开发人员,他们可以使用这个包编写粘连代码(glue code),从而使人们能够在 Java 应用程序中调用他们的语言。对于 Java 开发人员,脚本包提供了一组类和接口,允许使用一个公共 API 调用多种语言编写的脚本。因此,脚本包类似于不同语言(比如说不同的数据库)中的 Java Database Connectivity (JDBC) 包,可以使用一致的接口集成到 Java 平台中去。
以前,在 Java 代码中,动态调用脚本语言涉及到使用各种语言发行版所提供的独特类或使用 Apache 的 Jakarta Bean Scripting Framework (BSF)。BSF 在一个 API 内部统一了一组脚本语言(请参阅 参考资料)。使用 Java SE 6 脚本 API,二十余种脚本语言(AppleScript、Groovy、JavaScript、Jelly、PHP、Python、Ruby 和 Velocity)都可以集成到 Java 代码中,这在很大程序上依赖的是 BSF。
脚本 API 在 Java 应用程序和外部脚本之间提供了双向可见性。Java 代码不仅可以调用外部脚本,而且还允许那些脚本访问选定的 Java 对象。比如说,外部 Ruby 脚本可以对 Java 对象调用方法,并访问对象的属性,从而使脚本能够将行为添加到运行中的应用程序中(如果在开发时无法预计应用程序的行为)。
调用外部脚本可用于运行时应用程序增强、配置、监控或一些其他的运行时操作,比如说在不停止应用程序的情况下修改业务规则。脚本包可能的作用包括:
•在比 Java 语言更简单的语言中编写业务规则,而不用借助成熟的规则引擎。
•创建插件架构,使用户能够动态地定制应用程序。
•将已有脚本集成到 Java 应用程序中,比如说处理或转换文件文章的脚本。
•使用成熟的编程语言(而不是属性文件)从外部配置应用程序的运行时行为。
•在 Java 应用程序中添加一门特定于域的语言(domain-specific language)。
•在开发 Java 应用程序原型的过程中使用脚本语言。
•在脚本语言中编写应用程序测试代码。
你好,脚本世界
HelloScriptingWorld 类(本文中的相关代码均可从 下载部分 获得)演示了 Java 脚本包的一些关键特性。它使用硬编码的 JavaScript 作为示例脚本语言。此类的 main() 方法(如清单 1 所示)将创建一个 JavaScript 脚本引擎,然后分别调用五个方法(在下文的清单中有显示)用于突出显示脚本包的特性。
清单 1. HelloScriptingWorld main 方法
public static void main(String[] args) throws ScriptException, NoSuchMethodException {
ScriptEngineManager scriptEngineMgr = new ScriptEngineManager();
ScriptEngine jsEngine = scriptEngineMgr.getEngineByName("JavaScript");
if (jsEngine == null) {
System.err.println("No script engine found for JavaScript");
System.exit(1);
}
System.out.println("Calling invokeHelloScript...");
invokeHelloScript(jsEngine);
System.out.println("\nCalling defineScriptFunction...");
defineScriptFunction(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromEngine...");
invokeScriptFunctionFromEngine(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromJava...");
invokeScriptFunctionFromJava(jsEngine);
System.out.println("\nCalling invokeJavaFromScriptFunction...");
invokeJavaFromScriptFunction(jsEngine);
}
main() 方法的主要功能是获取一个 javax.script.ScriptEngine 实例(清单 1 中的前两行代码)。脚本引擎可以在特定的语言中加载并执行脚本。它是 Java 脚本包中使用最为频繁、作用最为重要的类。我们从 javax.script.ScriptEngineManager 获取一个脚本引擎(第一行代码)。通常,程序只需要获取一个脚本引擎实例,除非使用了很多种脚本语言。
ScriptEngineManager 类
ScriptEngineManager 可能是脚本包中惟一一个经常使用的具体类;其他大多数都是接口。它或许是脚本包中惟一的一个要直接或间接地(通过 Spring Framework 之类的依赖性注入机制)实例化的类。ScriptEngineManager 可以使用以下三种方式返回脚本引擎:
•通过引擎或语言的名称,比如说 清单 1 请求 JavaScript 引擎。
•通过该语言脚本共同使用的文件扩展名,比如说 Ruby 脚本的 .rb。
•通过脚本引擎声明的、知道如何处理的 MIME 类型。
本文示例为什么要使用 JavaScript?
本文中的 Hello World 示例使用了部分 JavaScript 脚本,这是因为 JavaScript 代码易于理解,不过主要还是因为 Sun Microsystems 和 BEA Systems 所提供的 Java 6 运行时环境附带有基于 Mozilla Rhino 开源 JavaScript 实现的 JavaScript 解释器。使用 JavaScript,我们无需在类路径中添加脚本语言 JAR 文件。
ScriptEngineManager 间接查找和创建脚本引擎。也就是说,当实例化脚本引擎管理程序时,ScriptEngineManager 会使用 Java 6 中新增的服务发现机制在类路径中查找所有注册的 javax.script.ScriptEngineFactory 实现。这些工厂类封装在 Java 脚本 API 实现中;也许您永远都不需要直接处理这些工厂类。
ScriptEngineManager 找到所有的脚本引擎工厂类之后,它会查询各个类并判断是否能够创建所请求类型的脚本引擎 —— 清单 1 中为 JavaScript 引擎。如果工厂说可以创建所需语言的脚本引擎,那么管理程序将要求工厂创建一个引擎并将其返回给调用者。如果没有找到所请求语言的工厂,那么管理程序将返回 null,清单 1 中的代码将检查 null 返回值并做出预防。
Java 开发人员清楚 Java 并不是在任何情况下都是最佳的语言。今年,1.0 版本的 JRuby 和 Groovy 的发行引领了一场热潮,促使人们纷纷在自己的 Java 应用程序中添加动态语言。Groovy、JRuby、Rhino、Jython 和一些其他的开源项目使在所谓的脚本语言中编写代码并在 JVM 中运行成为了可能(请参阅 参考资料)。通常,在 Java 代码中集成这些语言需要对各种解释器所特有的 API 和特性有所了解。
Java SE 6 中添加的 javax.script 包使集成动态语言更加容易。通过使用一小组接口和具体类,这个包使我们能够简单地调用多种脚本语言。但是,Java 脚本 API 的功能不只是在应用程序中编写脚本;这个脚本包使我们能够在运行时读取和调用外部脚本,这意味着我们可以动态地修改这些脚本从而更改运行应用程序的行为。
Java 脚本 APIwww.createedu.com qq:253490497
脚本与动态的对比
术语脚本 通常表示在解释器 shell 中运行的语言,它们往往没有单独的编译步骤。术语动态 通常表示等到运行时判断变量类型或对象行为的语言,往往具有闭包和连续特性。一些通用的编程语言同时具有这两种特性。此处首选脚本语言 是因为本文的着重点是 Java 脚本 API,而不是因为提及的语言缺少动态特性。
2006 年 10 月,Java 语言添加了脚本包,从而提供了一种统一的方式将脚本语言集成到 Java 应用程序中去。对于语言开发人员,他们可以使用这个包编写粘连代码(glue code),从而使人们能够在 Java 应用程序中调用他们的语言。对于 Java 开发人员,脚本包提供了一组类和接口,允许使用一个公共 API 调用多种语言编写的脚本。因此,脚本包类似于不同语言(比如说不同的数据库)中的 Java Database Connectivity (JDBC) 包,可以使用一致的接口集成到 Java 平台中去。
以前,在 Java 代码中,动态调用脚本语言涉及到使用各种语言发行版所提供的独特类或使用 Apache 的 Jakarta Bean Scripting Framework (BSF)。BSF 在一个 API 内部统一了一组脚本语言(请参阅 参考资料)。使用 Java SE 6 脚本 API,二十余种脚本语言(AppleScript、Groovy、JavaScript、Jelly、PHP、Python、Ruby 和 Velocity)都可以集成到 Java 代码中,这在很大程序上依赖的是 BSF。
脚本 API 在 Java 应用程序和外部脚本之间提供了双向可见性。Java 代码不仅可以调用外部脚本,而且还允许那些脚本访问选定的 Java 对象。比如说,外部 Ruby 脚本可以对 Java 对象调用方法,并访问对象的属性,从而使脚本能够将行为添加到运行中的应用程序中(如果在开发时无法预计应用程序的行为)。
调用外部脚本可用于运行时应用程序增强、配置、监控或一些其他的运行时操作,比如说在不停止应用程序的情况下修改业务规则。脚本包可能的作用包括:
•在比 Java 语言更简单的语言中编写业务规则,而不用借助成熟的规则引擎。
•创建插件架构,使用户能够动态地定制应用程序。
•将已有脚本集成到 Java 应用程序中,比如说处理或转换文件文章的脚本。
•使用成熟的编程语言(而不是属性文件)从外部配置应用程序的运行时行为。
•在 Java 应用程序中添加一门特定于域的语言(domain-specific language)。
•在开发 Java 应用程序原型的过程中使用脚本语言。
•在脚本语言中编写应用程序测试代码。
你好,脚本世界
HelloScriptingWorld 类(本文中的相关代码均可从 下载部分 获得)演示了 Java 脚本包的一些关键特性。它使用硬编码的 JavaScript 作为示例脚本语言。此类的 main() 方法(如清单 1 所示)将创建一个 JavaScript 脚本引擎,然后分别调用五个方法(在下文的清单中有显示)用于突出显示脚本包的特性。
清单 1. HelloScriptingWorld main 方法
public static void main(String[] args) throws ScriptException, NoSuchMethodException {
ScriptEngineManager scriptEngineMgr = new ScriptEngineManager();
ScriptEngine jsEngine = scriptEngineMgr.getEngineByName("JavaScript");
if (jsEngine == null) {
System.err.println("No script engine found for JavaScript");
System.exit(1);
}
System.out.println("Calling invokeHelloScript...");
invokeHelloScript(jsEngine);
System.out.println("\nCalling defineScriptFunction...");
defineScriptFunction(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromEngine...");
invokeScriptFunctionFromEngine(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromJava...");
invokeScriptFunctionFromJava(jsEngine);
System.out.println("\nCalling invokeJavaFromScriptFunction...");
invokeJavaFromScriptFunction(jsEngine);
}
main() 方法的主要功能是获取一个 javax.script.ScriptEngine 实例(清单 1 中的前两行代码)。脚本引擎可以在特定的语言中加载并执行脚本。它是 Java 脚本包中使用最为频繁、作用最为重要的类。我们从 javax.script.ScriptEngineManager 获取一个脚本引擎(第一行代码)。通常,程序只需要获取一个脚本引擎实例,除非使用了很多种脚本语言。
ScriptEngineManager 类
ScriptEngineManager 可能是脚本包中惟一一个经常使用的具体类;其他大多数都是接口。它或许是脚本包中惟一的一个要直接或间接地(通过 Spring Framework 之类的依赖性注入机制)实例化的类。ScriptEngineManager 可以使用以下三种方式返回脚本引擎:
•通过引擎或语言的名称,比如说 清单 1 请求 JavaScript 引擎。
•通过该语言脚本共同使用的文件扩展名,比如说 Ruby 脚本的 .rb。
•通过脚本引擎声明的、知道如何处理的 MIME 类型。
本文示例为什么要使用 JavaScript?
本文中的 Hello World 示例使用了部分 JavaScript 脚本,这是因为 JavaScript 代码易于理解,不过主要还是因为 Sun Microsystems 和 BEA Systems 所提供的 Java 6 运行时环境附带有基于 Mozilla Rhino 开源 JavaScript 实现的 JavaScript 解释器。使用 JavaScript,我们无需在类路径中添加脚本语言 JAR 文件。
ScriptEngineManager 间接查找和创建脚本引擎。也就是说,当实例化脚本引擎管理程序时,ScriptEngineManager 会使用 Java 6 中新增的服务发现机制在类路径中查找所有注册的 javax.script.ScriptEngineFactory 实现。这些工厂类封装在 Java 脚本 API 实现中;也许您永远都不需要直接处理这些工厂类。
ScriptEngineManager 找到所有的脚本引擎工厂类之后,它会查询各个类并判断是否能够创建所请求类型的脚本引擎 —— 清单 1 中为 JavaScript 引擎。如果工厂说可以创建所需语言的脚本引擎,那么管理程序将要求工厂创建一个引擎并将其返回给调用者。如果没有找到所请求语言的工厂,那么管理程序将返回 null,清单 1 中的代码将检查 null 返回值并做出预防。
动态调用动态语言之Java脚本API
发贴日期:
2008-05-28 [ 0人评论过 ]
我们不需要将动态语言编译为 Java字节码就可以在 Java 应用程序中使用它们。使用 Java Platform, Standard Edition 6 (Java SE)中添加的脚本包(并且向后兼容 Java SE 5),Java 代码可以在运行时以一种简单的、统一的方式调用多种动态语言。本系列文章共分两个部分,第 1 部分将介绍 Java 脚本 API 的各种特性。文章将使用一个简单的 Hello World 应用程序展示 Java 代码如何执行脚本代码以及脚本如何反过来执行 Java 代码。第 2 部分将深入研究 Java 脚本 API 的强大功能。
Java 开发人员清楚 Java 并不是在任何情况下都是最佳的语言。今年,1.0 版本的 JRuby 和 Groovy 的发行引领了一场热潮,促使人们纷纷在自己的 Java 应用程序中添加动态语言。Groovy、JRuby、Rhino、Jython 和一些其他的开源项目使在所谓的脚本语言中编写代码并在 JVM 中运行成为了可能(请参阅 参考资料)。通常,在 Java 代码中集成这些语言需要对各种解释器所特有的 API 和特性有所了解。
Java SE 6 中添加的 javax.script 包使集成动态语言更加容易。通过使用一小组接口和具体类,这个包使我们能够简单地调用多种脚本语言。但是,Java 脚本 API 的功能不只是在应用程序中编写脚本;这个脚本包使我们能够在运行时读取和调用外部脚本,这意味着我们可以动态地修改这些脚本从而更改运行应用程序的行为。
Java 脚本 APIwww.createedu.com qq:253490497
脚本与动态的对比
术语脚本 通常表示在解释器 shell 中运行的语言,它们往往没有单独的编译步骤。术语动态 通常表示等到运行时判断变量类型或对象行为的语言,往往具有闭包和连续特性。一些通用的编程语言同时具有这两种特性。此处首选脚本语言 是因为本文的着重点是 Java 脚本 API,而不是因为提及的语言缺少动态特性。
2006 年 10 月,Java 语言添加了脚本包,从而提供了一种统一的方式将脚本语言集成到 Java 应用程序中去。对于语言开发人员,他们可以使用这个包编写粘连代码(glue code),从而使人们能够在 Java 应用程序中调用他们的语言。对于 Java 开发人员,脚本包提供了一组类和接口,允许使用一个公共 API 调用多种语言编写的脚本。因此,脚本包类似于不同语言(比如说不同的数据库)中的 Java Database Connectivity (JDBC) 包,可以使用一致的接口集成到 Java 平台中去。
以前,在 Java 代码中,动态调用脚本语言涉及到使用各种语言发行版所提供的独特类或使用 Apache 的 Jakarta Bean Scripting Framework (BSF)。BSF 在一个 API 内部统一了一组脚本语言(请参阅 参考资料)。使用 Java SE 6 脚本 API,二十余种脚本语言(AppleScript、Groovy、JavaScript、Jelly、PHP、Python、Ruby 和 Velocity)都可以集成到 Java 代码中,这在很大程序上依赖的是 BSF。
脚本 API 在 Java 应用程序和外部脚本之间提供了双向可见性。Java 代码不仅可以调用外部脚本,而且还允许那些脚本访问选定的 Java 对象。比如说,外部 Ruby 脚本可以对 Java 对象调用方法,并访问对象的属性,从而使脚本能够将行为添加到运行中的应用程序中(如果在开发时无法预计应用程序的行为)。
调用外部脚本可用于运行时应用程序增强、配置、监控或一些其他的运行时操作,比如说在不停止应用程序的情况下修改业务规则。脚本包可能的作用包括:
•在比 Java 语言更简单的语言中编写业务规则,而不用借助成熟的规则引擎。
•创建插件架构,使用户能够动态地定制应用程序。
•将已有脚本集成到 Java 应用程序中,比如说处理或转换文件文章的脚本。
•使用成熟的编程语言(而不是属性文件)从外部配置应用程序的运行时行为。
•在 Java 应用程序中添加一门特定于域的语言(domain-specific language)。
•在开发 Java 应用程序原型的过程中使用脚本语言。
•在脚本语言中编写应用程序测试代码。
你好,脚本世界
HelloScriptingWorld 类(本文中的相关代码均可从 下载部分 获得)演示了 Java 脚本包的一些关键特性。它使用硬编码的 JavaScript 作为示例脚本语言。此类的 main() 方法(如清单 1 所示)将创建一个 JavaScript 脚本引擎,然后分别调用五个方法(在下文的清单中有显示)用于突出显示脚本包的特性。
清单 1. HelloScriptingWorld main 方法
public static void main(String[] args) throws ScriptException, NoSuchMethodException {
ScriptEngineManager scriptEngineMgr = new ScriptEngineManager();
ScriptEngine jsEngine = scriptEngineMgr.getEngineByName("JavaScript");
if (jsEngine == null) {
System.err.println("No script engine found for JavaScript");
System.exit(1);
}
System.out.println("Calling invokeHelloScript...");
invokeHelloScript(jsEngine);
System.out.println("\nCalling defineScriptFunction...");
defineScriptFunction(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromEngine...");
invokeScriptFunctionFromEngine(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromJava...");
invokeScriptFunctionFromJava(jsEngine);
System.out.println("\nCalling invokeJavaFromScriptFunction...");
invokeJavaFromScriptFunction(jsEngine);
}
main() 方法的主要功能是获取一个 javax.script.ScriptEngine 实例(清单 1 中的前两行代码)。脚本引擎可以在特定的语言中加载并执行脚本。它是 Java 脚本包中使用最为频繁、作用最为重要的类。我们从 javax.script.ScriptEngineManager 获取一个脚本引擎(第一行代码)。通常,程序只需要获取一个脚本引擎实例,除非使用了很多种脚本语言。
ScriptEngineManager 类
ScriptEngineManager 可能是脚本包中惟一一个经常使用的具体类;其他大多数都是接口。它或许是脚本包中惟一的一个要直接或间接地(通过 Spring Framework 之类的依赖性注入机制)实例化的类。ScriptEngineManager 可以使用以下三种方式返回脚本引擎:
•通过引擎或语言的名称,比如说 清单 1 请求 JavaScript 引擎。
•通过该语言脚本共同使用的文件扩展名,比如说 Ruby 脚本的 .rb。
•通过脚本引擎声明的、知道如何处理的 MIME 类型。
本文示例为什么要使用 JavaScript?
本文中的 Hello World 示例使用了部分 JavaScript 脚本,这是因为 JavaScript 代码易于理解,不过主要还是因为 Sun Microsystems 和 BEA Systems 所提供的 Java 6 运行时环境附带有基于 Mozilla Rhino 开源 JavaScript 实现的 JavaScript 解释器。使用 JavaScript,我们无需在类路径中添加脚本语言 JAR 文件。
ScriptEngineManager 间接查找和创建脚本引擎。也就是说,当实例化脚本引擎管理程序时,ScriptEngineManager 会使用 Java 6 中新增的服务发现机制在类路径中查找所有注册的 javax.script.ScriptEngineFactory 实现。这些工厂类封装在 Java 脚本 API 实现中;也许您永远都不需要直接处理这些工厂类。
ScriptEngineManager 找到所有的脚本引擎工厂类之后,它会查询各个类并判断是否能够创建所请求类型的脚本引擎 —— 清单 1 中为 JavaScript 引擎。如果工厂说可以创建所需语言的脚本引擎,那么管理程序将要求工厂创建一个引擎并将其返回给调用者。如果没有找到所请求语言的工厂,那么管理程序将返回 null,清单 1 中的代码将检查 null 返回值并做出预防。









Java 开发人员清楚 Java 并不是在任何情况下都是最佳的语言。今年,1.0 版本的 JRuby 和 Groovy 的发行引领了一场热潮,促使人们纷纷在自己的 Java 应用程序中添加动态语言。Groovy、JRuby、Rhino、Jython 和一些其他的开源项目使在所谓的脚本语言中编写代码并在 JVM 中运行成为了可能(请参阅 参考资料)。通常,在 Java 代码中集成这些语言需要对各种解释器所特有的 API 和特性有所了解。
Java SE 6 中添加的 javax.script 包使集成动态语言更加容易。通过使用一小组接口和具体类,这个包使我们能够简单地调用多种脚本语言。但是,Java 脚本 API 的功能不只是在应用程序中编写脚本;这个脚本包使我们能够在运行时读取和调用外部脚本,这意味着我们可以动态地修改这些脚本从而更改运行应用程序的行为。
Java 脚本 APIwww.createedu.com qq:253490497
脚本与动态的对比
术语脚本 通常表示在解释器 shell 中运行的语言,它们往往没有单独的编译步骤。术语动态 通常表示等到运行时判断变量类型或对象行为的语言,往往具有闭包和连续特性。一些通用的编程语言同时具有这两种特性。此处首选脚本语言 是因为本文的着重点是 Java 脚本 API,而不是因为提及的语言缺少动态特性。
2006 年 10 月,Java 语言添加了脚本包,从而提供了一种统一的方式将脚本语言集成到 Java 应用程序中去。对于语言开发人员,他们可以使用这个包编写粘连代码(glue code),从而使人们能够在 Java 应用程序中调用他们的语言。对于 Java 开发人员,脚本包提供了一组类和接口,允许使用一个公共 API 调用多种语言编写的脚本。因此,脚本包类似于不同语言(比如说不同的数据库)中的 Java Database Connectivity (JDBC) 包,可以使用一致的接口集成到 Java 平台中去。
以前,在 Java 代码中,动态调用脚本语言涉及到使用各种语言发行版所提供的独特类或使用 Apache 的 Jakarta Bean Scripting Framework (BSF)。BSF 在一个 API 内部统一了一组脚本语言(请参阅 参考资料)。使用 Java SE 6 脚本 API,二十余种脚本语言(AppleScript、Groovy、JavaScript、Jelly、PHP、Python、Ruby 和 Velocity)都可以集成到 Java 代码中,这在很大程序上依赖的是 BSF。
脚本 API 在 Java 应用程序和外部脚本之间提供了双向可见性。Java 代码不仅可以调用外部脚本,而且还允许那些脚本访问选定的 Java 对象。比如说,外部 Ruby 脚本可以对 Java 对象调用方法,并访问对象的属性,从而使脚本能够将行为添加到运行中的应用程序中(如果在开发时无法预计应用程序的行为)。
调用外部脚本可用于运行时应用程序增强、配置、监控或一些其他的运行时操作,比如说在不停止应用程序的情况下修改业务规则。脚本包可能的作用包括:
•在比 Java 语言更简单的语言中编写业务规则,而不用借助成熟的规则引擎。
•创建插件架构,使用户能够动态地定制应用程序。
•将已有脚本集成到 Java 应用程序中,比如说处理或转换文件文章的脚本。
•使用成熟的编程语言(而不是属性文件)从外部配置应用程序的运行时行为。
•在 Java 应用程序中添加一门特定于域的语言(domain-specific language)。
•在开发 Java 应用程序原型的过程中使用脚本语言。
•在脚本语言中编写应用程序测试代码。
你好,脚本世界
HelloScriptingWorld 类(本文中的相关代码均可从 下载部分 获得)演示了 Java 脚本包的一些关键特性。它使用硬编码的 JavaScript 作为示例脚本语言。此类的 main() 方法(如清单 1 所示)将创建一个 JavaScript 脚本引擎,然后分别调用五个方法(在下文的清单中有显示)用于突出显示脚本包的特性。
清单 1. HelloScriptingWorld main 方法
public static void main(String[] args) throws ScriptException, NoSuchMethodException {
ScriptEngineManager scriptEngineMgr = new ScriptEngineManager();
ScriptEngine jsEngine = scriptEngineMgr.getEngineByName("JavaScript");
if (jsEngine == null) {
System.err.println("No script engine found for JavaScript");
System.exit(1);
}
System.out.println("Calling invokeHelloScript...");
invokeHelloScript(jsEngine);
System.out.println("\nCalling defineScriptFunction...");
defineScriptFunction(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromEngine...");
invokeScriptFunctionFromEngine(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromJava...");
invokeScriptFunctionFromJava(jsEngine);
System.out.println("\nCalling invokeJavaFromScriptFunction...");
invokeJavaFromScriptFunction(jsEngine);
}
main() 方法的主要功能是获取一个 javax.script.ScriptEngine 实例(清单 1 中的前两行代码)。脚本引擎可以在特定的语言中加载并执行脚本。它是 Java 脚本包中使用最为频繁、作用最为重要的类。我们从 javax.script.ScriptEngineManager 获取一个脚本引擎(第一行代码)。通常,程序只需要获取一个脚本引擎实例,除非使用了很多种脚本语言。
ScriptEngineManager 类
ScriptEngineManager 可能是脚本包中惟一一个经常使用的具体类;其他大多数都是接口。它或许是脚本包中惟一的一个要直接或间接地(通过 Spring Framework 之类的依赖性注入机制)实例化的类。ScriptEngineManager 可以使用以下三种方式返回脚本引擎:
•通过引擎或语言的名称,比如说 清单 1 请求 JavaScript 引擎。
•通过该语言脚本共同使用的文件扩展名,比如说 Ruby 脚本的 .rb。
•通过脚本引擎声明的、知道如何处理的 MIME 类型。
本文示例为什么要使用 JavaScript?
本文中的 Hello World 示例使用了部分 JavaScript 脚本,这是因为 JavaScript 代码易于理解,不过主要还是因为 Sun Microsystems 和 BEA Systems 所提供的 Java 6 运行时环境附带有基于 Mozilla Rhino 开源 JavaScript 实现的 JavaScript 解释器。使用 JavaScript,我们无需在类路径中添加脚本语言 JAR 文件。
ScriptEngineManager 间接查找和创建脚本引擎。也就是说,当实例化脚本引擎管理程序时,ScriptEngineManager 会使用 Java 6 中新增的服务发现机制在类路径中查找所有注册的 javax.script.ScriptEngineFactory 实现。这些工厂类封装在 Java 脚本 API 实现中;也许您永远都不需要直接处理这些工厂类。
ScriptEngineManager 找到所有的脚本引擎工厂类之后,它会查询各个类并判断是否能够创建所请求类型的脚本引擎 —— 清单 1 中为 JavaScript 引擎。如果工厂说可以创建所需语言的脚本引擎,那么管理程序将要求工厂创建一个引擎并将其返回给调用者。如果没有找到所请求语言的工厂,那么管理程序将返回 null,清单 1 中的代码将检查 null 返回值并做出预防。
动态调用动态语言之Java脚本API
发贴日期:
2008-05-28 [ 0人评论过 ]
我们不需要将动态语言编译为 Java字节码就可以在 Java 应用程序中使用它们。使用 Java Platform, Standard Edition 6 (Java SE)中添加的脚本包(并且向后兼容 Java SE 5),Java 代码可以在运行时以一种简单的、统一的方式调用多种动态语言。本系列文章共分两个部分,第 1 部分将介绍 Java 脚本 API 的各种特性。文章将使用一个简单的 Hello World 应用程序展示 Java 代码如何执行脚本代码以及脚本如何反过来执行 Java 代码。第 2 部分将深入研究 Java 脚本 API 的强大功能。
Java 开发人员清楚 Java 并不是在任何情况下都是最佳的语言。今年,1.0 版本的 JRuby 和 Groovy 的发行引领了一场热潮,促使人们纷纷在自己的 Java 应用程序中添加动态语言。Groovy、JRuby、Rhino、Jython 和一些其他的开源项目使在所谓的脚本语言中编写代码并在 JVM 中运行成为了可能(请参阅 参考资料)。通常,在 Java 代码中集成这些语言需要对各种解释器所特有的 API 和特性有所了解。
Java SE 6 中添加的 javax.script 包使集成动态语言更加容易。通过使用一小组接口和具体类,这个包使我们能够简单地调用多种脚本语言。但是,Java 脚本 API 的功能不只是在应用程序中编写脚本;这个脚本包使我们能够在运行时读取和调用外部脚本,这意味着我们可以动态地修改这些脚本从而更改运行应用程序的行为。
Java 脚本 APIwww.createedu.com qq:253490497
脚本与动态的对比
术语脚本 通常表示在解释器 shell 中运行的语言,它们往往没有单独的编译步骤。术语动态 通常表示等到运行时判断变量类型或对象行为的语言,往往具有闭包和连续特性。一些通用的编程语言同时具有这两种特性。此处首选脚本语言 是因为本文的着重点是 Java 脚本 API,而不是因为提及的语言缺少动态特性。
2006 年 10 月,Java 语言添加了脚本包,从而提供了一种统一的方式将脚本语言集成到 Java 应用程序中去。对于语言开发人员,他们可以使用这个包编写粘连代码(glue code),从而使人们能够在 Java 应用程序中调用他们的语言。对于 Java 开发人员,脚本包提供了一组类和接口,允许使用一个公共 API 调用多种语言编写的脚本。因此,脚本包类似于不同语言(比如说不同的数据库)中的 Java Database Connectivity (JDBC) 包,可以使用一致的接口集成到 Java 平台中去。
以前,在 Java 代码中,动态调用脚本语言涉及到使用各种语言发行版所提供的独特类或使用 Apache 的 Jakarta Bean Scripting Framework (BSF)。BSF 在一个 API 内部统一了一组脚本语言(请参阅 参考资料)。使用 Java SE 6 脚本 API,二十余种脚本语言(AppleScript、Groovy、JavaScript、Jelly、PHP、Python、Ruby 和 Velocity)都可以集成到 Java 代码中,这在很大程序上依赖的是 BSF。
脚本 API 在 Java 应用程序和外部脚本之间提供了双向可见性。Java 代码不仅可以调用外部脚本,而且还允许那些脚本访问选定的 Java 对象。比如说,外部 Ruby 脚本可以对 Java 对象调用方法,并访问对象的属性,从而使脚本能够将行为添加到运行中的应用程序中(如果在开发时无法预计应用程序的行为)。
调用外部脚本可用于运行时应用程序增强、配置、监控或一些其他的运行时操作,比如说在不停止应用程序的情况下修改业务规则。脚本包可能的作用包括:
•在比 Java 语言更简单的语言中编写业务规则,而不用借助成熟的规则引擎。
•创建插件架构,使用户能够动态地定制应用程序。
•将已有脚本集成到 Java 应用程序中,比如说处理或转换文件文章的脚本。
•使用成熟的编程语言(而不是属性文件)从外部配置应用程序的运行时行为。
•在 Java 应用程序中添加一门特定于域的语言(domain-specific language)。
•在开发 Java 应用程序原型的过程中使用脚本语言。
•在脚本语言中编写应用程序测试代码。
你好,脚本世界
HelloScriptingWorld 类(本文中的相关代码均可从 下载部分 获得)演示了 Java 脚本包的一些关键特性。它使用硬编码的 JavaScript 作为示例脚本语言。此类的 main() 方法(如清单 1 所示)将创建一个 JavaScript 脚本引擎,然后分别调用五个方法(在下文的清单中有显示)用于突出显示脚本包的特性。
清单 1. HelloScriptingWorld main 方法
public static void main(String[] args) throws ScriptException, NoSuchMethodException {
ScriptEngineManager scriptEngineMgr = new ScriptEngineManager();
ScriptEngine jsEngine = scriptEngineMgr.getEngineByName("JavaScript");
if (jsEngine == null) {
System.err.println("No script engine found for JavaScript");
System.exit(1);
}
System.out.println("Calling invokeHelloScript...");
invokeHelloScript(jsEngine);
System.out.println("\nCalling defineScriptFunction...");
defineScriptFunction(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromEngine...");
invokeScriptFunctionFromEngine(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromJava...");
invokeScriptFunctionFromJava(jsEngine);
System.out.println("\nCalling invokeJavaFromScriptFunction...");
invokeJavaFromScriptFunction(jsEngine);
}
main() 方法的主要功能是获取一个 javax.script.ScriptEngine 实例(清单 1 中的前两行代码)。脚本引擎可以在特定的语言中加载并执行脚本。它是 Java 脚本包中使用最为频繁、作用最为重要的类。我们从 javax.script.ScriptEngineManager 获取一个脚本引擎(第一行代码)。通常,程序只需要获取一个脚本引擎实例,除非使用了很多种脚本语言。
ScriptEngineManager 类
ScriptEngineManager 可能是脚本包中惟一一个经常使用的具体类;其他大多数都是接口。它或许是脚本包中惟一的一个要直接或间接地(通过 Spring Framework 之类的依赖性注入机制)实例化的类。ScriptEngineManager 可以使用以下三种方式返回脚本引擎:
•通过引擎或语言的名称,比如说 清单 1 请求 JavaScript 引擎。
•通过该语言脚本共同使用的文件扩展名,比如说 Ruby 脚本的 .rb。
•通过脚本引擎声明的、知道如何处理的 MIME 类型。
本文示例为什么要使用 JavaScript?
本文中的 Hello World 示例使用了部分 JavaScript 脚本,这是因为 JavaScript 代码易于理解,不过主要还是因为 Sun Microsystems 和 BEA Systems 所提供的 Java 6 运行时环境附带有基于 Mozilla Rhino 开源 JavaScript 实现的 JavaScript 解释器。使用 JavaScript,我们无需在类路径中添加脚本语言 JAR 文件。
ScriptEngineManager 间接查找和创建脚本引擎。也就是说,当实例化脚本引擎管理程序时,ScriptEngineManager 会使用 Java 6 中新增的服务发现机制在类路径中查找所有注册的 javax.script.ScriptEngineFactory 实现。这些工厂类封装在 Java 脚本 API 实现中;也许您永远都不需要直接处理这些工厂类。
ScriptEngineManager 找到所有的脚本引擎工厂类之后,它会查询各个类并判断是否能够创建所请求类型的脚本引擎 —— 清单 1 中为 JavaScript 引擎。如果工厂说可以创建所需语言的脚本引擎,那么管理程序将要求工厂创建一个引擎并将其返回给调用者。如果没有找到所请求语言的工厂,那么管理程序将返回 null,清单 1 中的代码将检查 null 返回值并做出预防。
Java 开发人员清楚 Java 并不是在任何情况下都是最佳的语言。今年,1.0 版本的 JRuby 和 Groovy 的发行引领了一场热潮,促使人们纷纷在自己的 Java 应用程序中添加动态语言。Groovy、JRuby、Rhino、Jython 和一些其他的开源项目使在所谓的脚本语言中编写代码并在 JVM 中运行成为了可能(请参阅 参考资料)。通常,在 Java 代码中集成这些语言需要对各种解释器所特有的 API 和特性有所了解。
Java SE 6 中添加的 javax.script 包使集成动态语言更加容易。通过使用一小组接口和具体类,这个包使我们能够简单地调用多种脚本语言。但是,Java 脚本 API 的功能不只是在应用程序中编写脚本;这个脚本包使我们能够在运行时读取和调用外部脚本,这意味着我们可以动态地修改这些脚本从而更改运行应用程序的行为。
Java 脚本 APIwww.createedu.com qq:253490497
脚本与动态的对比
术语脚本 通常表示在解释器 shell 中运行的语言,它们往往没有单独的编译步骤。术语动态 通常表示等到运行时判断变量类型或对象行为的语言,往往具有闭包和连续特性。一些通用的编程语言同时具有这两种特性。此处首选脚本语言 是因为本文的着重点是 Java 脚本 API,而不是因为提及的语言缺少动态特性。
2006 年 10 月,Java 语言添加了脚本包,从而提供了一种统一的方式将脚本语言集成到 Java 应用程序中去。对于语言开发人员,他们可以使用这个包编写粘连代码(glue code),从而使人们能够在 Java 应用程序中调用他们的语言。对于 Java 开发人员,脚本包提供了一组类和接口,允许使用一个公共 API 调用多种语言编写的脚本。因此,脚本包类似于不同语言(比如说不同的数据库)中的 Java Database Connectivity (JDBC) 包,可以使用一致的接口集成到 Java 平台中去。
以前,在 Java 代码中,动态调用脚本语言涉及到使用各种语言发行版所提供的独特类或使用 Apache 的 Jakarta Bean Scripting Framework (BSF)。BSF 在一个 API 内部统一了一组脚本语言(请参阅 参考资料)。使用 Java SE 6 脚本 API,二十余种脚本语言(AppleScript、Groovy、JavaScript、Jelly、PHP、Python、Ruby 和 Velocity)都可以集成到 Java 代码中,这在很大程序上依赖的是 BSF。
脚本 API 在 Java 应用程序和外部脚本之间提供了双向可见性。Java 代码不仅可以调用外部脚本,而且还允许那些脚本访问选定的 Java 对象。比如说,外部 Ruby 脚本可以对 Java 对象调用方法,并访问对象的属性,从而使脚本能够将行为添加到运行中的应用程序中(如果在开发时无法预计应用程序的行为)。
调用外部脚本可用于运行时应用程序增强、配置、监控或一些其他的运行时操作,比如说在不停止应用程序的情况下修改业务规则。脚本包可能的作用包括:
•在比 Java 语言更简单的语言中编写业务规则,而不用借助成熟的规则引擎。
•创建插件架构,使用户能够动态地定制应用程序。
•将已有脚本集成到 Java 应用程序中,比如说处理或转换文件文章的脚本。
•使用成熟的编程语言(而不是属性文件)从外部配置应用程序的运行时行为。
•在 Java 应用程序中添加一门特定于域的语言(domain-specific language)。
•在开发 Java 应用程序原型的过程中使用脚本语言。
•在脚本语言中编写应用程序测试代码。
你好,脚本世界
HelloScriptingWorld 类(本文中的相关代码均可从 下载部分 获得)演示了 Java 脚本包的一些关键特性。它使用硬编码的 JavaScript 作为示例脚本语言。此类的 main() 方法(如清单 1 所示)将创建一个 JavaScript 脚本引擎,然后分别调用五个方法(在下文的清单中有显示)用于突出显示脚本包的特性。
清单 1. HelloScriptingWorld main 方法
public static void main(String[] args) throws ScriptException, NoSuchMethodException {
ScriptEngineManager scriptEngineMgr = new ScriptEngineManager();
ScriptEngine jsEngine = scriptEngineMgr.getEngineByName("JavaScript");
if (jsEngine == null) {
System.err.println("No script engine found for JavaScript");
System.exit(1);
}
System.out.println("Calling invokeHelloScript...");
invokeHelloScript(jsEngine);
System.out.println("\nCalling defineScriptFunction...");
defineScriptFunction(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromEngine...");
invokeScriptFunctionFromEngine(jsEngine);
System.out.println("\nCalling invokeScriptFunctionFromJava...");
invokeScriptFunctionFromJava(jsEngine);
System.out.println("\nCalling invokeJavaFromScriptFunction...");
invokeJavaFromScriptFunction(jsEngine);
}
main() 方法的主要功能是获取一个 javax.script.ScriptEngine 实例(清单 1 中的前两行代码)。脚本引擎可以在特定的语言中加载并执行脚本。它是 Java 脚本包中使用最为频繁、作用最为重要的类。我们从 javax.script.ScriptEngineManager 获取一个脚本引擎(第一行代码)。通常,程序只需要获取一个脚本引擎实例,除非使用了很多种脚本语言。
ScriptEngineManager 类
ScriptEngineManager 可能是脚本包中惟一一个经常使用的具体类;其他大多数都是接口。它或许是脚本包中惟一的一个要直接或间接地(通过 Spring Framework 之类的依赖性注入机制)实例化的类。ScriptEngineManager 可以使用以下三种方式返回脚本引擎:
•通过引擎或语言的名称,比如说 清单 1 请求 JavaScript 引擎。
•通过该语言脚本共同使用的文件扩展名,比如说 Ruby 脚本的 .rb。
•通过脚本引擎声明的、知道如何处理的 MIME 类型。
本文示例为什么要使用 JavaScript?
本文中的 Hello World 示例使用了部分 JavaScript 脚本,这是因为 JavaScript 代码易于理解,不过主要还是因为 Sun Microsystems 和 BEA Systems 所提供的 Java 6 运行时环境附带有基于 Mozilla Rhino 开源 JavaScript 实现的 JavaScript 解释器。使用 JavaScript,我们无需在类路径中添加脚本语言 JAR 文件。
ScriptEngineManager 间接查找和创建脚本引擎。也就是说,当实例化脚本引擎管理程序时,ScriptEngineManager 会使用 Java 6 中新增的服务发现机制在类路径中查找所有注册的 javax.script.ScriptEngineFactory 实现。这些工厂类封装在 Java 脚本 API 实现中;也许您永远都不需要直接处理这些工厂类。
ScriptEngineManager 找到所有的脚本引擎工厂类之后,它会查询各个类并判断是否能够创建所请求类型的脚本引擎 —— 清单 1 中为 JavaScript 引擎。如果工厂说可以创建所需语言的脚本引擎,那么管理程序将要求工厂创建一个引擎并将其返回给调用者。如果没有找到所请求语言的工厂,那么管理程序将返回 null,清单 1 中的代码将检查 null 返回值并做出预防。
Java 泛型的理解与等价实现
发贴日期:
2008-05-18 [ 0人评论过 ]
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。www.createedu.com qq:253490497
Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
泛型在使用中还有一些规则和限制:
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上成为“有界类型”。
5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(java.lang.String);
泛型还有接口、方法等等,内容很多,需要花费一番功夫才能理解掌握并熟练应用。在此给出我曾经了解泛型时候写出的两个例子(根据看的印象写的),实现同样的功能,一个使用了泛型,一个没有使用,通过对比,可以很快学会泛型的应用,学会这个基本上学会了泛型70%的内容。
例子一:使用了泛型
public class Gen<T> {
private T ob; //定义泛型成员变量
public Gen(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo {
public static void main(String[] args){
//定义泛型类Gen的一个Integer版本
Gen<Integer> intOb=new Gen<Integer>(88);
intOb.showTyep();
int i= intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义泛型类Gen的一个String版本
Gen<String> strOb=new Gen<String>("Hello Gen!");
strOb.showTyep();
String s=strOb.getOb();
System.out.println("value= " + s);
}
}
例子二:没有使用泛型
public class Gen2 {
private Object ob; //定义一个通用类型成员
public Gen2(Object ob) {
this.ob = ob;
}
public Object getOb() {
return ob;
}
public void setOb(Object ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo2 {
public static void main(String[] args) {
//定义类Gen2的一个Integer版本
Gen2 intOb = new Gen2(new Integer(88));
intOb.showTyep();
int i = (Integer) intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义类Gen2的一个String版本
Gen2 strOb = new Gen2("Hello Gen!");
strOb.showTyep();
String s = (String) strOb.getOb();
System.out.println("value= " + s);
}
}
运行结果:
两个例子运行Demo结果是相同的,控制台输出结果如下:
T的实际类型是:
java.lang.Integer
value= 88
----------------------------------
T的实际类型是: java.lang.String
value= Hello Gen!
Process finished with exit code 0
Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
泛型在使用中还有一些规则和限制:
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上成为“有界类型”。
5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(java.lang.String);
泛型还有接口、方法等等,内容很多,需要花费一番功夫才能理解掌握并熟练应用。在此给出我曾经了解泛型时候写出的两个例子(根据看的印象写的),实现同样的功能,一个使用了泛型,一个没有使用,通过对比,可以很快学会泛型的应用,学会这个基本上学会了泛型70%的内容。
例子一:使用了泛型
public class Gen<T> {
private T ob; //定义泛型成员变量
public Gen(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo {
public static void main(String[] args){
//定义泛型类Gen的一个Integer版本
Gen<Integer> intOb=new Gen<Integer>(88);
intOb.showTyep();
int i= intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义泛型类Gen的一个String版本
Gen<String> strOb=new Gen<String>("Hello Gen!");
strOb.showTyep();
String s=strOb.getOb();
System.out.println("value= " + s);
}
}
例子二:没有使用泛型
public class Gen2 {
private Object ob; //定义一个通用类型成员
public Gen2(Object ob) {
this.ob = ob;
}
public Object getOb() {
return ob;
}
public void setOb(Object ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo2 {
public static void main(String[] args) {
//定义类Gen2的一个Integer版本
Gen2 intOb = new Gen2(new Integer(88));
intOb.showTyep();
int i = (Integer) intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义类Gen2的一个String版本
Gen2 strOb = new Gen2("Hello Gen!");
strOb.showTyep();
String s = (String) strOb.getOb();
System.out.println("value= " + s);
}
}
运行结果:
两个例子运行Demo结果是相同的,控制台输出结果如下:
T的实际类型是:
java.lang.Integer
value= 88
----------------------------------
T的实际类型是: java.lang.String
value= Hello Gen!
Process finished with exit code 0
Java 泛型的理解与等价实现
发贴日期:
2008-05-18 [ 0人评论过 ]
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。www.createedu.com qq:253490497
Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
泛型在使用中还有一些规则和限制:
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上成为“有界类型”。
5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(java.lang.String);
泛型还有接口、方法等等,内容很多,需要花费一番功夫才能理解掌握并熟练应用。在此给出我曾经了解泛型时候写出的两个例子(根据看的印象写的),实现同样的功能,一个使用了泛型,一个没有使用,通过对比,可以很快学会泛型的应用,学会这个基本上学会了泛型70%的内容。
例子一:使用了泛型
public class Gen<T> {
private T ob; //定义泛型成员变量
public Gen(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo {
public static void main(String[] args){
//定义泛型类Gen的一个Integer版本
Gen<Integer> intOb=new Gen<Integer>(88);
intOb.showTyep();
int i= intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义泛型类Gen的一个String版本
Gen<String> strOb=new Gen<String>("Hello Gen!");
strOb.showTyep();
String s=strOb.getOb();
System.out.println("value= " + s);
}
}
例子二:没有使用泛型
public class Gen2 {
private Object ob; //定义一个通用类型成员
public Gen2(Object ob) {
this.ob = ob;
}
public Object getOb() {
return ob;
}
public void setOb(Object ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo2 {
public static void main(String[] args) {
//定义类Gen2的一个Integer版本
Gen2 intOb = new Gen2(new Integer(88));
intOb.showTyep();
int i = (Integer) intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义类Gen2的一个String版本
Gen2 strOb = new Gen2("Hello Gen!");
strOb.showTyep();
String s = (String) strOb.getOb();
System.out.println("value= " + s);
}
}
运行结果:
两个例子运行Demo结果是相同的,控制台输出结果如下:
T的实际类型是:
java.lang.Integer
value= 88
----------------------------------
T的实际类型是: java.lang.String
value= Hello Gen!
Process finished with exit code 0
Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
泛型在使用中还有一些规则和限制:
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上成为“有界类型”。
5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(java.lang.String);
泛型还有接口、方法等等,内容很多,需要花费一番功夫才能理解掌握并熟练应用。在此给出我曾经了解泛型时候写出的两个例子(根据看的印象写的),实现同样的功能,一个使用了泛型,一个没有使用,通过对比,可以很快学会泛型的应用,学会这个基本上学会了泛型70%的内容。
例子一:使用了泛型
public class Gen<T> {
private T ob; //定义泛型成员变量
public Gen(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo {
public static void main(String[] args){
//定义泛型类Gen的一个Integer版本
Gen<Integer> intOb=new Gen<Integer>(88);
intOb.showTyep();
int i= intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义泛型类Gen的一个String版本
Gen<String> strOb=new Gen<String>("Hello Gen!");
strOb.showTyep();
String s=strOb.getOb();
System.out.println("value= " + s);
}
}
例子二:没有使用泛型
public class Gen2 {
private Object ob; //定义一个通用类型成员
public Gen2(Object ob) {
this.ob = ob;
}
public Object getOb() {
return ob;
}
public void setOb(Object ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo2 {
public static void main(String[] args) {
//定义类Gen2的一个Integer版本
Gen2 intOb = new Gen2(new Integer(88));
intOb.showTyep();
int i = (Integer) intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义类Gen2的一个String版本
Gen2 strOb = new Gen2("Hello Gen!");
strOb.showTyep();
String s = (String) strOb.getOb();
System.out.println("value= " + s);
}
}
运行结果:
两个例子运行Demo结果是相同的,控制台输出结果如下:
T的实际类型是:
java.lang.Integer
value= 88
----------------------------------
T的实际类型是: java.lang.String
value= Hello Gen!
Process finished with exit code 0
java接口例子(登陆程序)
发贴日期:
2008-05-17 [ 0人评论过 ]
public interface Jiekou {
abstract void set(String acc ,String pass);
}
interface Jiekou1{
final String ACCOUNT = "root";
final String PASSWORD = "123456";
abstract void connect();
}
interface ShowResult{
abstract void show();
}
class UserDB implements Jiekou,Jiekou1,ShowResult{
String userAccount;
String userPassword;
String resultMessage;
public void set(String acc, String pass){
this.userAccount = acc;
this.userPassword = pass;
}
public void connect(){
if(userAccount == ACCOUNT &&userPassword == PASSWORD){
resultMessage = "成功连接到数据库!";
}else{
resultMessage = "登陆失败,请检查用户名和密码!";
}
}
public void show(){
System.out.println(resultMessage);
}www.createedu.com
}qq:253490497
abstract void set(String acc ,String pass);
}
interface Jiekou1{
final String ACCOUNT = "root";
final String PASSWORD = "123456";
abstract void connect();
}
interface ShowResult{
abstract void show();
}
class UserDB implements Jiekou,Jiekou1,ShowResult{
String userAccount;
String userPassword;
String resultMessage;
public void set(String acc, String pass){
this.userAccount = acc;
this.userPassword = pass;
}
public void connect(){
if(userAccount == ACCOUNT &&userPassword == PASSWORD){
resultMessage = "成功连接到数据库!";
}else{
resultMessage = "登陆失败,请检查用户名和密码!";
}
}
public void show(){
System.out.println(resultMessage);
}www.createedu.com
}qq:253490497
java接口例子(登陆程序)
发贴日期:
2008-05-17 [ 0人评论过 ]
public interface Jiekou {
abstract void set(String acc ,String pass);
}
interface Jiekou1{
final String ACCOUNT = "root";
final String PASSWORD = "123456";
abstract void connect();
}
interface ShowResult{
abstract void show();
}
class UserDB implements Jiekou,Jiekou1,ShowResult{
String userAccount;
String userPassword;
String resultMessage;
public void set(String acc, String pass){
this.userAccount = acc;
this.userPassword = pass;
}
public void connect(){
if(userAccount == ACCOUNT &&userPassword == PASSWORD){
resultMessage = "成功连接到数据库!";
}else{
resultMessage = "登陆失败,请检查用户名和密码!";
}
}
public void show(){
System.out.println(resultMessage);
}www.createedu.com
}qq:253490497
abstract void set(String acc ,String pass);
}
interface Jiekou1{
final String ACCOUNT = "root";
final String PASSWORD = "123456";
abstract void connect();
}
interface ShowResult{
abstract void show();
}
class UserDB implements Jiekou,Jiekou1,ShowResult{
String userAccount;
String userPassword;
String resultMessage;
public void set(String acc, String pass){
this.userAccount = acc;
this.userPassword = pass;
}
public void connect(){
if(userAccount == ACCOUNT &&userPassword == PASSWORD){
resultMessage = "成功连接到数据库!";
}else{
resultMessage = "登陆失败,请检查用户名和密码!";
}
}
public void show(){
System.out.println(resultMessage);
}www.createedu.com
}qq:253490497

22
0