Java,是一种可以撰写跨平台应用软件的面向对象的程序设计语言,由升阳(Sun Microsystems)公司的詹姆斯·高斯林(James Gosling)等人于1990年代初开发。它最初被命名为Oak,目标设定在家用电器等小型系统的编程语言,来解决诸如电视机、电话、闹钟、烤面包机等家用电器的控制和通讯问题。由于这些智能化家电的市场需求没有预期的高,Sun放弃了该项计划。就在Oak几近失败之时,随着互联网的发展,Sun看到了 Oak在计算机网络上的广阔应用前景,于是改造了Oak,在1995年5月以“Java”的名称正式发布了。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。 Oracle收购Sun背后 Solaris前途未卜。
Java 编程语言的风格十分接近C 语言。继承了 C 语言面向对象技术的核心,Java舍弃了C 语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)、多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再被引用的对象所占据的内存空间。在 Java SE 1.5 版本中,Java 又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性。
Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了“一次编译、到处执行”的跨平台特性。不过,这同时也在一定程度上降低了 Java 程序的运行效率。但在 J2SE 1.4.2 发布后,Java 的执行速度有了大幅提升。
与传统程序不同,Sun 公司在推出 Java 之际就将其作为一种开放的技术。全球数以万计的 Java 开发公司被要求所设计的 Java 软件必须相互兼容。“Java 语言靠群体的力量而非公司的力量”是 Sun 公司的口号之一,并获得了广大软件开发商的认同。这与微软公司所倡导的注重精英和封闭式的模式完全不同。
Sun 公司对 Java 编程语言的解释是:Java 编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言。
Java 平台是基于 Java 语言的平台。这样的平台目前非常流行,因此微软公司推出了与之竞争的.NET平台以及模仿 Java 的 C# 语言。
一天,几位Java成员组的会员正在讨论给这个新的语言取什么名字,当时他们正在咖啡馆喝着Java(爪哇)咖啡,有一个人灵机一动说就叫Java 怎样,这个提议得到了其他人的赞同,于是,Java这个名字就这样传开了。原来看SUN的JAVA标识没去多想,现在看看,这不就是一杯正冒着热气的咖啡吗?
早期的Java
Java平台和语言最开始只是升阳公司在1990年12开始研究的一个内部项目。升阳公司的一个叫做帕特里克·诺顿的工程师被升阳自己开发的C 和C语言编译器搞得焦头烂额,因为其中的API极其难用。帕特里克决定改用NeXT,同时他也获得了研究公司的一个叫做“Stealth 计划”的项目的机会。
“Stealth 计划”后来改名为“Green计划”,詹姆斯·高斯林和麦克·舍林丹也加入了帕特里克的工作小组。他们和其他几个工程师一起在加利福尼亚州门罗帕克市沙丘路的一个小工作室里面研究开发新技术,瞄准下一代智能家电(如微波炉)的程序设计,升阳公司预料未来科技将在家用电器领域大显身手。团队最初考虑使用C 语言,但是很多成员包括升阳的首席科学家比尔·乔伊,发现C 和可用的API在某些方面存在很大问题。
工作小组使用的是内嵌类型平台,可以用的资源极其有限。很多成员发现C 太复杂以至很多开发者经常错误使用。他们发现C 缺少垃圾回收系统,还有可移植的安全性、分布程序设计、和多线程功能。最后,他们想要一种易于移植到各种设备上的平台。
根据可用的资金,比尔·乔伊决定开发一种集C语言和 Mesa语言大成的新语言,在一份报告上,乔伊把它叫做“未来”,他提议升阳公司的工程师应该在C 的基础上,开发一种面向对象的环境。最初,高斯林试图修改和扩展C 的功能,他自己称这种新语言为 C --,但是后来他放弃了。他将要创造出一种全新的语言,被他命名为“Oak”(橡树),以他的办公室外的树而命名。
就像很多开发新技术的秘密的工程一样,工作小组没日没夜地工作到了1992年的夏天,他们能够演示新平台的一部分了,包括Green操作系统,Oak的程序设计语言,类库,和其硬件。最初的尝试是面向一种类PDA设备,被命名为Star7,这种设备有鲜艳的图形界面和被称为“Duke”的智能代理来帮助用户。1992年12月3日,这台设备进行了展示。
同年11月,Green计划被转化成了“FirstPerson有限公司”,一个升阳公司的全资子公司,团队也被重新安排到了帕洛阿尔托。 FirstPerson团队对建造一种高度互动的设备感兴趣,当时代华纳发布了一个关于电视机顶盒的征求提议书时(Request for proposal),FirstPerson改变了他们的目标,作为对征求意见书的响应, 提出了一个机顶盒平台的提议。但是有线电视业界觉得FirstPerson的平台给予用户过多地控制权,因此FirstPerson的投标败给了SGI。与3DO 公司的另外一笔关于机顶盒的交易也没有成功,由于他们的平台不能在电视工业产生任何效益,公司再并回升阳公司。
JAVA遭遇互联网
1994年6、7月间,在经历了一场历时三天的头脑风暴的讨论后,约翰·盖吉、詹姆斯·高斯林、比尔·乔伊、帕特里克·诺顿、韦恩·罗斯因和埃里克·斯库米,团队决定再一次改变了努力的目标,这次他们决定将该技术应用于万维网。他们认为随着Mosaic浏览器的到来,因特网正在向同样的高度互动的远景演变,而这一远景正是他们在有线电视网中看到的。作为原型,帕特里克·诺顿写了一个小型万维网浏览器,WebRunner,后来改名为HotJava。
同年,Oak改名为Java。商标搜索显示,Oak已被一家显卡制造商注册,因此团队找到了一个新名字。这个名字是在很多成员常去的本地咖啡馆中杜撰出来的。名字是不是首字母缩写还不清楚,很大程度上来说不是。虽然有人声称是开发人员名字的组合:James Gosling(詹姆斯·高斯林) Arthur Van Hoff(阿瑟·凡·霍夫) Andy Bechtolsheim(安迪·贝克托克姆),或“Just Another Vague Acronym”(只是另外一个含糊的缩写)。还有一种比较可信的说法是这个名字是出于对咖啡的喜爱,所以以Java咖啡来命名。类文件的前四个字节如果用十六进制阅读的话,分别为CA FE BA BE, 就会拼出两个单词“CAFE BABE”(咖啡宝贝)。
1994年10月,HotJava和Java平台为公司高层进行演示。1994年,Java 1.0a版本已经可以提供下载,但是Java和HotJava浏览器的第一次公开发布却是在1995年3月23日SunWorld大会上进行的。升阳公司的科学指导约翰·盖吉宣告Java技术。这个发布是与网景公司的执行副总裁马克·安德森的惊人发布一起进行的,宣布网景将在其浏览器中包含对Java的支持。1996年1月,升阳公司成立了Java业务集团,专门开发Java技术。
1、Java语言是简单的。Java语言的语法与C语言和C++语言很接近,使得大多数程序员很容易学习和使用Java。另一方面,Java丢弃了 C++ 中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制类型转换。特别地,Java语言不使用指针,并提供了自动的废料收集,使得程序员不必为内存管理而担忧。
2、Java语言是一个面向对象的。Java语言提供类、接口和继承等原语,为了简单起见,只支持类之间的单继承,但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为implements)。Java语言全面支持动态绑定,而C++ 语言只对虚函数使用动态绑定。总之,Java语言是一个纯的面向对象程序设计语言。
3、Java语言是分布式的。Java语言支持Internet应用的开发,在基本的Java应用编程接口中有一个网络应用编程接口(java.net),它提供了用于网络应用编程的类库,包括URL、URLConnection、Socket、 ServerSocket等。Java的RMI(远程方法激活)机制也是开发分布式应�玫闹匾侄巍�
4、Java语言是健壮的。Java的强类型机制、异常处理、废料的自动收集等是Java程序健壮性的重要保证。对指针的丢弃是Java的明智选择。Java的安全检查机制使得Java更具健壮性。
5、Java语言是安全的。Java通常被用在网络环境中,为此,Java提供了一个安全机制以防恶意代码的攻击。除了Java语言具有的许多安全特性以外,Java对通过网络下载的类具有一个安全防范机制(类ClassLoader),如分配不同的名字空间以防替代本地的同名类、字节代码检查,并提供安全管理机制(类SecurityManager)让Java应用设置安全哨兵。
6、Java语言是体系结构中立的。Java程序(后缀为java的文件)在Java平台上被编译为体系结构中立的字节码格式(后缀为class的文件), 然后可以在实现这个Java平台的任何系统中运行。这种途径适合于异构的网络环境和软件的分发。
7、Java语言是可移植的。这种可移植性来源于体系结构中立性,另外,Java还严格规定了各个基本数据类型的长度。Java系统本身也具有很强的可移植性,Java编译器是用Java实现的,Java的运行环境是用ANSI C实现的。
8、Java语言是解释型的。如前所述,Java程序在Java�教ㄉ媳槐嘁胛纸诼敫袷剑� 然后可以在实现这个Java平台的任何系统中运行。在运行时,Java平台中的Java解释器对这些字节码进行解释执行,执行过程中需要的类在联接阶段被载入到运行环境中。
9、Java是高性能的。与那些解释型的高级脚本语言相比,Java的确是高性能的。事实上,Java的运行速度随着JIT(Just-In-Time)编译器技术的发展越来越接近于C++。
10、Java语言是多线程的。在Java语言中,线程是一种特殊的对象,它必须由Thread类或其子(孙)类来创建。通常有两种方法来创建线程:其一,使用型构为Thread(Runnable) 的构造子将一个实现了Runnable接口的对象包装成一个线程,其二,从Thread类派生出子类并重写run方法,使用该子类创建的对象即为线程。值得注意的是Thread类已经实现了Runnable接口,因此,任何一个线程均有它的run方法,而run方法中包含了线程所要运行的代码。线程的活动由一组方法来控制。 Java语言支持多个线程的同时执行,并提供多线程之间的同步机制(关键字为synchronized)。
11、Java语言是动态的。Java语言的设计目标之一是适应于动态变化的环境。Java程序需要的类能够动态地被载入到运行环境,也可以通�缋丛厝胨枰睦唷U庖灿欣谌砑纳丁A硗猓琖ava中的类有一个运行时刻的表示,能进行运行时刻的类型检查。
Java语言的优良特性使得Java应用具有无比的健壮性和可靠性,这也减少了应用系统的维护费用。Java对对象技术的全面支持和Java平台内嵌的 API能缩短应用系统的开发时间并降低成本。Java的编译一次,到处可运行的特性使得它能够提供一个随处可用的开放结构和在多平台之间传递信息的低成本方式。特别是Java企业应用编程接口(Java Enterprise APIs)为企业计算及电子商务应用系统提供了有关技术和丰富的类库。
Java是一种简单的,面向对象的,分布式的,解释型的,健壮安全的,结构中立的,可移植的,性能优异、多线程的动态语言。
当1995年SUN推出Java语言之后,全世界的目光都被这个神奇的语言所吸引。那么Java到底有何神奇之处呢?
Java语言其实最早诞生于1991年,起初被称为OAK语言,是SUN公司为一些消费性电子产品而设计的一个通用环境。他们最初的目的只是为了开发一种独立于平台的软件技术,而且在网络出现之前,OAK可以说是默默无闻,甚至差点夭折。但是,网络的出现改变了OAK的命运。
在Java出现以前,Internet上的信息内容都是一些乏味死板的HTML文档。这对于那些迷恋于WEB浏览的人们来说简直不可容忍。他们迫切希望能在WEB中看到一些交互式的内容,开发人员也极希望能够在WEB上创建一类无需考虑软硬件平台就可以执行的应用程序,当然这些程序还要有极大的安全保障。对于用户的这种要求,传统的编程语言显得无能为力。SUN的工程师敏锐地察觉到了这一点,从1994年起,他们开始将OAK技术应用于WEB上,并且开发出了HotJava的第一个版本。当SUN公司1995年正式以Java这个名字推出的时候,几乎所有的WEB开发人员都心生感叹:噢,这正是我想要的!于是Java成了一颗耀眼的明星,丑小鸭一下了变成了白天鹅。
Java近况
在流行几年之后,Java在浏览器中的地位被逐步侵蚀。它在简单交互性动画方面的用途已经完全被Adobe公司的Flash排挤,2005年Java倾向只被用于雅虎游戏那样的更为复杂的应用程序。Java同时遭受到来自微软的反对,他们决定在新版本的Internet Explorer和Windows中不再附带Java平台。
与此相反。在万维网的服务器端和手持设备上,Java变得更加流行。很多网站在前端使用JSP和其他的Java技术。
在桌面系统上,独立的Java程序还是相对少见,这是因为Java平台的运行开销较大,而许多人的电脑上没有安装Java,由于网络带宽在以前较小,下载Java曾经是个耗时的事情。但是随着计算机计算能力、网络带宽在10年中取得了很大的进步,同时虚拟机和编译器的质量得到了越高,许多应用程序得到了广泛的使用,包括:
开源软件:
NetBeans
Eclipse
JEdit
Azureus BitTorrent客户端。
JNode操作系统
闭源软件:
EIOffice(永中Office)
纯Java 3D游戏合金战士Chrome
还有许多用Java写的软件,可以在 http://www.java.com 找到。 在以下网页可以看到非常多用Java写的程序: http://java.sun.com/products/ 下面有大量用Java Swing开发的桌面Java程序 http://java.sun.com/products/jfc/tsc/sightings/ 目前Java提供以下三个版本:
Java Platform, Enterprise Edition (Java EE:Java平台企业版)
Java Platform, Standard Edition (Java SE:Java平台标准版)
Java Platform, Micro Edition (Java ME:Java平台微型版)
以上为Java各种版本的SUN公司官方中文翻译方式:http://cn.sun.com/press/jun2005/20050627-6.html
版本历史(时间表)
1995年5月23日,Java语言诞生
1996年1月,第一个JDK-JDK1.0诞生
1996年4月,10个最主要的操作系统供应商申明将在其产品中嵌入JAVA技术
1996年9月,约8.3万个网页应用了JAVA技术来制作
1997年2月18日,JDK1.1发布
1997年4月2日,JavaOne会议召开,参与者逾一万人,创当时全球同类会议规模之纪录
1997年9月,JavaDeveloperConnection社区成员超过十万
1998年2月,JDK1.1被下载超过2,000,000次
1998年12月8日,JAVA2企业平台J2EE发布
1999年6月,SUN公司发布Java的三个版本:标准版(J2SE)、企业版(J2EE)和微型版(J2ME)
2000年5月8日,JDK1.3发布
2000年5月29日,JDK1.4发布
2001年6月5日,NOKIA宣布,到2003年将出售1亿部支持Java的手机
2001年9月24日,J2EE1.3发布
2002年2月26日,J2SE1.4发布,自此Java的计算能力有了大幅提升
2004年9月30日18:00PM,J2SE1.5发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性,J2SE1.5更名为Java SE 5.0
2005年6月,JavaOne大会召开,SUN公司公开Java SE 6。此时,Java的各种版本已经更名,以取消其中的数字“2”:J2EE更名为Java EE,J2SE更名为Java SE,J2ME更名为Java ME
2006年12月,SUN公司发布JRE6.0
Java之所以被开发,是要达到以下五个:
应当使用面向对象程序设计方法学
应当允许同一程序在不同的计算机平台执行
应当包括内建的对计算机网络的支持
应当被设计成安全地执行远端代码
应当易于使用,并借鉴以前那些面向对象语言(如C )的长处。
Java技术主要分成几个部分:Java语言、运行环境JVM、类库。一般情况下说Java时并不区分指的是哪个部分。
面向对象
Java的特点之一就是面向对象,是程序设计方法的一种。“面向对象程序设计语言”的核心之一就是开发者在设计软件的时候可以使用自定义的类型和关联操作。代码和数据的实际集合体叫做“对象”。一个对象可以想象成绑定了很多“行为(代码)”和“状态(数据)”的物体。对于数据结构的改变需要和代码进行通信然后操作,反之亦然。面向对象设计让大型软件工程的计划和设计变得更容易管理,能增强工程的健康度,减少失败工程的数量。
面向对象设计另外一个目标就是能产生很多的有关联的类,可以让软件的再开发变得简单。举例来说,很多软件工程都有同样的功能,尤其是很多应用了同一原理组织的软件工程。软件的二次开发者想自己为软件开发插件以增强功能的时候,绝对不想看到混乱的开发代码和管理计划。面向对象的目的就是不生产难懂且难以使用的代码,为软件各个功能群之间建立有效的通信通道。很多开源软件社区正�诩苹砑髡咛峁└嗟睦嗬慈萌砑亩慰⒈涞眉虮恪�
跨平台姓
Java语言的第二个特性就是跨平台性,也就是说使用Java语言编写的程序可以在编译后不用经过任何更改,就能在任何硬件设备条件下运行。这个特性经常被称为“一次编译,到处运行”。
实现跨平台性的方法是大多数编译器在进行Java语言程序的编码时候会生成一个用字节码(Bytecode)写成的“半成品”,这个“半成品”会在Java虚拟机(解释层)的帮助下运行,虚拟机会把它转换成当前所处硬件平台的原始代码。之后,Java虚拟机会打开标准库,进行数据(图片、线程和网络)的存取工作。主要注意的是,尽管已经存在一个进行代码翻译的解释层,有些时候Java的字节码代码还是会被JIT编译器进行二次编译。
有些编译器,比如GCJ,可以自动生成原始代码而不需要解释层。但是这些编译器所生成的代码只能应用于特定平台。并且GCJ目前只支持部分的Java API。
升阳对于Java的许可是“全兼容的”,这也导致了微软和升阳关于微软的程序不支持RMI和JNI接口、并且增加特性为己所用的法律争端。升阳最终赢得了官司,获得了大约两千万美元的赔偿,法院强制要求微软执行升阳公司关于Java的许可要求。作为回应,微软不再在Windows系统中捆绑 Java,最新的Windows版本,Windows Vista和Internet Explorer 7.0版本也不再提供对于Java应用程序和控件的支持。但是升阳公司和其他使用Java运行时系统的公司对于微软的操作对用户提供无偿的第三方插件和程序支持。
Java语言使用解释层最初是为了轻巧性。所以这些程序的运行效率比C语言和C 要低很多,用户也对此颇有微词。很多最近的调查显示Java的程序运行速度比几年前要高出许多,有些同样功能的程序的效率甚至超过了C 和C语言编写的程序。
Java语言在最开始应用的时候是没有解释层的,所有需要编译的代码都直接转换成机器的原始代码。这样做的后果就是获得了最佳的性能,但是程序臃肿异常。从JIT技术开始,Java的程序都经过一次转换之后才�涑苫髀搿:芏嗬吓频牡谌叫槟饣际褂靡恢纸凶�“动态编译”的技术,也就是说虚拟机实时监测和分析程序的运行行为,同时选择性地对程序所需要的部分进行编译和优化。所有这些技术都改善了代码的运行速度,但是又不会让程序的体积变得失常。
程序的轻便性事实上是软件编写很难达到的一个目标,Java虽然成功地实现了“一次编译,到处运行”,但是由于平台和平台之间的差异,所编写的程序在转换代码的时候难免会出现微小的、不可察觉的错误和意外。有些程序员对此非常头疼,他们嘲笑Java的程序不是“一次编译,到处运行”,而是“一次编译,到处调试”。
平台无关性让Java在服务器端软件领域非常成功。很多服务器端软件都使用Java或相关技术建立。
自动垃圾回收(Garbage Collection)
C 语言被用户诟病的原因之一就是大多数C 编译器不支持垃圾收集机制。通常使用C 编程的时候,程序员所创建的对象在创建时在本地堆栈上分配一块内存地址,当不需要这个对象,进行析构或者删除的时候再释放分配的内存地址。如果对象是在堆上分配的,而程序员又忘�墙械刂飞境敲淳突嵩斐赡诖嫘孤�(Memory Leak)。长此以往,程序运行的时候可能会生成很多不清除的垃圾,浪费了不必要的内存空间。更糟糕的是,如果同一内存地址被删除两次的话,程序会变得不稳定,甚至崩溃。因此有经验的C 程序员都会在删除之后将指针重置为0,然后在删除之前先判断指针是否为0。
Java语言则不同,上述的情况被自动垃圾收集功能自动处理。对象的建立和放置都是在内存堆上面进行的。程序或者其他的对象可以锁定一块堆地址来进行其他对象的引用。当一个对象没有任何引用的时候,Java的自动垃圾收集机制就发挥作用,自动删除这个对象所占用的空间,释放内存以避免内存泄漏。但是内存泄漏并不是就此避免了,当程序员疏忽大意地忘记解除一个对象不应该有的引用的时候,内存泄漏仍然不可避免,不过发生的几率要比不启用垃圾收集机制的C 程序少很多。但是总体来讲,自动垃圾收集机制要安全和简单许多。
不同厂商、不同版本的JVM中的内存垃圾回收机制并不完全一样,通常越新版本的内存回收机制越快,IBM、BEA、SUN等等开发JVM的公司都曾宣称过自己制造出了世界上最快的JVM, JVM性能的世界纪录也在不断的被打破并提高。
IBM有一篇有关Java内存回收机制比不启用垃圾收集机制的C 内存处理快数倍的技术文章,可在如下网址找到:
http://www-128.ibm.com/developerworks/cn/java/j-jtp09275.html
而著名的Java技术书籍《Java编程思想》(《Thinking in Java》)也有一段论述Java内存及性能达到甚至超过C 的章节:
http://www.sdau.edu.cn/support/thinkinjava/chapter/appe.htm
但是应该注意到,C 中也可以使用“智能指针”(Smart Pointer)或者使用C 托管扩展编译器的方法来实现自动化内存释放,智能指针可以在标准类库中找到,而C 托管扩展被微软的Visual C 7.0及以上版本所支持。智能指针的优点是不需引入缓慢的垃圾收集机制,而且可以不考虑线程安全的问题,但是缺点是如果不善使用智能指针的话,性能有可能不如垃圾收集机制,而且不断地分配和释放内存可能造成内存碎片,需要手动对堆进行压缩。除此之外,由于智能指针是一个基于模板的功能,所以没有经验的程序员在需要使用多态特性进行自动清理时也可能束手无策。
当然,作为一个“负责任”的程序编撰员,在程序完结前应该手动清理不再需要的变量和物件,令效能有点提升。以Java为例,finalize方法位于 Java.Object 内,而Object 这个类是每一个类自动承继的。因此清理需要的便是覆写finalize便行了。
protected void finalize() throws Throwable{ super.finalize(); } |
当中若有任何变量要清理,可以在super.finalize() 前加上 = null; 或 . = null;
不过事实上,就算使用了 finalize(),你还是不能保证你在堆栈中所使用的空间会马上被回收,垃圾回收机制只有在你的你堆栈已经毫无空间可以使用的情况下,才会真的去进行回收的动作,因此在编程上,还是要避免内存空间的浪费。
接口和类别
Java自带了创建接口的类别,可以这样使用:
public interface Deleteable { void delete(); } |
这段代码的意思是任何实现(implement)Deleteable接口的类别都必须实现delete()方法。每个类别对这个方法的实现可以自行定制。由此概念可以引出很多种使用方法,下面是一个类别的例子:
public class Fred implements Deleteable { //Must include the delete () method to satisfy the Deleteable interface public void delete() { //code implementation goes here } //Can also include other methods public void doOtherStuff() { } } |
在另外一个类别中,可以使用这样的代码:
public void deleteAll (Deleteable [] list) { for (int i = 0; i < list.length; i ) { list[i].delete(); } } |
因为队列中所有的对象都可以使用delete()方法。Deleteable队列中包含Fred对象的引用,而这个类别和其他Deleteable类别在使用deleteAll()方法时候不需要进行任何改变。
之所以这样做就是为了在接口的执行和其代码之间进行区别。举例来说,一个名叫Collection的接口可以包含任何对象所需要的引入、转换和存储数据的方法,其他的类都可以使用这个接口。但是这个接口可以是一个可重定义大小的队列、一个链表或者是其他功能的集合。
这种特性其实是一种折中的办法。Java的设计者们不想让Java有多重继承的特性,因为C 的多重继承显示了这种特性的困难。Java的接口功能可以提供同样的功能,但是又不会很复杂。
自动装箱/拆箱 (Auto-Boxing/Unboxing)
没有自动装箱/拆箱:
int int1 = 1; Integer integer2 = new Integer(int1); int int3 = integer2.intValue(); |
有自动装箱/拆箱:
int int1 = 1; Integer integer2 = int1; // 自动装箱 int int3 = integer2; // 自动拆箱 |
泛型 (Generic Types)
泛型就像是C 的模板。原有的Collection API加上泛型支援后,增加对型别的检查,减少程序错误的机会。
没有泛型:
HashMap hm = new HashMap(); int i=1; String tt="test"; hm.put(new Integer(i), tt); |
使用Generic:
HashMap hm = new HashMap(); int i=1; String tt = "test"; hm.put(i, tt); // 在这里对int自动装箱成Integer,也使用了参数的型别检查 |
自动装箱的新功能,可能是从C#语言身上学习来的,Java 已经越来越像C#。然而Java对自动装箱/拆箱的支援,仅是利用编译器实现,在Java Bytecode 中,并无自动装箱/拆箱的操作码 (opcode)。
注释 (Annotation)
Annotation全名是Program Annotation Facility ,是Java SE 5.0的新功能。Java 的 Annotation 类似于 .NET 的属性 (Attribute)。Java 的注释是一种接口 (interface),继承自 java.lang.annotation.Annotation。Class File 则贴上 ACC_ANNOTATION 标签。
// JDK 1.4 /** * @todo to be implemented **/ void gimmeSomeLoving() { throw new Exception("not implemented"); } |
// JDK 1.5 @todo void gimmeSomeLoving() { throw new Exception("not implemented"); } |
枚举类型 (enum)
枚举类型也是J2SE 5.0的新功能。过去 Java 认为 enum 的关键字是不必要的功能,因为用 public static int field 就可以取代 enum,因此过去一直不用。J2SE 5.0中的 class 如果是 enum,在 class file �谢岜惶弦桓� ACC_ENUM 标签。
// JDK 1.4 class JavaTech { public static final int J2ME = 1; public static final int J2SE = 2; public static final int J2EE = 3; } |
// JDK 1.5 public enum NewJavaTech { J2ME, J2SE, J2EE } |
输入输出
试试用位于 java.io 包 (package) 内的BufferedReader。请紧记要 import java.io.*;。尾部"*"是指示要 import 所有位于 java.io 内的类。
import java.io.*; |
public class TestRead{ public static void main(String[] args) throws IOException{ BufferedReader bufread = new BufferedReader(System.in); String str; System.out.print("请输入一句字串"); str = bufread.readLine(); System.out.println(str); } } |
程序码解说: import java.io.* 是把整个包“打开”,那么你便可以承继该包的类,用内里的类创建一个物件。其实 java.io.* 是缺省 import 的,不过 Eclipse 会要求 import java.io 所以功夫不可小!
public class TestRead 是宣告一个“公开”的 class(类别),而名字是TestRead 。
public static void main(String[] args) 是一个主程序。虽然是 Method ,但 main method 对于 Java 执行器来说是第一个执行程序的地方,同样离开了 main method 就等如离开了程序。main method 的宣告式是要背的,当然是有解,不过暂且不说。
BufferedReader bufread = new BufferedReader(System.in) 在此创建一个以 BufferedReader 为蓝图的物件 bufread ,bufread名字是任你定的。详细来说是第一个BufferedReader 是宣告 bufread 是一个会“存储”一个BufferedReader类的物件。new BufferedReader(System.in) 是指创建一个 BufferedReader 的物件。由于BufferedReader 需要一个输入流,因此我们指定了 System.in 给 BufferedReader。
应用程序开发接口
在Java语言中,应用程序接口(API)化身成类,并且分组成为包。每个包中包含有相关的接口和类。对于不同的平台,Java提供了不同版本的包。
API的设定由升阳公司和其他公司通过JCP(Java社群程序)决定。任何公司和个人都可以参与这个工程,对API进行设计。
2004年,IBM和BEA公司准备联合对官方的Java开源软件工程进行支持,但是2005年初,升阳公司拒绝了这个支持。
Hello World
下面这个程序显示“Hello, world!”然后结束运行:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, world!"); } } |
国际化
Java语言严格区分字节和字符。字符的存储格式为UCS-2,从Java 5开始支持UTF-16字符。Java的程序遂可以使用Unicode字符进行书写。
下面就是一个合法的Java程序,里面包含了中文字符作为类的名称而不是字符串,这个程序可以在编译器中运行通过。
public class 哈啰世界 { private string 文本 = "哈啰世界"; } |
其它
数据类型
任何编程语言都免不了要定义变量,JAVA也不例外。JAVA的变量声明形式如下:
type name; |
其中的type是数据类型名,name指�ㄒ宓母檬堇嘈偷囊桓鼍咛灞淞俊�
JAVA的内置数据类型主要有如下几种:
boolean : 布尔值,仅有两个常量,true和false.
byte :字节类型值,长度8位(一个字节),取值范围是-128至127。
short :短整型值,长度16位(两个字节),取值范围是-32768至32767。
int :整型值,长度32位(四个字节),取值范围是-2147483648至2147483647
long :长整型,长度64位(八个字节),取值范围是-9223372036854775808至9223372036854775807
float :单精度IEEE754浮点数,长度32位(四个字节)。
double :双精度IEEE754浮点数,长度64位(八个字节)。
char :字符型,长度16位,支持所有的Unicode和Ascii编码。
JAVA关键字
Java试图通过新的方式解决软件编写的复杂性。很多人认为Java语言做到了它承诺的一切。但是Java并不是一门完美的语言,在编程风格、编程环境和需求方面并没有获得全球性的认可。
并不是所有的工程和环境需要企业级别的复杂性,比如一个简单的个人网站或者独自编程的程序员所写的程序。这些程序员会发现Java的复杂管理对于自己要做的程序来说过于强大了。
Java经常让那些并不是对面向对象编程很热心的程序员感到不满。
一些人觉得Java在面向对象上面做的没有Ruby和Smalltalk纯粹。但是最新出现的用Java实现的语言Groovy解决了这些问题。
作为一种已经建立的新技术,Java显然综合了很多语言的特性,比如C 、C语言、Python等等。一些对于Java的评论认为Java的不变性在动摇,有些人认为Java只是一种“新的COBOL"语言。
语言问题
有些程序员不喜欢原始类型(primitive type)和类(class)的分离,尤其是那些曾经使用过Smalltalk和Ruby的程序员。他们会问:“这就是一切皆对象(object)?”
事实上,JAVA语言本身只是Smalltalk的一个不完整的代替品。JAVA的流行与SUN背后的支持分不开。
Java的代码相对于其他的代码来说过于冗长,这与它的轻便化声明相违背。
Java语言在单范例程序方面非常出色。历史上的Java则在这方面做的不好。
Java是一种单层继承的语言。这也导致了程序员在试图使用多重继承时候的不便,而很多语言都可以使用这个特性。但是Java可以使用接口类,把多重继承可能导致的风险减少到最小。
Java不支持运算符重载�馐俏朔乐乖怂惴卦厥沟么氲墓δ鼙涞牟磺逦5怯肳ava实现的语言Groovy可以进行运算符重载。
5.0版本增加了大量的基本类的支持,可以节省大量的额外编程工作。
过去Java对于文本的操作和其他语言,比如Perl和PHP相比差的较多,但Java在1.4版本时候引入了正则表达式。
准确地说,JAVA不是平台无关的,它本身就是一个平台。
类库问题
使用Swing平台编写的带有GUI(图形用户界面)的程序和其他原始程序非常不同。选用AWT工具包编写程序的程序员看到的都是原始界面,而且也无法获得先进的GUI编程支持,如果使用的话,就要提供每个平台上面所需的API,这将是一项庞大的工程。Swing则是完全用Java语言所写的程序,避免了界面元素重复的问题,只使用所有平台都支持的最基本的绘图机制。但是很多用户不知道如何在Java风格和Windows风格之间进行转换,结果造成了Java程序的界面在很多程序中非常特殊。苹果电脑已经提供了优化过的Java运行时程序,包含了Mac OS X的经典Aqua界面风格。
性能问题
由于Java编译器和虚拟机的不同对Java代码的性能影响比语言本身的影响大的多,所以统一讨论Java的程序的性能经常是有误导性的。据IBM的数据,在同样的硬件上2001年时的IBM JDK版本的性能是1996年的JDK版本的十倍左右。见IBM东京研究院的数据: http://www.is.titech.ac.jp/ppl2004/proceedings/ishizaki_slides.pdf 而即使是在同一时期,不同公司的JDK和JRE的性能也不一样,比如SUN、IBM、BEA等公司都有自己开发的JDK和JRE。
Java语言的一些特性不可避免的有额外的性能代价,例如数组范围检查、运行时类型检查等等。Java程序的性能还会因为不同的动态复杂性和垃圾处理机制使用的多少而各有不同。如果JVM的实现比较优化的话,那么这些功能甚至可以增加内存分配的性能。这和总是使用STL或者托管C 的程序的情况类似。
尽管如此,仍然有许多人认为Java的性能低。这部分归因于Sun公司最初的JVM实现使用未优化的解释机制来执行字节码。一些新版本的JVM使用 Just-In-Time(JIT)编译器,在加载字节码的时候将其编译成针对运行环境的本地代码来实现一些本地编译器的优化特性。Just-In- Time机制和本地编译的性能比较仍旧是一个有争议的话题。JIT编译需要很多时间,对于运行时间不长或者代码很多的大型程序并不适宜。但是不算JIT编译阶段的话,程序的运行性能在很多JVM下可以和本地编译的程序一争短长,甚至在一些计算比较密集的数值计算领域也是这样。目前,Java已经使用更先进的HotSpot技术来代替JIT技术,Java的性能有了更进一步的提升。另外,在使用-server选项运行java程序时,也可以对java进行更深入的优化,比如在运行时将调用较多的方法内联(inline)到程序中来提高运行速度,这就是所谓的“动态优化”,而本地编译器是无法做到这一点的;这也是一些java代码比对应用C/C 等语言编写的本地代码运行的更快的原因之一。微软的.NET平台也使用JIT编译器,所以也有类似问题。
Java的设计目的主要是安全性和可移植性,所以对于一些特性,比如对硬件架构和内存地址访问的直接访问都被去除了。如果需要间接调用这些底层功能的话,就需要使用JNI(Java本地接口)来调用本地代码,而间接访问意味着频繁调用这些特性时性能损失会很大,微软的.NET平台也有这样的问题。所以到目前为止,性能敏感的代码,例如驱动程序和3D视频游戏,还是大多使用本地编译,甚至直接以不直接支持面向对象的C语言或机器码编写。但最近已经有了许多用纯Java编写的3D游戏,其效果与用C语言编写的不相上下,例如“合金战士”(英文名:Chrome)。这主要是因为新版的Java 3D技术已经能像C 一样调用硬件加速,也就是使用显卡来加速,无论是C 还是Java语言写的3D游戏都是使用显卡及GPU来处理,从而使得CPU可以专注于其它方面的工作。
关于Java的性能,可以参看以下文章: http://www-128.ibm.com/developerworks/cn/java/j-jtp09275.html http://www.matrix.org.cn/thread.shtml?topicId=16092&forumId=18
Java运行时环境,即Java Runtime Environment,简称为JRE,是在任何平台上运行Java编写的程序都需要用到的软件。终端用户可以以软件或者插件方式得到和使用JRE。 Sun公司还发布了一个JRE的更复杂的版本,叫做JDK,即Java 2 开发包,里面包含了Java需要的编译器、参考文档和调试器等。
JRE的成分:
Java的类库,包含了编译Java程序所需要的最核心文件。
核心库文件,其中有
数据结构的库,包括列表、字典和树等
XML分析库
安全方面应用库
国际化和本地化应用库
综合库文件,包含了程序员和其他系统通信的功能文件。
JDBC,即Java数据库联通的API
JNDI,即Java命名和目录接口
RMI和CORBA用于重新分发软件
用户界面库文件,包含:
AWT,即抽象窗口开发包,提供了产生图形用户界面所需要的功能
Swing库
其他用于回访媒体文件、录音、截图的库
一个用于执行软件的Java虚拟机
插件,可以在浏览器里面使用
JWS,可以让终端用户连接到互联网
许可文件和文档
扩展和与Java程序设计语言紧密相关的架构(按字母排序)。
Groovy ,一种用纯Java实现的脚本语言,Python的强有力竞争者
JAIN (Java API for Integrated Networks)Java综合网络应用程序开发接口
JAI,(Java Advanced Imaging)Java进阶图像
JAXP, (Java API for XML Processing) Java XML 处理 API
Java EE(原名J2EE),Java平台企业版
Java ME(原名J2ME) ,Java平台微型版为PDA和智能手机开发的移动版本
Java SE(原名J2SE),Java平台标准版
JDBC ,(Java Database Connectivity)Java数据库联通
JDMK,(Java Dynamic Management Kit)Java动态管理开发包
JDO ,(Java Data Objects)Java数据对象
JJSF,Java服务器界面
JMF,(Java Media Framework) Java媒体框架
JMI,Java元数据接口
JML ,(Java Modeling Language)Java建模软件
JMX ,(Java Management Extensions)Java管理扩展
JNDI ,(Java Naming and Directory Interface)Java命名和目录接口
JNI ,Java原始界面
JOGL,使用OpenGL的低阶三位游戏开发接口
JSML ,(Java Speech API Markup Language)Java的语音和标记语言
JSP ,(JavaServer Pages)Java服务器页面
JSF ,(JavaServer Faces)
JXTA ,P2P虚拟网络协议
Java Card
Java3D ,用于三维游戏编程的高阶应用程序开发接口
JavaSpaces
Jini ,Java网络分布计算结构
Jiro
OSGi,(Dynamic Service Management and Remote Maintenance)动态服务管理和远程控制
Rhino, 用Java实现的JavaScript语言。
Swing, Java 的图像用户界面 API
SWT, Standard Widget Toolkit, 由IBM和Eclipse基金会主导开发的开源图像用户界面API
SuperWaba ,手持设备的虚拟机程序
总的来说java已经变得越来越庞大,或许是有些臃肿,在ROR等各种新的事物的出现的情况下,java或许将会将重点集中在企业级的开发上
1、JDBC(Java Database Connectivity)提供连接各种关系数据库的统一接口。
2、EJB(Enterprise JavaBeans)使得开发者方便地创建、部署和管理跨平台的基于组件的企业应用。
3、Java RMI(Java Remote Method Invocation)用来开发分布式Java应用程序。一个Java对象的方法能被远程Java虚拟机调用。这样,远程方法激活可以发生在对等的两端,也可以发生在客户端和服务器之间,只要双方的应用程序都是用Java写的。
4、Java IDL(Java Interface Definition Language) 提供与CORBA(Common Object Request Broker Architecture)的无缝的互操作性。这使得Java能集成异构的商务信息资源。
5、JNDI(Java Naming and Directory Interface)提供从Java平台到的统一的无缝的连接。这个接口屏蔽了企业网络所使用的各种命名和目录服务。
6、JMAPI(Java Management API)为异构网络上系统、网络和服务管理的开发提供一整套丰富的对象和方法。
7、JMS(Java Message Service)提供企业消息服务,如可靠的消息队列、发布和订阅通信、以及有关推拉(Push/Pull)技术的各个方面。
8、JTS(Java transaction Service)提供存取事务处理资源的开放标准,这些事务处理资源包括事务处理应用程序、事务处理管理及监控。
在Java技术中,值得关注的还有JavaBeans,它是一个开放的标准的组件体系结构,它独立于平台,但使用Java语言。一个JavaBean 是一个满足JavaBeans规范的Java类,通常定义了一个现实世界的事物或概念。一个JavaBean的主要特征包括属性、方法和事件。通常,在一个支持JavaBeans规范的开发环境(如Sun Java Studio 和IBM VisualAge for Java)中,可以可视地操作JavaBean,也可以使用JavaBean构造出新的JavaBean。JavaBean的优势还在于Java带来的可移植性。现在,EJB (Enterprise JavaBeans) 将JavaBean概念扩展到Java服务端组件体系结构,这个模型支持多层的分布式对象应用。除了JavaBeans,典型的组件体系结构还有DCOM 和CORBA,关于这些组件体系结构的深入讨论超出了本书的范围。
Spring Framework 【Java开源 J2EE框架】
Spring 是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring的架构基础是基于使用JavaBean属性的 Inversion of Control容器。然而,这仅仅是完整图景中的一部分:Spring在使用IoC容器作为构建完关注所有架构层的完整解决方案方面是独一无二的。 Spring提供了唯一的数据访问抽象,包括简单和有效率的JDBC框架,极大的改进了效率并且减少了可能的错误。Spring的数据访问架构还集成了 Hibernate和其他O/R mapping解决方案。Spring还提供了唯一的事务管理抽象,它能够在各种底层事务管理技术,例如JTA或者JDBC事务提供一个一致的编程模型。 Spring提供了一个用标准Java语言编写的AOP框架,它给POJOs提供了声明式的事务管理和其他企业事务--如果你需要--还能实现你自己的 aspects。这个框架足够强大,使得应用程序能够抛开EJB的复杂性,同时享受着和传统EJB相关的关键服务。Spring还提供了可以和IoC容器集成的强大而灵活的MVC Web框架。【SpringIDE:Eclipse平台下一个辅助开发插件】.
WebWork 【Java开源 Web框架】
WebWork 是由OpenSymphony组织开发的,致力于组件化和代码重用的拉出式MVC模式J2EE Web框架。WebWork目前最新版本是2.1,现在的WebWork2.x前身是Rickard Oberg开发的WebWork,但现在WebWork已经被拆分成了Xwork1和WebWork2两个项目。 Xwork简洁、灵活功能强大,它是一个标准的Command模式实现,并且完全从web层脱离出来。 Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL – the Object Graph Notation Language),IoC(Inversion of Control倒置控制)容器等。 WebWork2建立在Xwork之上,处理HTTP的响应和请求。WebWork2使用ServletDispatcher将HTTP请求的变成 Action(业务层Action类), session(会话)application(应用程序)范围的映射,request请求参数映射。WebWork2支持多视图表示,视图部分可以使用 JSP, Velocity, FreeMarker, JasperReports,XML等。在WebWork2.2中添加了对AJAX的支持,这支持是构建在DWR与Dojo这两个框架的基础之上. 【EclipseWork:用于WebWork辅助开发的一个Eclipse插件】
Struts 【Java开源 Web框架】
Struts 是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。由于Struts能充分满足应用开发的需求,简单易用,敏捷迅速,在过去的一年中颇受关注。Struts把Servlet、JSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间,所以说Struts是一个非常不错的应用框架。【StrutsIDE:用于Struts辅助开发的一个Eclipse插件】
Hibernate 【Java开源 持久层框架】
Hibernate 是一个�旁创氲亩韵蠊叵涤成淇蚣埽訵DBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序实用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。Eclipse平台下的Hibernate辅助开发工具:【Hibernate Synchronizer】【MiddlegenIDE】
Quartz 【Java开源 Job调度】
Quartz 是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 1.5.0。
Velocity 【Java开源 模板引擎】
Velocity 是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。当Velocity应用于web开发时,界面设计人员可以和java程序开发人员同步开发一个遵循 MVC架构的web站点,也就是说,页面设计人员可以只关注页面的显示效果,而由java程序开发人员关注业务逻辑编码。Velocity将java代码从web页面中分离出来,这样为web站点的长期维护提供了便利,同时也为我们在JSP和PHP之外又提供了一种可选的方案。 Velocity的能力远不止web站点开发这个领域,例如,它可以从模板(template)产生SQL和PostScript、XML,它也可以被当作一个独立工具来产生源代码和报告,或者作为其他系统的集成组件使用。Velocity也可以为Turbine web开发架构提供模板服务(template service)。Velocity Turbine提供一个模板服务的方式允许一个web应用以一个真正的MVC模型进行开发。 【VeloEclipse :Velocity在Eclipse平台下的一个辅助开发插件】
IBATIS 【Java开源 持久层框架】
使用ibatis 提供的ORM机制,对业务逻辑实现人员而言,面对的是纯粹的Java对象, 这一层与通过Hibernate 实现ORM 而言基本一致,而对于具体的数据操作,Hibernate 会自动生成SQL 语句,而ibatis 则要求开发者编写具体的SQL 语句。相对Hibernate等 “全自动”ORM机制而言,ibatis 以SQL开发的工作量和数据库移植性上的让步,为系统设计提供了更大�淖杂煽占洹W魑�“全自动”ORM 实现的一种有益补充,ibatis 的出现显得别具意义。
Compiere ERP&CRM 【Java开源ERP与CRM系统】
Compiere ERP&CRM为全球范围内的中小型企业提供综合型解决方案,覆盖从客户管理、供应链到财务管理的全部领域,支持多组织、多币种、多会计模式、多成本计算、多语种、多税制等国际化特性。易于安装、易于实施、易于使用。只需要短短几个小时,您就可以使用申购-采购-发票-付款、报价-订单-发票-收款、产品与定价、资产管理、客户关系、供应商关系、员工关系、经营业绩分析等强大功能了。
Roller Weblogger 【Java开源 Blog博客】
这个weblogging 设计得比较精巧,源代码是很好的学习资料。它支持weblogging应有的特性如:评论功能,所见即所得HTML编辑,TrackBack,提供页面模板,RSS syndication,blogroll管理和提供一个XML-RPC 接口。
Eclipse 【Java开源 开发工具】
Eclipse平台是IBM向开发源码社区捐赠的开发框架,它之所以出名并不是因为IBM宣称投入开发的资金总数 —4千万美元,而是因为如此巨大的投入所带来的成果:一个成熟的、精心设计的以及可扩展的体系结构。
XPlanner 【Java开源 项目管理】
XPlanner 一个基于Web的XP团队计划和跟踪工具。XP独特的开发概念如iteration、user stories等,XPlanner都提供了相对应的的管理工具,XPlanner支持XP开发流程,并解决利用XP思想来开发项目所碰到的问题。 XPlanner特点包括:简单的模型规划,虚拟笔记卡(Virtual note cards),iterations、user stories与工作记录的追踪,未完成stories将自动迭代,工作时间追踪,生成团队效率,个人工时报表,SOAP界面支持。
HSQLDB 【Java开源 DBMS数据库】
HSQLDB(Hypersonic SQL)是纯Java开发的关系型数据库,并提供JDBC驱动存取数据。支持ANSI-92 标准 SQL语法。而且他占的空间很小。大约只有160K,拥有快速的数据库引擎。
Liferay 【Java开源 Portal门户】
代表了完整的J2EE应用,使用了Web、EJB以及JMS等技术,特别是其前台界面部分使用Struts 框架技术,基于XML的portlet配置文件可以自由地动态扩展,使用了Web Services来支持一些远程信息的获取,使用 Apahce Lucene实现全文检�鞴δ堋�
JetSpeed 【Java开源 Portal门户】
Jetspeed 是一个开放源代码的企业信息门户(EIP)的实现,使用的技术是Java和XML。用户可以使用浏览器,支持WAP协议的手机或者其它的设备访问 Jetspeed架设的信息门户获取信息。Jetspeed扮演着信息集中器的角色,它能够把信息集中起来并且很容易地提供给用户。
JOnAS 【Java开源 J2EE服务器】
JOnAS 是一个开放源代码的J2EE实现,在ObjectWeb协会中开发。整合了Tomcat或Jetty成为它的Web容器,以确保符合Servlet 2.3和JSP 1.2规范。JOnAS服务器依赖或实现以下的Java API:JCA、JDBC、JTA 、JMS、JMX、JNDI、JAAS、JavaMail 。
JFox3.0 【Java开源 J2EE服务器】
JFox 是 Open Source Java EE Application Server,致力于提供轻量级的Java EE应用服务器,从3.0开始,JFox提供了一个支持模块化的MVC框架,以简化EJB以及Web应用的开发! 如果您正在寻找一个简单、轻量、高效、完善的Java EE开发平台,那么JFox正是您需要的。
【JAVA数组操作的常用工具类】
Java提供了的Arrays类里包含了一些static修饰方法可以直接操作数组,这个Arrays类里包含了提供了如下几个static修饰的方法(static修饰的方法可以直接通过类名调用):
int binarySearch(type[] a,type key):这个方法查询key元素值在a数组中出现的索引; 如果a数组不包含key元素值,则返回-1.调用该方法时要求数组中元素已经按升序排列,这样才能得到正确结果。
binarySearch(type[] a,int fromIndex,int toIndex,type key):这个方法与前一个方法类似,但它只搜索a数组中formIndex到toIndex索引的元素。调用该方法时要求数组中元素已经按升序排列,这样才能得到正确结果。
type[] copyOf(type[] original,int newLength):这个方法将会把original数组复制成一个新数组,其中length是新数组的长度。如果length小于original数组的长度,则新数组就是原数组的前面length个元素; 如果length大于original数组的长度,则新数组的前面元素就是原数组的所个元素,后面补充0(数值型)、false(布尔型)或者 null(引用型)。
type[] copyOfRange(type[] original,int from,int to):这个方法与前面方法相似,但这个方法只复制original数组的from索引到to索引的元素。
boolean equals(type[] a,type[] a2):如果a数组和a2数组的�ざ认嗟龋襫数组和a2数组的数组元素也一一相同,该方法将返回true.
void fill(type[] a,type val):该方法将会把a数组所有元素值都赋值为val.
void fill(type[] a,int fromIndex, int toIndex, type val):该方法与前一个方法的作用相同,区别只是该方法仅仅将a数组的fromIndex到toIndex索引的数组元素赋值为val.
void sort(type[] a):该方法对a数组的数组元素进行排序。
void sort(type[] a,int fromIndex,int toIndex):该方法与前一个方法相似,区别是该方法仅仅对fromIndex到toIndex索引的元素进行排序。
String toString(type[] a):该方法将会一个数组转换成一个字符串。该方法按顺序把多个数组元素连缀在一起,多个数组元素使用英文逗号(,)和空格隔开。(利用该方法可以很清楚地看到各数组元素)
下面程序示范了Arrays类的用法:
public class TestArrays
{
public static void main(String[] args)
{
//定义一个a数组
int[] a = new int[]{3, 4 , 5, 6};
//定义一个a2数组
int[] a2 = new int[]{3, 4 , 5, 6};
//a数组和a2数组的长度相等,每个元素依次相等,将输出true
System.out.println("a数组和a2数组是否相等:" Arrays.equals(a , a2));
//通过复制a数组,生成一个新的b数组
int[] b = Arrays.copyOf(a, 6);
System.out.println("a数组和b数组是否相等:" Arrays.equals(a , b));
//输出b数组的元素,将输出[3, 4, 5, 6, 0, 0]
System.out.println("b数组的元素为:" Arrays.toString(b));
//将b数组的第3个元素(包括)到第5个元素(不包括)赋为1
Arrays.fill(b , 2, 4 , 1); //fill方法可一次对多个数组元素进行批量赋值
//输出b数组的元素,将输出[3, 4, 1, 1, 0, 0]
System.out.println("b数组的元素为:" Arrays.toString(b));
//对b数组进行排序
Arrays.sort(b);
//输出b数组的元素,将输出[0, 0, 1, 1, 3, 4]
System.out.println("b数组的元素为:" Arrays.toString(b));
}
}
注意:Arrays类处于java.util包下,为了在程序中使用Arrays类,必须在程序中导入java.util.Arrays类。
除此之外,在System类里也包含了一个static void arraycopy(Object src,int srcPos,Object dest, int destPos,int length)方法,该方法可以将src数组里的元素值赋给dest数组的元素,其中srcPos指定从src数组的第几个元素开始赋值,length参数指定将src数组的多少个元素赋给dest数组的元素。
【浅析Hibernate下数据批量处理方法】
很多人都对Java在批量数据的处理方面是否是其合适的场所持有怀疑的念头,由此延伸,那么就会认为ORM可能也不是非凡适合数据的批量处理。其实,我想假如我们应用得当的话,完全可以消除ORM批量处理性能问题这方面的顾虑。下面以Hibernate为例来做为说明,假如我们真的不得不在 Java中使用Hibernate来对数据进行批量处理的话。 向数据库插入100 000条数据,用Hibernate可能像这样:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i ) {
Customer customer = new Customer(.....);
session.save(customer); }
tx.commit();
session.close();
大概在运行到第50 000条的时候,就会出现内存溢出而失败。这是Hibernate把最近插入的Customer都以session-level cache在内存做缓存,我们不要忘记Hiberante并没有限制first-level cache 的缓存大小。
◆持久对象实例被治理在事务结束时,此时Hibernate与数据库同步任何已经发生变 化的被治理的的对象。
◆Session实现了异步write-behind,它答应Hibernate显式地写操作的批处理。 这里,我给出Hibernate如何实现批量插入的方法:
首先,我们设置一个合理的JDBC批处理大小,hibernate.jdbc.batch_size 20。 然后在一定间隔对Session进行flush()和clear()。
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) {
//flush 插入数据和释放内存:
session.flush(); session.clear(); }
}
tx.commit();
session.close();
那么,关于怎样删除和更新数据呢?那好,在Hibernate2.1.6或者更后版本,scroll() 这个方法将是最好的途径:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
ScrollableResults customers = session.getNamedQuery("GetCustomers")
.scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
if ( count % 20 == 0 ) {
//flush 更新数据和释放内存:
session.flush(); session.clear(); } }
tx.commit(); session.close();
这种做法并不困难,也不算不优雅。请注重,假如Customer启用了second-level caching ,我们仍然会有一些内存治理的问题。原因就是对于用户的每一次插入和更新,Hibernate在事务处理结束后不得不通告second-level cache 。因此,我们在批处理情况下将要禁用用户使用缓存。
【如何把Java程序编译成.exe文件】
常常在网上看到有人询问:如何把 java 程序编译成 .exe 文件。通常回答只有两种,一种是制作一个可执行的 JAR 文件包,然后就可以像.chm 文档一样双击运行了;而另一种是使用 JET 来进行 编译。但是 JET 是要用钱买的,而且据说 JET 也不是能把所有的 Java 程序都编译成执行文件,性能也要打些折扣。所以,使用制作可执行 JAR 文件包的方法就是最佳选择了,何况它还能保持 Java 的跨平台特性。
下面就来看看什么是 JAR 文件包吧:
1. JAR 文件包
JAR 文件就是 Java Archive File,顾名思意,它的应�檬怯� Java 息息相关的,是 Java 的一种文档格式。JAR 文件非常类似 ZIP 文件——准确的说,它就是 ZIP 文件,所以叫它文件包。JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中,包含了一个 META-INF/MANIFEST.MF 文件,这个文件是在生成 JAR 文件的时候自动创建的。举个例子,如果我们具有如下目录结构的一些文件:
==
`-- test
`-- Test.class
把它压缩成 ZIP 文件 test.zip,则这个 ZIP 文件的内部目录结构为:
test.zip
`-- test
`-- Test.class
如果我们使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar,则这个 JAR 文件的内部目录结构为:
test.jar
|-- META-INF
| `-- MANIFEST.MF
`-- test
`--Test.class
2. 创建可执行的 JAR 文件包
制作一个可执行的 JAR 文件包来发布你的程序是 JAR 文件包最典型的用法。
Java 程序是由若干个 .class 文件组成的。这些 .class 文件必�敫菟撬舻陌煌旨斗帜柯即娣牛辉诵星靶枰阉杏玫降陌母柯贾付ǜ� CLASSPATH 环境变量或者 java 命令的 -cp 参数;运行时还要到控制台下去使用 java 命令来运行,如果需要直接双击运行必须写 Windows 的批处理文件 (.bat) 或者 Linux 的 Shell 程序。因此,许多人说,Java 是一种方便开发者苦了用户的程序设计语言。
其实不然,如果开发者能够制作一个可执行的 JAR 文件包交给用户,那么用户使用起来就方便了。在 Windows 下安装 JRE (Java Runtime Environment) 的时候,安装文件会将 .jar 文件映射给 javaw.exe 打开。那么,对于一个可执行的 JAR 文件包,用户只需要双击它就可以运行程序了,和阅读 .chm 文档一样方便 (.chm 文档默认是由 hh.exe 打开的)。那么,现在的关键,就是如何来创建这个可执行的 JAR 文件包。
创建可执行的 JAR 文件包,需要使用带 cvfm 参数的 jar 命令,同样以上述 test 目录为例,命令如下:
jar cvfm test.jar manifest.mf test
这里 test.jar 和 manifest.mf 两个文件,分别是对应的参数 f 和 m,其重头戏在 manifest.mf。因为要创建可执行的 JAR 文件包,光靠�付ㄒ桓� manifest.mf 文件是不够的,因为 MANIFEST 是 JAR 文件包的特征,可执行的 JAR 文件包和不可执行的 JAR 文件包都包含 MANIFEST。关键在于可执行 JAR 文件包的 MANIFEST,其内容包含了 Main-Class 一项。这在 MANIFEST 中书写格式如下:
Main-Class: 可执行主类全名(包含包名)
例如,假设上例中的 Test.class 是属于 test 包的,而且是可执行的类 (定义了 public static void main(String[]) 方法),那么这个 manifest.mf 可以编辑如下:
Main-Class: test.Test <回车>
这个 manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且该行以一个回车符结束即可。创建了 manifest.mf 文件之后,我们的目录结构变为:
==
|-- test
| `-- Test.class
`-- manifest.mf
这时候,需要到 test 目录的上级目录中去使用 jar 命令来创建 JAR 文件包。也就是在目录树中使用“==”表示的那个目录中,使用如下命令:
jar cvfm test.jar manifest.mf test
之后在“==”目录中创建了 test.jar,这个 test.jar 就是执行的 JAR 文件包。运行时只需要使用 java -jar test.jar 命令即可。
需要注意的是,创建的 JAR 文件包中需要包含完整的、与 Java 程序的包结构对应的目录结构,就像上例一样。而 Main-Class 指定的类,也必须是完整的、包含包路径的类名,如上例的 test.Test;而且在没有打成 JAR 文件包之前可以使用 java <类名> 来运行这个类,即在上例中 java test.Test 是可以正确运行的 (当然要在 CLASSPATH 正确的情况下)。
【如何使用Java编写多线程程序】
线程呢可以看作单独地占有CPU时间来执行相应的代码的。当然一个程序可以是多线程的,多线程的各个线程看上去像是并行地独自完成各自的工作,就像一台一台计算机上运行着多个处理机一样。
1、什么是线程
线程呢可以看作单独地占有CPU时间来执行相应的代码的。当然一个程序可以是多线程的,多线程的各个线程看上去像是并行地独自完成各自的工作,就像一台一台计算机上运行着多个处理机一样。在多处理机计算机上实现多线程时,它们确实可以并行工作,而且采用适当的分时策略可以大大提高程序运行的效率。
2、为什么要使用多线程
顺序执行程序和采用多线程并行执行程序相比,效率是可以大大地提高。
3、java中是如何实现多线程
在java语言中的线程系统是java语言自建的,因为java中有专门的支持多线程的API库,所以很容易写一个支持线程的程序。在使用java创建线程的时候,可以生成一个Thread类或者他的子类对象,并给这个对象发送start()消息(程序可以向任何一个派生自 Runnable 接口的类对象发送 start() 消息的),这样一来程序会一直执行,直到run返回为止,此时该线程就停止了。
在这里我们用多线程中最典型的例子,生产者与消费者问题。在这个例子里面我们定义了生产者Producer,消费者Consumer和仓库Warehouse三个类,在整个程序的生命周期里,生产者随机地制造出产品放到仓库中,消费者也是随即地从仓库中取出产品。
import exception.ProducerConsumerException;
/**
* Consumer.java
* Consumer
* By: Jiabo
* Date: Mar 21, 2004
* Time: 2:47:58 PM
*/
public class Consumer extends Thread {
private Warehouse warehouse;
private String id;
public Consumer(Warehouse warehouse, String id) {
this.warehouse = warehouse;
this.id = id;
}
public void run() {
int tmp = (int) Math.random() * 10;
try {
warehouse.get(tmp);
System.out.println("Consumer # " this.id " get " tmp);
} catch (ProducerConsumerException e) {
e.printStackTrace();
}
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
在这个类中,值得注意的一点是run方法中必须使用try-catch,因为,消费者从仓库中取东西时有可能诸如仓库中的储量不够得异常,在消费者里面也是一样,只不过异常变为仓库已满。
import exception.*;
/**
* Producer.java
* Producer
* By: Jiabo
* Date: Mar 21, 2004
* Time: 2:47:45 PM
*/
public class Producer extends Thread {
private Warehouse warehouse;
private String id;
public Producer(Warehouse warehouse, String id) {
this.warehouse = warehouse;
this.id = id;
}
public void run() {
int tmp = (int) Math.random() * 10;
if (tmp != 0) {
try {
warehouse.put(tmp);
System.out.println("Consumer # " this.id " put " tmp);
} catch (ProducerConsumerException e) {
e.printStackTrace();
}
}
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
最重要的一部分在Warehouse类,如上所说为了保证get何set的原子性,在这里使用了synchronized关键字,并且在操作时抛出了可能跑出的异常。
import exception.*;
/**
* Warehouse
* By: Jiabo
* Date: Mar 21, 2004
* Time: 2:48:10 PM
*/
public class Warehouse {
// max capability of the warehouse
private int MAX;
private int contents;
// init with max capacity
public Warehouse(int max) {
this.MAX = max;
this.contents = 0;
}
public synchronized void get(int amount) throws ProducerConsumerException {
// the amount you want to get is bigger than the contends that the warehouse stores
if (amount > this.contents) {
throw new NotEnoughGoodsException();
}
amount -= contents;
}
public synchronized void put(int amount) throws ProducerConsumerException {
// the amount you want to put is out of the capability of the warehouse
if (amount > (this.MAX - this.contents)) {
throw new WarehouseFullException();
} else if (this.contents == 0) {
// warehouse is empty
throw new WarehouseEmptyException();
}
amount = contents;
}
}