汉化软件的几种方法
现在的汉化软件和汉化补丁是越来越多了,你肯定也想自己汉化一些软件试试吧。肯定你又会以为这是很麻烦或者很难的事情,只有高手才会做,其实并不是这样,你也完全可以自己汉化一些软件,有些方法还是很简单的,不需要设计到编程的知识。不相信,不相信就听我下面给你介绍三种方法,保证你看完后,你也能汉化一些平常见的软件了。(哎,我把胸口都拍痛了)
第一种方法:
直接修改源二进制的代码,不要紧张,也不要被吓倒,很简单的。这里需要用到一个二进制代码查看器,如果你没有,我推荐你用一个名字为Ultra Edit的编辑器,相信你已经用过这个编辑器,(没有用过?没有用过也不要紧,往下看!)这个软件比Windows自带的记事本的功能强大许多,用法上倒没有什么复杂的地方,至于具体好在哪里,我就不说了,呵呵,可以自己看看专门介绍它的软件。比如说,我们要汉化一个英文软件,就比如汉化Turbo C吧,把菜单中的“File”汉化成中文的“文件”。用此编辑器打开TC的可执行文件tc.exe,当然啦,在做这之前,你要先备份好你要操作的文件,免得到时候没有汉化成功,倒弄坏了文件,回不来了。打开以后,就可以看到它的原二进制代码文件。这时候,你选择查找功能。从二进制中查找到“file”,找倒后,将它修改成“文件”,然后关闭,执行这个文件,看看是不是已经汉化了。当然,这次你找到的不一定就是你要汉化的菜单,不一定会成功。这就需要反复实验了。
这类方法比较累,并且也不一定准确。这种方法现在也基本没有人使用了。
第二种方法:
这种方法是比较简单的一种,但这种方法只能适用于带有语言选择的软件,这样的软件不是很多,只能是偶尔逮着一个,方法很简单,找到它的语言选择文件夹,里面会有各个语言的选择文件,比如FlashGet的language目录下面有三十几个国家的语言版本。这里面已经有中国的了,假如你想新建一个的话,则也可以用记事本按照它的格式建立一个语言版本。提供给大家的一个思路就是将它的原语言版本复制一个后,用记事本打开,然后按照它的格式修改,将它的内容换成你的内容,注意要一行一行地换,如果你把两行弄到一行去了,这就可能会产生错误了。换完后,你也就已经汉化了这个软件了。
这种方法用途不是很大,一般的多语言版本的程序都有中文的语言版本,不需要你的汉化了。
第三种方法:
好的方法当然留在最后讲,这种方法是汉化者们经常用的一种,那就是修改文件的资源文件。我们知道,用VC和DEPHI编译成的软件都有资源文件。高手呢,就是打开VC,直接修改内核,而我们嘛,就不必掌握这些复杂的方法了,这里给大家介绍一个简单的方法,用eXeScope软件修改,特别的简单。(没有听说过?那没有关系,网络学院里面有教程的)像这类的软件还有很多,不过这个历史比较长,使用也非常的简单。就给大家介绍它了。比如我们要汉化OICQ,当然这本来就是中文版了,不需要汉化,没有关系,这里只是给大家演示一下汉化的过程而已。(要详细了解eXeScope,有专门的文章介绍)
启动eXeScope,选择文件菜单,再选择打开,打开QQ的可执行文件。这时候左边的资源栏目里面就会出现该文件的全部资源,包括什么头部文件,导入的动态连接库,以及它所用到的资源文件。而资源文件,就是我们汉化时要终点修改的内容。从资源中间选择菜单(一般汉化就是汉化菜单和对话框)当菜单栏目展开以后,你可以看到右边的栏目里面有该菜单的全部内容了,这时候,只需要你自己改动就可以了,将各个菜单的名字都改成你所要的名字就可以了,比如说要是“File”,你讲它改成“文件”就可以了。注意的是“&”这个符号,编过程序的人应该知道,这个是不能动的,如果你不知道意思,只要记住,这个符号的意义是:这个符号后面紧跟的字母是这个菜单的快捷键,就像记事本的菜单“文件(F)”那么这个F就是快捷键,最好不要删除掉。比如说有个菜单为:“&Edit”,那么你换的时候,就不能把快捷键去掉,把它写成“(&E)编辑”,就可以了。这是一个要注意的地方。
汉化还包括汉化对话框,同样从左边资源树中点开对话框,从右边就可以看到各个具体的标签与空间的名称了,只需要将各控件显示的文字改过来就可以了,按下F8键,就可以可视化地进行修改了。将修改后的文件保存就可以了(在编辑菜单中有“保存修改”项)。你运行一下你刚才修改过的文件,可以看到修改后的效果了。
当然啦,eXeScope的功能远不止这一些,但汉化是非常好的一个功能。*_*
汉化软件要注意的几点是:
1. 汉化前的备份,如果失败,还可以还原回来。切记!
2. 汉化软件的时候,最好就不要做别的事情了,因为我们都是刚学汉化的人,有可能某个错误,而使软件运行后死机,如果你别的文档没有存盘,可不要说我没有预先通知你了。呵呵。
3. 习惯问题,为了软件的通用性,一般都把“File”汉化成“文件”,把“Edit”汉化成“编辑”,最好遵守一下这个规则。
4. 软件版权问题,还是尊纪守法的好,打官司了,不要说是我害了你哟。
希望上面的汉化方法会对大家有一点帮助,谢谢。
2009年考研时间表
2008年
1月 搜集考研信息,听免费讲座。
2月-3月 确定考研目标,听考研形势的讲座。选择专业,全面了解所报专业的信息。准备复习。
4月-5月 第一轮复习,可以报一个基础班,特别是数学班和英语班。不要急于做模拟试题,着重于基础的复习。
6月 全面关注考研公共课的考试大纲,购买最新的辅导用书,准备暑期复习。
7月-8月 制定一个全面复习计划,开始第二轮复习。可以参加一个有权威性的辅导班,有选择地做一些必要的题目。
9月 关注各招生单位的招生简章和专业计划,购买专业课辅导用书,联系导师,获取专业课考试信息。
10月 确定十一黄金周复习计划,对前两个阶段的复习进行总结。同时,开始专业课的复习,可报一个长期班系统复习。
11月10-14日 研究生考试报名工作开始,报名、填报专愿。
11月中下旬 第三轮复习阶段开始,政治、英语、数学、专业课的冲刺复习,购买辅导冲刺的内部资料。冲刺班报名。
12-1月 进行模拟实训,报一个冲刺班,做考前整理。
2009年
1月中下旬 调整心态、准备考试。熟悉考试环境。
2月 放松心情,查询初试成绩。
3月 关注复试分数线。
4月 准备复试,联系招生单位。
5月 关注复试成绩。
6月 关注录取通知书。
9月 报到。
JSP开发工具的选择(3)
Jrun
Allaire公司的JRun是一个具有最广阔适用性的Java引擎,用于开发及实施由Java Servlets(JSP)和JavaServer Pages编写的服务器端Java应用。JRun是第一个完全支持JSP 1.0 规格书的商业化产品,全球有超过80,000名开发人员使用JRun在他们已有的Web服务器上添加服务器端Java的功能。其中Web服务器包括了Microsoft IIS,Netscape Enterprise Server,Apache等。
JRun是开发实施服务器端Java的先进引擎。如果你希望在你的Web应用中添加服务器端Java功能,那么JRun将成为你的正确选择。
你可以使用JRun运行Java Servlets -- 运行Java Servlets有2种方法,扩展你的Web 服务器或是使用内置JRun的Web服务器。通过在整个环境中将servlets作为一个可扩展的,完整定义过的Java部件模型来使用,你就可以更加方便、快速的开发、实施复杂的应用,维护起来也更加经济。
JRun目前有3个版本,它是第一个支持JavaServer Pages(JSP)规格书1.0的商业化产品。JSP是一种强大的服务器端技术,它是用于创建复杂Web应用的一整套快速应用开发系统。
JRun可以使你开始开发并测试Java应用。它最多接受5个并发的连接并且:
包括全部Java Servlet API
支持JavaServer Pages(JSP)
支持所有主要的Web servers和计算机平台
JRun Pro能够在生产环境下承受大访问量的负载,帮助你实施应用、服务或Web站点(包括内联网)。JRun Pro 支持无限量并发式连接运行多个Java虚拟机,包括多个并发的Java虚拟机(JVM)。
提供一个远程管理applet以及一个远程可再分布式的管理applet。JRun Pro Unlimited包括了所有JRun Pro的功能,除次以外,还可以运行无限量的,并发的JVM。
Allaire JRun一个适用性广泛的引擎,用于开发及实施使用JavaServer Pages(JSP)及Java Servlets开发成的Java应用。利用Java技术,你可以在现有的Web server之上添加服务器端Java功能,JRun所支持的Web服务器包括Microsoft IIS和Personal Web Server,Netscape的Enterprise或FastTrack,Apache, O´Reilly公司的WebSite以及StarNine公司的WebSTAR。
JRun依靠其内置的JRun Web Server可以单独运行。使用服务器端Java,用户可以开发出复杂的商业应用系统。最重要的一点是,由于servlets的平台独立性,以及更加简单的开发、更快速的实施、更经济的维护成本,它是CGI(Common Gateway Interface)或Perl scripts的极佳的替代产品。
主要功能:
JRun 2.3可以全面实施最新Java Servlet API。同时,JRun还可以利用Java Web Server中的许多先进功能。一些JRun2.3的重要功能列举如下:
? 全面支持Java Servlet API version2.1
? 全面支持JavaServer Pages(JSP)1.0 draft spec
? 动态 taglets
? 提供现成模板
? 页面编辑
? dynamic-servlet重载 ? Servlet-initialization属性
? Servlet 串联及过滤
? 多个宿主(虚拟主机)支持 ? <servlet> tag支持
? 任务跟踪
? 安装向导
? 复杂的Swing-based管理应用
? 100%纯粹Java以及完全跨平台
? 可运行于任何Java Virtual Machine ? 最多运行于5台Java Virtual machine(JRun Pro) ? 可运行于无限多个Java Virtual machine(JRun Pro Unlimited)
? 远程管理(JRun Pro)
技术优势
Java Servlets是由Java Servlet API--Java平台的一部分,编写成的独立跨平台的服务器端程序。Java Servlets拥有“一次编写,随处运行”的强大力量,同时具备网络传递安全性以及对服务器端应用提供了良好伸缩性。Servlets可以替代传统的由Perl,C/C++或其他语言编写的服务器端应用及扩展程序。用户将Servlet作为一个可扩展的,定义良好的跨平台环境来运用,能够更加方便的开发、快速实施服务器端复杂的应用,并节省维护成本。(可以在廉价的Windows NT机器上部署servlets)
在现有的成熟的服务器技术,例如Web 服务器中结合servlets,当编写复杂的应用时,就可以避免特定服务器配置中平台的局限性及复杂性。使用Servlets,开发人员就不必再顾虑服务器的内部工作方式。servlets API内在的classes能够控制Form 数据,server header,cookies等一切物质。
现有服务器端应用和servlets的最大区别就是性能。在服务器中运行一个独立的JVM,servlet一旦被呼叫即被载入。直到servlets改变时才会被再次载入。无须重新启动服务器或应用,一个被修改过的servlet就可以被自动加载。由于servlet永远驻留在内存中,它的加载速度极快。静态或永久信息可以通过多个激活的servlet 达到共享,并且允许多个用户之间共享信息。Servelet也是模块化的,它们即可以单独的完成一项特定任务,同时也可以结合在一起工作。 servlets彼此可以互相对话。
JRun支持的Web Server? Microsoft´s Internet Information Server (IIS) and Personal Web Server (PWS) ? Netscape´s Enterprise and FastTrack Servers
? Apache ? O´Reilly´s WebSite Pro
? StarNine´s WebSTAR
? Novell Netware 5 (Novonyx)
JSP开发工具的选择(2)
Jbuiler
JBuilder 软件的目标定位是代码开发人员而不是高级设计人员,所以JBuilder中包含了大量的向导程序和其他针对中间层的快速开发工具。JBuilder性能稳定、使用方便,特别适用于创建Java 组件。此外该软件还提供了很多JSP功能。
JBuilder本身通过内置的Java和Swing(Java的GUI程序框架)技术支持跨平台的软件开发:它可以运行在Windows、Linux和Solaris操作系统之上,操作界面和工具完全一致。这种所谓的“all-Java”策略意味着软件运行JBuilder的内存不会太多。128MB是系统最小需求,我们推荐装备256MB内存以获得更好的性能。
和早期版本一样,JBuilder 4 IDE设计得更富于效率性和功能性。你可以在同一开发环境下很方便地查看Java、 HTML和JSP文件、建立Sun推出的新型JDK 1.3 HotSpot虚拟机(这种新型虚拟机优化了Java代码)。JBuilder具有了相当出色的响应界面。在多种令人注目的特性之后,我们特别喜欢方便的自动补充功能(auto-completion wizardry),该功能不仅支持即时帮助还支持键入JBuilder Enterprise版更提供了对Enterprise Java-Bean组件开发的支持。在Jbuilder中,可以更容易的创建(create)配置(deploy)企业JavaBean。提供了一系列的向导来进行创建,处理,配置企业JavaBean的流程。把IAS的配置描述编辑器集成到Jbuilder的开发环境中(不过,并没有把IAS4.1内置到Jbuilder4中,需要另外下载安装)。Jbuilder还支持BEA的WebLogic Server 5.1。
Jbuider4的一个新的特性就是EJB Group功能。每一个EJB Group都代表了一个可配置的JAR文件。通过EJB Group,可以对已有的EJB在EJB Group之间进行移植。一个project工程中可以有多个EJB Group。
Entity Bean Modeler可以创建一个映射到现存表的实体Entity Bean。可以产生所有必须的Java代码,更新EJBGroup中配置描述。
在Jbuilder中,可以:
1、用EJB 向导创建Session Bean和Entity Bean
2、用Entity Bean Modeler将Entity Bean映射到现有的table中。
3、通过EJB Group向导创建EJB Group。这样,就可以在一个应用程序里面放多个的Enterprise JavaBean。
4、可以将一个Enterprise JavaBean从一个EJB Group移植到另一个EJB Group
5、一个应用程序里面可以有多个的EJB Group。
6、用Make和Rebuild就可以自动的创建可配置的JAR文件。
7、可以在node viewer中查看JAR的内容。
8、通过Test Client wizard可以在本地的容器或者与EJB1.1兼容的应用服务器中测试Enterprise JavaBean。
9、运行或调式EJB的时候会自动的配置EJB。 JBuilder支持EJB 1.1,由于采用了灵活的XML解决方案,软件还准备支持EJB 2.0。目前用户可以自动地生成基于后端数据库表的EJB Java类。JBuilder同时还简化了EJB的自动部署功能。此外它还支持CORBA,相应的向导程序有助于用户全面地管理IDL(分布应用程序所必需的接口定义语言interface definition language)和控制远程对象。
JBuilder的本地开发依赖于软件中所包含的轻度Java数据库,这种数据库被叫做JDataStore。软件包含的JDataStore Explorer和JDBC Explorer 可以让用户管理JDataStore和任何遵守JDBC标准的数据源。增强了数据库工具功能,也更加容易使用了。
JdataStore:更快,更灵活了。其底层的连接池的性能有显著的提高。Jbuilder4对支持JTA的支持使JdataStore连接可以利用标准的XA接口参与分布式的事务处理。
JdataStore Explorer可以用图形化的界面创建和操作table。可以创建表的索引。现在JdataStore支持交叉连接,内连接,外连接,左,右连接。
在现在的发行版本中,是通过“natural”或 “using”关键字来指定连接的域。JdataStore现在也支持SQL-92的连接序列,支持分级的子查询。
JBuilder 处理同时也建立在中间层的EJB之上的事务可谓得心应手。尽管用JBuilder创建默认的JSP非常容易,你还是可以用基本的HTML表单而不是WebSphere Studio中的工具来完成该项工作。JSP本身对JBuilder而言还是一种很新颖的技术,你可以用简单的JavaBean 技术来管理JavaServer Page。
JBuilder 4 Enterprise包含了300多种组件,其中,大多数组件都属于JavaBean和Swing控件,这对建立客户端小程序和独立运行的Java应用程序是很有用的。此外软件还包括16种名为InternetBeans的特殊控件。不过,这些控件都是专用于JSP和servlet的。这些组件封装了Web表单中采用的控件,其范围不仅包括了简单的按钮也包括表这样的高级特性。
这些对象都将HTML和后台的JSP/servlet代码分割开来,这样Web设计人员在无须Java程序员修改底层代码的情况下就可以单独修改HTML。这种解决方案对我们很有吸引力,有了它也就拥有了未来扩展的足够余地。事实上,同类组件还可以让用户生成用于无线设备的WML代码,你只需要将模版改为WML,这些InternetBeans就会动态地填充用于WAP设备的数据。在真实的应用环境中,我们完全可以采用自己喜欢的HTML工具从事HTML编辑工作。Jbuilder支持Web应用程序的开发,增加了对XML的支持,提供了更好的Servlet和JSP的支持。通过InternetBeans Express和一些组件,能够在Java和html之间进行无缝数据转换。 Jbuilder内置了Tomcat3.1,可以动态的调试Servlet和JSP程序。 每一个Servlet都有一个别名(Servlet-name)和init()初始化函数的参数,能够离开SHTML独立执行。 Jbuilder提供了增强的JSP支持,很容易的就可以直接调试JSP源代码。提供了XML的支持。能够简单快速的编写XML文件。XML关键字的高亮度显示很容易的对整个XML文件的结构了如指掌。 通过InternetBeans Express控件,可以动态的产生WEB页面的内容。
JBuilder还针对团队开发推出了CVS版本控制功能,该技术已经被我们的程序员用于建立测试应用程序。采用CVS,开发队伍就可以方便地跟踪项目开发全过程了。
工程文件(*.jpr和*.jpx)可以分为两部分,private和shared。Windows, watch, breakpoints保存在private私有部分,而libraries和编译选项保存在公有shared部分。
版本追踪和控制:Jbuilder4对每一个版本都提供更改的支持。要查看一个文件的版本信息,单击底部的histroy标签,里面有每个文件的历史修改记录。Jbuilder自动的保持着文件的备份。可以设定备份的个数。Histroy页面就用这些备份来管理着历史的修改记录。可以访问上一个版本文件。也可以查看两个版本之间做了哪些修改。Jbuilder4的企业版还提供了CVS(Concurrent Versions System并发版本系统)JBuilder漂亮的IDE环境充分展示了Inprise和Borland开发人员的一贯喜好,JBuilder将继续获得Java程序员的青睐。这一装备了获得好评的帮助程序和服务器端EJB工具的软件在总体水准上是一款相当成熟和优秀的Java开发环境。但是Jbuilder4也还是它的不足:
1. 和中文系统有冲突。至少和Win2000的中文系统有冲突,它的菜单总是触发中文输入条。
2. 速度不够快。还是要求高配置。
3. 由于需要Application Server,而且要求装在同一机器上,开发EJB要求的硬件环境太高
4. 缺乏WebGain Studio里的一些有用工具,如StructureBuilder。缺乏和Rose等工具的高效集成
5. 支持的工具,如版本控制的工具比较少
JSP开发工具的选择(1)
IBM VisualAge for Java
IBM的Web开发产品可谓同类之中的庞然大物:体积庞大,功能众多;使用对象是整个开发团队;而设计目标则是搞定视野里能看到的一切!
IBM WebSphere软件平台(全套的集成电子商务解决方案,包括VisualAge for Java 1.2版)是电子商务应用构架的关键部分,该构架是IBM在同一编程模型上开发的统一的端对端体系结构。作为公共编程模型,EJB规范得到了行业范围内的广泛支持,它也是电子商务应用构架的集成部件模型。VisualAge for Java是提供了向导功能的第一个Java IDE,它可以生成大量的EJB基础结构代码,从而简化了EJB开发过程。另外,对话和实体beans的创建向导、把beans映射到现有关系数据存储以及先进的测试环境极大地减少了创建、测试和部署EJB所花的时间。
VisualAge for Java持续性工具能让开发人员把EJB映射到现有的关系数据库结构。利用对对话和实体beans(CMP)的支持,开发人员能从现有的数据库表生成EJB或从现有的EJB生成数据库结构。VisualAge for Java还能提供把对象模型映射到数据模型的手段,从而把数据库管理员和Java开发人员联系在一起。另外,VisualAge for Java 3.5版还支持IBM DB2 S/390和Sybase,以及支持IBM DB2通用数据库和Oracle。
如果在VisualAge for Java中主机运行IBM WebSphere测试环境(WTE),开发人员还能在把EJB和servlet部署到远程服务器前对它们进行预测试。由于开发人员能启动和停止服务器和应用程序,并能在VisualAge for Java IDE中任意改变应用,所以开发人员不必远程部署和测试代码,从而节省了大量时间。
生成测试客户机能让开发人员测试他们服务器端的EJB而无须编写一个用户界面或等待图形制作人员给出的强制性界面。另外,当用户界面完成时,它还能作为一个测试工具,决定问题是存在于应用程序的客户机部分还是服务器部分。
VisualAge for Java还简化了把EJB添加到现有应用程序中的过程。通过生成AccessBeans,VisualAge for Java隐藏了EJB的远程和本地接口并把它融合到JavaBeans编程模型中。这提供了到EJB的简化的JavaBeans接口,简化了企业beans与servlet或JSP间的编程接口,得到了所有Java开发人员的普遍认可。另外,AccessBeans引入了先进的EJB属性本地缓存功能,减少了远程调用的次数,提供了对EJB的快速访问能力。
现在,IBM为建设Web站点所推出的WebSphere Studio Advanced Edition及其包含的VisualAge for Java Professional Edition软件已全面转向以Java为中心,这样,Java开发人员对WebSphere全套工具的感觉或许会好了许多。Studio所提供的工具有:Web站点管理、快速开发 JDBC页向导程序、HTML编辑器和HTML语法检查等。这确实是个不错的HTML站点页面编辑环境。Studio和VisualAge集成度很高,菜单中提供了在两种软件包之间快速移动代码的选项。这就让使用Studio的Web页面设计人员和使用VisualAge的Java程序员可以相互交换文件、协同工作。
Studio提供了建立Java Server Page的完整前端开发环境。许多向导程序可以帮助用户以更快捷、更难以出错的方式实现特定的开发任务。比如说,SQL向导程序就可以让我们在测试所用的Oracle 8i 数据库中浏览各表、执行多种SQL任务(比如增加连接、限制带约束的查询以及在存储结果之前查看查询结果等等)。
IBM新增加的标签可以让JSP访问数据的工作变得更加方便,比如 <tsx:repeat> 标签就负责遍历查询中各行而无须增加处理数据库的Java代码。这些标签表明IBM正在逐步采用以标签为中心的数据访问解决方案(就象ColdFusion所采用的方案那样)。
在编辑页面的时候,我们面前有好几个工具可供选择,包括一个图形界面的所见即所得页面编辑器、一个可以显示页面层次结构的纲要视图以及HTML源代码编辑视图。不过我们发现这些编辑工具之间存在整合方面的一些问题,相比之下还是Dreamweaver 或者ColdFusion做得好一些。
Studio提供了代码补充特性,但是很令人失望??该特性只能用于VoiceXML文件,不能用于 HTML或者JSP文件。不过,它对VoiceXML和WML这样的Web技术,其支持力度还是处于市场领先的地位。
Studio和VisualAge都包括了JavaServer Page调试器。因为JavaServer Page在执行前采用预编译方式运行,所以IBM为其预编译表单所提供的页面调试方式值得关注,这种方式并没有在服务器上实际运行Java 源代码表单。有了VisualAge的Java Server Page调试器,我们就可以在页面调试的时候从输出窗口中查看HTML显示。不过在编译JavaServer Page之后,编译器的输出却只列出错误结果而不自动地标记那些出现错误的源代码。
VisualAge for Java支持团队开发,内置的代码库可以自动地根据我们做出改动而修改程序代码,这样我们就可以很方便地将目前代码和早期版本做出比较。Studio本身并不提供源代码版本管理的支持,它只是包含了一个内置文件锁定系统,当我们编辑项目文件的时候可以防止其他人对这些文件的错误修改。软件还支持诸如Microsoft Visual SourceSafe这样的第三方源代码控制系统。因为Studio对多服务器和多阶段项目部署都提供了完整的可定置支持,所以开发完应用程序之后,在测试服务器和产品服务器上的应用部署都很快。
WebSphere Studio Advanced Edition 3.5 和VisualAge for Java Enterprise Edition 3.5对开发团队而言都是可供选择的优秀开发环境,他们提供了对单一项目下多个开发人员的内置支持。但是这两套产品的界面和编辑缺陷使得IBM产品成为最佳开发包的努力功亏一篑。
Oracle、MySQL和PostgreSQL的功能比较
本文在安全、触发器、视图、物化视图和存储过程方面对Oracle、MySQL和PostgreSQL进行了比较……
【IT专家网独家】随着现代数据库中可以被使用的功能的蓬勃发展,已经很难将它们从数据库中分离出来。例如在Oracle中有许多高级的数据仓库功能,这些功能你可能永远都不需要。此外,还可能有一些其它的功能例如你不能没有的ACID遵从性事务。我们将介绍主要的功能,例如存储过程、视图、快照、表数据类型、事务等等。我们将对比Postgresql、MySQL和Oracle,看哪些能够满足你的需要。
存储过程
有人支持、也有人反对在数据库中保存应用程序代码。在这个问题上我保持基本公正的态度,所以我会试着从双方来讨论。当你开始将应用程序代码放置到数据库中时,你就变得极其不轻便。在你将你的应用转向另一个数据库时,这个代码将会被重写。但是它放置在数据库上意味着它还可以充分利用和紧密连接这个引擎。在某些情况下在数据库中存储代码可以显著的提高速度。比如你在对数据进行了某些策略后需要更新百万行的数据中的绝大部分。
在一个存储过程中数据是在一步中被读取、操纵和更新的。而如果你在应用程序代码的中间层做相同的操作,那么你需要将数据通过网络传送过去,进行操作和将它发送回来。这不只会减慢这一个任务,其它在竞争和它使用的相同的数据的操作很可能就要等待了,因为这个数据处于传送过程中,而且将被执行操作。此外,存储过程的代码可以提供服务对特定的请求进行封装,这对简化你的整个应用程序来说是非常宝贵的。这三个数据库都支持存储过程和函数。Oracle还支持存储过程的包或集合,还包括各种面向对象的功能,这些功能几乎没有人使用过。一个数据库引擎实际上在存储过程和内嵌在那里的SQL代码之间进行上下文切换。在9i中,Oracle推出了批量绑定,这样你就可以对行的大型集合进行操作,并一次就更新整个集合,而不是在每个循环迭代中进行更新。这个功能甚至还可以非常显著的进一步提高性能。
视图
视图是基本的存储查询,正因为如此,它执行起来不是特别复杂。然而在查询中使用视图时,它们必定会使查询更加复杂。所以很明显,使用数据库中的视图之前,要更新子查询。Oracle显然提供视图有段时间了。在MySQL5.0中,也支持视图了。像Oracle一样,MySQL也支持UPDATEABLE视图,不过有些限制。Postgres也支持视图和UPDATEABLE视图。详见复杂SQL那一节。
物化视图(快照)
物化视图在Oracle中默认模式下支持的很好。作为回顾,记住一个物化视图(我更喜欢更加形象的术语“快照”,我离题了)是一个定期更新的拷贝或是一个表的子集。想象一个视图使用它的查询填充一个镜像拷贝。直到下一次刷新,这个拷贝是静态的,不随主本的更新而更新。通常会在更新的频率和支持它的处理日志(很像一个索引)的维护间做个权衡。名义上,MySQL和Postgresql不支持物化视图,但是在网上有这个的实现,它可以满足你的需求,如果你采用这个方法,你还需要一些支持。用一个存储过程创建物化视图,而另一个刷新它。大致上是CREATE TABLE my_copy AS SELECT。。。
语言集成
今天,基于web 的应用程序编程真的是一个平等的世界。几乎所有流行的web 语言都支持所有的数据库类型。Java、PHP、Perl、Python、C#/.NET 等等。这世界让你随心所欲。
触发器
MySQL、Oracle和Postgres都在INSERT、UPDATE和DELETE上支持BEFORE & AFTER事件触发器。我个人偏向于除非绝对必要,不然不使用触发器。它们正在逐渐被遗忘,但有时又会出现给你制造麻烦。不过如果谨慎的使用它们,它们会是很有用的。
安全
所有这三个数据库都有它们的漏洞。软件中有地方隐藏着错误真的是很正常的。而且,这三个数据库都有定期发布的更新补丁。不过我个人觉得,开源意味着必定有更多的眼光,而通常是批评的眼光在看待这个代码。而且,在开源世界里,社会压力要大的多。在商业领域,当修复比所知的等待修复的成本更昂贵的时候,供应商可能、并通常会加快速度。
在数据库中的安全方面,这三个数据库都采用密码登录和在数据库中对各种类型进行加密。Oracle最近提供了一个叫做虚拟专用数据库(virtual private database)的功能,在它里面数据表的某些部分和字段可以被加密,并隐藏起来不被看到。这对于数据库管理员和其他管理员不应该有权限访问的有争议的或敏感数据来说,非常有用。
总结
我们这三个数据库平台很显然有很多功能,和用于相同问题的不同解决方法。在安全、触发器、视图、物化视图和存储过程方面,它们提供了许多相同的功能性,尽管在性能和可配置性方面不尽相同。在第二部分我们将讨论在索引方面这些数据库真正开始显著不同的一些地方,不过可能最重要的是在它们的优化引擎方面。
【IT专家网独家】在我们的数据库比较的上一节中,我们介绍了各种知识例如触发器、视图和存储过程。尽管在Oracle、Postgresql和MySQL数据库中的功能设置肯定是各不相同的,但是这些内容已经可以满足你的大多数日常所需了。在这一节,我们将介绍一些关于平台间在处理复杂SQL和优化选择方面的不同,这些不同更加显著,也更加重要。
复杂SQL(优化引擎)
SQL是你与你的数据库交互的基础和最关键的方法,无论你选择哪个。这三个平台也恰恰是从它开始真正分离。Oracle支持非常复杂的查询、几乎不限制表的个数、所有的类型的连接和合并。虽然Oracle有很多功能,但是它真正宝贵的却是它基于成本的优化器,它可以分析SQL、如果可能的话进行重写和简化、基于成本选择索引、决定对表的操作和它之中的所有其它的各种功能。
阅读MySQL的文档,你会发现对偏向于性能的描述和供应商定义的细节使优化器和性能调整在任何平台上都很复杂。MySQL规定的最大规模是在任何连接或在一个视图中表的最大数目为61个。再一次的,我个人觉得无论如何在任何一个应用中这么多表的一个查询将是难以使用的,所以正如上面提到的,目前更适用的是优化器而不是查询最大表规格,等等。
8.x版本的Postgresql支持所有SQL92规范,几乎没有任何限制。再一次的,我认为你会看到的一个数据库优于其它的数据库的方面就是在优化方面。复杂的查询会变得凌乱,并且查询计划是你在诊断性能瓶颈时的最好的朋友。
索引类型
索引技术对于数据库性能是至关重要的,而Oracle有大量的选项可供选择。有非常多的不同的索引类型,包括标准的二进制树、转换键的、基于功能的、常被错误使用的位图索引,甚至还有索引表。随着附加项技术的发展,数据库管理员有了可用的提供索引的Oracle文本,它允许你搜索CLOB(字符大对象),并且Oracle Spatial提供用于基于位置的数据的索引。
在MySQL中,我们发现有二进制树、哈希、纯文本和GIS索引(对于基于位置的数据)。还有集群索引,但是如果说我在Oracle方面的经验给我任何指导的话,那么就是大多数应用通常是不相关的。因此,大多数情况下我在Oracle、MySQL或Postgres应用中看到的只有二进制树索引。另外,尽管像在MySQL中基于功能的索引是不可用的,但是他们可以通过创建另一个保存使用这个函数的数据的列来进行模拟,然后添加一个触发器来将安装它。
Postgresql提供二进制树和哈希,还有R树,和它自己定制的GiST索引类型,GiST索引类型允许使用用户定义的类型和允许创建基于功能的索引。Oracle提供了一个类似的功能性类型,它的基于功能的索引可以用于基于pl/sql的功能而不只是标准的预定义系统功能,例如你本来可能会使用的trunc、UPPER。要小心像这样的索引可能访问起来非常缓慢,你可能在谈论到要录入或移除数据时,甚至不希望听到“慢”这个词。
它确实实现了,并且优化器选择索引的方式优于Oracle。
审计
Oracle使你可以对一个表或一个文件进行审计,通过审查索引工具。一旦允许了,你可以审查对某一个表的插入、更新或删除,或者登录,或甚至是某一特定用户的所有访问。它有许多选项,并且设置为可用的是非常简单的。
Postgresql也有这个功能,并且它看起来和Oracle的一样灵活和可配置的。
另一方面MySQL看起来没有提供这个功能,但是你当然可以创建你自己的存储过程和触发器来做你想做的,并录入相关的信息到数据表里,这只需要一点额外的工作。
数据类型
Oracle、MySQL和Postgresql都支持最大达到4GB的大型的二进制和文本数据。我们所知道并喜欢的所有的数据类型也是非常有用的,例如数字、字符和日期。每一个都在一定程度上提供一些定制数据类型,尽管我很少看到在应用中使用这些。
现在我要讲的一件事是Postgresql和MySQL已经超过了过去的基础,不用担心它们实现我们经常使用的一个良好的自增长列类型。Oracle的争论是按顺序来做这项工作更加有效,但是是静态的。Oracle也没有SET数据类型,这个数据类型很重要。它也没有只有时间的时间数据类型,这个数据类型Postgresql和MySQL都有。但是你会发现你能在这三个数据库品平台上做所有你想做的关于日期和时间的操作,从对时区的操作到对间隔的处理,等等。
另外一个我喜欢Postgresql和MySQL的理由是它们支持各种优秀的数学数字类型,从smallint到decimal、real、double,等等。这些利用了基本的架构实现,与编程语言中可用的数据类型相匹配,例如C语言。
对事务的支持
在数据库领域,适当的事务操作遵守了acronym到ACID,这意味着原子性、一致性、隔离性和持久性。原子性意思是一个事务是一个完整的单元,所有都被提交或所有都被回滚。一致性意思是你从一个*VALID*状态转移到另一个,例如你执行适当的约束来加强业务逻辑。隔离性意思是一个事务不能看到另一个事务在做什么,直到它完成了(提交了)。持久性意思是一旦提交了,这个变更就是永久的,并且是防止你硬盘失败的*至关重要的*。
关于这个问题我有一些事情要说,希望能够避免争论。我看到像“任何企业级应用绝不会使用一个没有实现完全的ACID遵从性的数据库,而且非事务型的表是完全没有用的”这样的说法已经消失了。这些都是愚蠢的说法。例如,Oracle在它的数据字典中的它本身的性能视图就不是事务型的。其次,它们在那个环境中根本没有必要。有许多应用是这样的。我看过一个航空票务系统,它需要定期升级和添加第二个服务器用于放置Oracle。他们看了这个软件的所有相关的许可成本和大型设备的硬件成本。然后他们回头看这个应用。有些人正确的认识到在航空网站上90%的操作是浏览航班(只读),而仅仅10%才是真正的购买机票。所以,他们建立了一组低成本的MySQL服务器用于浏览航班,而变更旅程请求则提交给大型的Oracle服务器来执行票务操作。多么好的一个结合解决方案!
是的,MySQL在事务方面的InnoDB表方面已经走了很长一段路。这也许可以解释为什么Oracle购买Innobase。一些人仍然认为MySQL只是一个用于LDAP或NFS的SQL接口。但是,MySQL确实走了很长的路并且将继续挑战反对它的人。
在这点上Postgresql更完整,所以我会说你能看到的主要是和Oracle的性能方面的不同,这就是它的问题。
总结
正如你在我们的数据库平台的多个部分中看到的,选择一个数据库平台时要考虑很多事情。从功能完整性,到供应商支持和共同支持,到性能和优化。在你充分了解你在构建的应用和它真正需要什么之前,不要投资过多。到了最后你可能觉得这些比较模糊,并且难以确定,但是有了一点创造性,仔细思考这个主题,并且拥有一个好的开发环境,你就应该能够得出一个成本高效并强大的解决方案来。
北京玉渊潭公园第二十届樱花节
北京玉渊潭公园第二十届樱花节将于3月26日开幕,并持续到4月30日。期间市民将能欣赏到今20个品种,约2000多株樱花组成的“在水一方”、“樱棠春晓”等樱花八景。
活动期间,玉渊潭公园开闭园时间为早6点至晚8点30分。公园成人票上调至10元每人次,学生半价。年、季、月票周一至周五有效,周六日上午9点前、下午4点后有效。
此外,玉渊潭公园樱花园升级改造工程昨天完工,市民可漫步在5000平方米的樱花大道上观赏樱花.
Tomcat全攻略
随着java的流行,其在web上的应用也越来越广,tomcat作为一个开源的servlet容器,应用前景越来越广,本文将向你讲述tomcat的一些知识。
一:简介
tomcat是jakarta项目中的一个重要的子项目,其被JavaWorld杂志的编辑选为2001年度最具创新的Java产品(Most Innovative
Java Product),同时它又是sun公司官方推荐的servlet和jsp容器(具体可以见http://java.sun.com/products/jsp/tomcat/),因此其越来越多的受到软件公司和开发人员的喜爱。servlet和jsp的最新规范都可以在tomcat的新版本中得到实现。
二:安装及配置
tomcat最新版本为4.0.1,这个版本用了一个新的servlet容器Catalina,完整的实现了servlet2.3和jsp1.2规范。注意安装之前你的系统必须安装了jdk1.2以上版本。
(一):安装
1:windows平台
从tomcat网站下载jakarta-tomcat-4.0.1.exe,按照一般的windows程序安装步骤即可安装好tomcat,安装时它会自动寻找你的jdk和jre的位置。
2:Linux平台
下载jakarta-tomcat-4.0.1.tar.gz,将其解压到一个目录。
(二):配置
运行tomcat需要设置JAVA_HOME变量
|
(三):运行
设置完毕后就可以运行tomcat服务器了,进入tomcat的bin目录,win98下用startup启动tomcat,linux下用startup.sh,相应的关闭tomcat的命令为shutdown和shutdown.sh。
启动后可以在浏览器中输入http://localhost:8080/测试,由于tomcat本身具有web服务器的功能,因此我们不必安装apache,当然其也可以与apache集成到一起,下面会介绍。
下面你可以测试其自带的jsp和servlet示例。
(一):目录结构
tomcat的目录结构如下:
目录名 | 简介 |
bin | 存放启动和关闭tomcat脚本 |
conf | 包含不同的配置文件,server.xml(Tomcat的主要配置文件)和web.xml |
work | 存放jsp编译后产生的class文件 |
webapp | 存放应用程序示例,以后你要部署的应用程序也要放到此目录 |
logs | 存放日志文件 |
lib/japser/common | 这三个目录主要存放tomcat所需的jar文件 |
(二):server.xml配置简介
下面我们将讲述这个文件中的基本配置信息,更具体的配置信息见tomcat的文档
元素名 | 属性 | 解释 |
server | port | 指定一个端口,这个端口负责监听关闭tomcat的请求 |
shutdown | 指定向端口发送的命令字符串 | |
service | name | 指定service的名字 |
Connector
(表示客户端和service之间的连接) |
port | 指定服务器端要创建的端口号,并在这个断口监听来自客户端的请求 |
minProcessors | 服务器启动时创建的处理请求的线程数 | |
maxProcessors | 最大可以创建的处理请求的线程数 | |
enableLookups | 如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址 | |
redirectPort | 指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号 | |
acceptCount | 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理 | |
connectionTimeout | 指定超时的时间数(以毫秒为单位) | |
Engine
(表示指定service中的请求处理机,接收和处理来自Connector的请求) |
defaultHost | 指定缺省的处理请求的主机名,它至少与其中的一个host元素的name属性值是一样的 |
Context
(表示一个web应用程序,通常为WAR文件,关于WAR的具体信息见servlet规范) |
docBase | 应用程序的路径或者是WAR文件存放的路径 |
path | 表示此web应用程序的url的前缀,这样请求的url为http://localhost:8080/path/**** | |
reloadable | 这个属性非常重要,如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化,自动装载新的应用程序,我们可以在不重起tomcat的情况下改变应用程序 | |
appBase | 应用程序基本目录,即存放应用程序的目录 | |
unpackWARs | 如果为true,则tomcat会自动将WAR文件解压,否则不解压,直接从WAR文件中运行应用程序 | |
Logger
(表示日志,调试和错误信息) |
className | 指定logger使用的类名,此类必须实现org.apache.catalina.Logger 接口 |
prefix | 指定log文件的前缀 | |
suffix | 指定log文件的后缀 | |
timestamp | 如果为true,则log文件名中要加入时间,如下例:localhost_log.2001-10-04.txt | |
Realm
(表示存放用户名,密码及role的数据库) |
className | 指定Realm使用的类名,此类必须实现org.apache.catalina.Realm接口 |
Valve
(功能与Logger差不多,其prefix和suffix属性解释和Logger 中的一样) |
className | 指定Valve使用的类名,如用org.apache.catalina.valves.AccessLogValve类可以记录应用程序的访问信息 |
directory | 指定log文件存放的位置 | |
pattern | 有两个值,common方式记录远程主机名或ip地址,用户名,日期,第一行请求的字符串,HTTP响应代码,发送的字节数。combined方式比common方式记录的值更多 |
注意:1:经过我测试,我设置Context 的path="",reloadable=true,然后放一个WAR文件到webapps目录,结果tomcat不能检测出此文件(重起tomcat可以),而把此文件解压,则tomcat会自动检测出这个新的应用程序。如果不能自动检测WAR文件,我们可以利用下面管理中讲的方法来部署应用程序。
2:默认的server.xml中,Realm元素只设置了一个className属性,但此文件中也包含几个通过JDBC连接到数据库进行验证的示例(被注释掉了),通过Realm元素我们可以实现容器安全管理(Container
Managed Security)。
3:还有一些元素我们没有介绍,如Parameter,loader,你可以通过tomcat的文档获取这些元素的信息。
(三):管理
1:配置
在进行具体的管理之前,我们先给tomcat添加一个用户,使这个用户有权限来进行管理。
打开conf目录下的tomcat-users.xml文件,在相应的位置添加下面一行:
|
注意:这一行的最后部分一定是/>,tomcat的文档掉了/符号,如果没有/符号的话,tomcat重起时将无法访问应用程序。通过logs/catalina.out文件你可以看到这个错误的详细信息。
然后重起tomcat,在浏览器中输入http://localhost:8080/manager/,会弹出对话框,输入上面的用户名和密码即可。
2:应用程序列表
在浏览器中输入http://localhost:8080/manager/list,浏览器将会显示如下的信息:
|
面的信息分别为应用程序的路径,当前状态(running 或者stopped),与这个程序相连的session数。
3:重新装载应用程序
在浏览器中输入 http://localhost:8080/manager/reload?path=/examples,浏览器显示如下:
|
表示example应用程序装载成功,如果我们将server.xml的Context元素的reloadable属性设为true(见上面表格),则没必要利用这种方式重新装载应用程序,因为tomcat会自动装载。
4:显示session信息
在浏览器中输入http://localhost:8080/manager/sessions?path=/examples,浏览器显示如下:
|
5:启动和关闭应用程序
在浏览器中输入http://localhost:8080/manager/start?path=/examples和http://localhost:8080/manager/stop?path=/examples分别启动和关闭examples应用程序。
6:部署及撤销部署
WAR有两种组织方式,一种是按一定的目录结构组织文件,一种是一个后缀为WAR的压缩包,因此它的部署方式也有两种:
(1):在浏览器中输入:http://localhost:8080/manager/install?path=/examples&war=file:/c:examples
就会将按目录结构组织的WAR部署
(2):如果输入:http://localhost:8080/manager/install?path=/examples&war=jar:file:/c:examples.war!/
就会将按压缩包组织的WAR部署,注意此url后半部分一定要有!/号。
部署后就可以用 http://localhost:8080/examples访问了。
在浏览器中输入:http://localhost:8080/manager/remove?path=/examples
就会撤销刚才部署的应用程序。
(四):与apache集成
虽然tomcat也可以作web服务器,但其处理静态html的速度比不上apache,且其作为web服务器的功能远不如apache,因此我们想把apache和tomcat集成起来。
我们以linux系统为例介绍.
从apache网站下载apache1.3.22源代码版本,然后使用如下命令配置安装apache:
|
注意configure命令制定目标安装目录,并且加入DSO(Dynamic Shared Object)支持,注意一定不要忘了这一个选项。
然后下载webapp模块,将解压后mod_webapp.so文件放入apache的libexec目录,编辑apache的conf目录下的httpd.conf,在这个文件的最后加入下面三行:
|
第一行是加入webapp模块,如果编译apache时不增加DSO支持,则无法使用LoadModule指令,第二行指定tomcat与apache的连接,第三行指定部署那个应用,这两个指令使用格式如下:
|
其中connection name指定连接名,provider只能是warp,port端口与你的tomcat的配置文件server.xml最后几行制定的要保持一致。文件如下:
|
application name与你在tomcat中部署的应用名一致,url path指定访问这个应用的url。例如上面的例子可以通过http://localhost/examples/来访问tomcat中的examples应用。
(五):中文问题
一般jsp的乱码问题可以通过在jsp中加入来解决,至于servlet的乱码在可以使用servlet2.3中提供的HttpServeletRequest.setCharacterEncoding函数。更详细的中文问题请见JSP/Servlet
中的汉字编码问题。
tomcat作为一个servlet(jsp也被编译为servlet执行)容器,其应用前景是非常好的,如果与jboss结合起来,则可以实现sun的j2ee规范(用jboss作ejb服务器)。jboss的官方网站也提供集成了tomcat3.2*的jboss以供下载。另外一个开源的应用服务器(enhydra)
也是基于tomcat的,其提供了更友好的管理界面,部署应用程序也更简单,功能也更强大。
教你如何破解注册码
网上有许多令人心动的共享软件,可惜的是它们或多或少都存在各种限制,对于我等贫苦一族来说,面对昂贵的注册费用只能望而却步,而且支付起来也不太方便(特别是国外的共享软件)。现在,只要利用Google强大的搜索功能,再配合一定的搜索技巧就会让你有意外的发现。
打开Google的搜索页面后,在搜索栏内填上你要搜索的软件名称、空格,并在后面加上“94fbr”的搜索代码(例如:WinZIP 94fbr),单击“搜索”按钮后你会看到所要的东西了。但该方法也并不是万能的,当没有找到合适的结果,则不妨再试试输入“软件名称 crack OR sn OR 破解”,一般都能找到了。
小提示
该方法仅为学习软件或暂时不方便注册的用户使用,切勿用于非法用途!
对比C++和Java
对比C++和Java
“作为一名程序员,我们早已掌握了面向对象程序设计的基本概念,而且Java的语法无疑是非常熟悉的。事实上,Java本来就是从C++衍生出来的。”
然而,C++和Java之间仍存在一些显著的差异。可以这样说,这些差异代表着技术的极大进步。一旦我们弄清楚了这些差异,就会理解为什么说Java是一种优秀的程序设计语言。本附录将引导大家认识用于区分Java和C++的一些重要特征。
(1) 最大的障碍在于速度:解释过的Java要比C的执行速度慢上约20倍。无论什么都不能阻止Java语言进行编译。写作本书的时候,刚刚出现了一些准实时编译器,它们能显著加快速度。当然,我们完全有理由认为会出现适用于更多流行平台的纯固有编译器,但假若没有那些编译器,由于速度的限制,必须有些问题是Java不能解决的。
(2) 和C++一样,Java也提供了两种类型的注释。
(3) 所有东西都必须置入一个类。不存在全局函数或者全局数据。如果想获得与全局函数等价的功能,可考虑将static方法和static数据置入一个类里。注意没有象结构、枚举或者联合这一类的东西,一切只有“类”(Class)!
(4) 所有方法都是在类的主体定义的。所以用C++的眼光看,似乎所有函数都已嵌入,但实情并非如何(嵌入的问题在后面讲述)。
(5) 在Java中,类定义采取几乎和C++一样的形式。但没有标志结束的分号。没有class foo这种形式的类声明,只有类定义。
class aType()
void aMethod() {/* 方法主体 */}
}
(6) Java中没有作用域范围运算符“::”。Java利用点号做所有的事情,但可以不用考虑它,因为只能在一个类里定义元素。即使那些方法定义,也必须在一个类的内部,所以根本没有必要指定作用域的范围。我们注意到的一项差异是对static方法的调用:使用ClassName.methodName()。除此以外,package(包)的名字是用点号建立的,并能用import关键字实现C++的“#include”的一部分功能。例如下面这个语句:
import java.awt.*;
(#include并不直接映射成import,但在使用时有类似的感觉。)
(7) 与C++类似,Java含有一系列“主类型”(Primitive type),以实现更有效率的访问。在Java中,这些类型包括boolean,char,byte,short,int,long,float以及double。所有主类型的大小都是固有的,且与具体的机器无关(考虑到移植的问题)。这肯定会对性能造成一定的影响,具体取决于不同的机器。对类型的检查和要求在Java里变得更苛刻。例如:
■条件表达式只能是boolean(布尔)类型,不可使用整数。
■必须使用象X+Y这样的一个表达式的结果;不能仅仅用“X+Y”来实现“副作用”。
(8) char(字符)类型使用国际通用的16位Unicode字符集,所以能自动表达大多数国家的字符。
(9) 静态引用的字串会自动转换成String对象。和C及C++不同,没有独立的静态字符数组字串可供使用。
(10) Java增添了三个右移位运算符“>>>”,具有与“逻辑”右移位运算符类似的功用,可在最末尾插入零值。“>>”则会在移位的同时插入符号位(即“算术”移位)。
(11) 尽管表面上类似,但与C++相比,Java数组采用的是一个颇为不同的结构,并具有独特的行为。有一个只读的length成员,通过它可知道数组有多大。而且一旦超过数组边界,运行期检查会自动丢弃一个异常。所有数组都是在内存“堆”里创建的,我们可将一个数组分配给另一个(只是简单地复制数组句柄)。数组标识符属于第一级对象,它的所有方法通常都适用于其他所有对象。
(12) 对于所有不属于主类型的对象,都只能通过new命令创建。和C++不同,Java没有相应的命令可以“在堆栈上”创建不属于主类型的对象。所有主类型都只能在堆栈上创建,同时不使用new命令。所有主要的类都有自己的“封装(器)”类,所以能够通过new创建等价的、以内存“堆”为基础的对象(主类型数组是一个例外:它们可象C++那样通过集合初始化进行分配,或者使用new)。
(13) Java中不必进行提前声明。若想在定义前使用一个类或方法,只需直接使用它即可——编译器会保证使用恰当的定义。所以和在C++中不同,我们不会碰到任何涉及提前引用的问题。
(14) Java没有预处理机。若想使用另一个库里的类,只需使用import命令,并指定库名即可。不存在类似于预处理机的宏。
(15) Java用包代替了命名空间。由于将所有东西都置入一个类,而且由于采用了一种名为“封装”的机制,它能针对类名进行类似于命名空间分解的操作,所以命名的问题不再进入我们的考虑之列。数据包也会在单独一个库名下收集库的组件。我们只需简单地“import”(导入)一个包,剩下的工作会由编译器自动完成。
(16) 被定义成类成员的对象句柄会自动初始化成null。对基本类数据成员的初始化在Java里得到了可靠的保障。若不明确地进行初始化,它们就会得到一个默认值(零或等价的值)。可对它们进行明确的初始化(显式初始化):要么在类内定义它们,要么在构建器中定义。采用的语法比C++的语法更容易理解,而且对于static和非static成员来说都是固定不变的。我们不必从外部定义static成员的存储方式,这和C++是不同的。
(17) 在Java里,没有象C和C++那样的指针。用new创建一个对象的时候,会获得一个引用(本书一直将其称作“句柄”)。例如:
String s = new String("howdy");
然而,C++引用在创建时必须进行初始化,而且不可重定义到一个不同的位置。但Java引用并不一定局限于创建时的位置。它们可根据情况任意定义,这便消除了对指针的部分需求。在C和C++里大量采用指针的另一个原因是为了能指向任意一个内存位置(这同时会使它们变得不安全,也是Java不提供这一支持的原因)。指针通常被看作在基本变量数组中四处移动的一种有效手段。Java允许我们以更安全的形式达到相同的目标。解决指针问题的终极方法是“固有方法”(已在附录A讨论)。将指针传递给方法时,通常不会带来太大的问题,因为此时没有全局函数,只有类。而且我们可传递对对象的引用。Java语言最开始声称自己“完全不采用指针!”但随着许多程序员都质问没有指针如何工作?于是后来又声明“采用受到限制的指针”。大家可自行判断它是否“真”的是一个指针。但不管在何种情况下,都不存在指针“算术”。
(18) Java提供了与C++类似的“构建器”(Constructor)。如果不自己定义一个,就会获得一个默认构建器。而如果定义了一个非默认的构建器,就不会为我们自动定义默认构建器。这和C++是一样的。注意没有复制构建器,因为所有自变量都是按引用传递的。
(19) Java中没有“破坏器”(Destructor)。变量不存在“作用域”的问题。一个对象的“存在时间”是由对象的存在时间决定的,并非由垃圾收集器决定。有个finalize()方法是每一个类的成员,它在某种程度上类似于C++的“破坏器”。但finalize()是由垃圾收集器调用的,而且只负责释放“资源”(如打开的文件、套接字、端口、URL等等)。如需在一个特定的地点做某样事情,必须创建一个特殊的方法,并调用它,不能依赖finalize()。而在另一方面,C++中的所有对象都会(或者说“应该”)破坏,但并非Java中的所有对象都会被当作“垃圾”收集掉。由于Java不支持破坏器的概念,所以在必要的时候,必须谨慎地创建一个清除方法。而且针对类内的基础类以及成员对象,需要明确调用所有清除方法。
(20) Java具有方法“过载”机制,它的工作原理与C++函数的过载几乎是完全相同的。
(21) Java不支持默认自变量。
(22) Java中没有goto。它采取的无条件跳转机制是“break 标签”或者“continue 标准”,用于跳出当前的多重嵌套循环。
(23) Java采用了一种单根式的分级结构,因此所有对象都是从根类Object统一继承的。而在C++中,我们可在任何地方启动一个新的继承树,所以最后往往看到包含了大量树的“一片森林”。在Java中,我们无论如何都只有一个分级结构。尽管这表面上看似乎造成了限制,但由于我们知道每个对象肯定至少有一个Object接口,所以往往能获得更强大的能力。C++目前似乎是唯一没有强制单根结构的唯一一种OO语言。
(24) Java没有模板或者参数化类型的其他形式。它提供了一系列集合:Vector(向量),Stack(堆栈)以及Hashtable(散列表),用于容纳Object引用。利用这些集合,我们的一系列要求可得到满足。但这些集合并非是为实现象C++“标准模板库”(STL)那样的快速调用而设计的。Java 1.2中的新集合显得更加完整,但仍不具备正宗模板那样的高效率使用手段。
(25) “垃圾收集”意味着在Java中出现内存漏洞的情况会少得多,但也并非完全不可能(若调用一个用于分配存储空间的固有方法,垃圾收集器就不能对其进行跟踪监视)。然而,内存漏洞和资源漏洞多是由于编写不当的finalize()造成的,或是由于在已分配的一个块尾释放一种资源造成的(“破坏器”在此时显得特别方便)。垃圾收集器是在C++基础上的一种极大进步,使许多编程问题消弥于无形之中。但对少数几个垃圾收集器力有不逮的问题,它却是不大适合的。但垃圾收集器的大量优点也使这一处缺点显得微不足道。
(26) Java内建了对多线程的支持。利用一个特殊的Thread类,我们可通过继承创建一个新线程(放弃了run()方法)。若将synchronized(同步)关键字作为方法的一个类型限制符使用,相互排斥现象会在对象这一级发生。在任何给定的时间,只有一个线程能使用一个对象的synchronized方法。在另一方面,一个synchronized方法进入以后,它首先会“锁定”对象,防止其他任何synchronized方法再使用那个对象。只有退出了这个方法,才会将对象“解锁”。在线程之间,我们仍然要负责实现更复杂的同步机制,方法是创建自己的“监视器”类。递归的synchronized方法可以正常运作。若线程的优先等级相同,则时间的“分片”不能得到保证。
(27) 我们不是象C++那样控制声明代码块,而是将访问限定符(public,private和protected)置入每个类成员的定义里。若未规定一个“显式”(明确的)限定符,就会默认为“友好的”(friendly)。这意味着同一个包里的其他元素也可以访问它(相当于它们都成为C++的“friends”——朋友),但不可由包外的任何元素访问。类——以及类内的每个方法——都有一个访问限定符,决定它是否能在文件的外部“可见”。private关键字通常很少在Java中使用,因为与排斥同一个包内其他类的访问相比,“友好的”访问通常更加有用。然而,在多线程的环境中,对private的恰当运用是非常重要的。Java的protected关键字意味着“可由继承者访问,亦可由包内其他元素访问”。注意Java没有与C++的protected关键字等价的元素,后者意味着“只能由继承者访问”(以前可用“private protected”实现这个目的,但这一对关键字的组合已被取消了)。
(28) 嵌套的类。在C++中,对类进行嵌套有助于隐藏名称,并便于代码的组织(但C++的“命名空间”已使名称的隐藏显得多余)。Java的“封装”或“打包”概念等价于C++的命名空间,所以不再是一个问题。Java 1.1引入了“内部类”的概念,它秘密保持指向外部类的一个句柄——创建内部类对象的时候需要用到。这意味着内部类对象也许能访问外部类对象的成员,毋需任何条件——就好象那些成员直接隶属于内部类对象一样。这样便为回调问题提供了一个更优秀的方案——C++是用指向成员的指针解决的。
(29) 由于存在前面介绍的那种内部类,所以Java里没有指向成员的指针。
(30) Java不存在“嵌入”(inline)方法。Java编译器也许会自行决定嵌入一个方法,但我们对此没有更多的控制权力。在Java中,可为一个方法使用final关键字,从而“建议”进行嵌入操作。然而,嵌入函数对于C++的编译器来说也只是一种建议。
(31) Java中的继承具有与C++相同的效果,但采用的语法不同。Java用extends关键字标志从一个基础类的继承,并用super关键字指出准备在基础类中调用的方法,它与我们当前所在的方法具有相同的名字(然而,Java中的super关键字只允许我们访问父类的方法——亦即分级结构的上一级)。通过在C++中设定基础类的作用域,我们可访问位于分级结构较深处的方法。亦可用super关键字调用基础类构建器。正如早先指出的那样,所有类最终都会从Object里自动继承。和C++不同,不存在明确的构建器初始化列表。但编译器会强迫我们在构建器主体的开头进行全部的基础类初始化,而且不允许我们在主体的后面部分进行这一工作。通过组合运用自动初始化以及来自未初始化对象句柄的异常,成员的初始化可得到有效的保证。
public class Foo extends Bar { public Foo(String msg) { super(msg); // Calls base constructor } public baz(int i) { // Override super.baz(i); // Calls base method } }
(32) Java中的继承不会改变基础类成员的保护级别。我们不能在Java中指定public,private或者protected继承,这一点与C++是相同的。此外,在衍生类中的优先方法不能减少对基础类方法的访问。例如,假设一个成员在基础类中属于public,而我们用另一个方法代替了它,那么用于替换的方法也必须属于public(编译器会自动检查)。
(33) Java提供了一个interface关键字,它的作用是创建抽象基础类的一个等价物。在其中填充抽象方法,且没有数据成员。这样一来,对于仅仅设计成一个接口的东西,以及对于用extends关键字在现有功能基础上的扩展,两者之间便产生了一个明显的差异。不值得用abstract关键字产生一种类似的效果,因为我们不能创建属于那个类的一个对象。一个abstract(抽象)类可包含抽象方法(尽管并不要求在它里面包含什么东西),但它也能包含用于具体实现的代码。因此,它被限制成一个单一的继承。通过与接口联合使用,这一方案避免了对类似于C++虚拟基础类那样的一些机制的需要。
为创建可进行“例示”(即创建一个实例)的一个interface(接口)的版本,需使用implements关键字。它的语法类似于继承的语法,如下所示:
public interface Face { public void smile(); } public class Baz extends Bar implements Face { public void smile( ) { System.out.println("a warm smile"); } }
(34) Java中没有virtual关键字,因为所有非static方法都肯定会用到动态绑定。在Java中,程序员不必自行决定是否使用动态绑定。C++之所以采用了virtual,是由于我们对性能进行调整的时候,可通过将其省略,从而获得执行效率的少量提升(或者换句话说:“如果不用,就没必要为它付出代价”)。virtual经常会造成一定程度的混淆,而且获得令人不快的结果。final关键字为性能的调整规定了一些范围——它向编译器指出这种方法不能被取代,所以它的范围可能被静态约束(而且成为嵌入状态,所以使用C++非virtual调用的等价方式)。这些优化工作是由编译器完成的。
(35) Java不提供多重继承机制(MI),至少不象C++那样做。与protected类似,MI表面上是一个很不错的主意,但只有真正面对一个特定的设计问题时,才知道自己需要它。由于Java使用的是“单根”分级结构,所以只有在极少的场合才需要用到MI。interface关键字会帮助我们自动完成多个接口的合并工作。
(36) 运行期的类型标识功能与C++极为相似。例如,为获得与句柄X有关的信息,可使用下述代码:
X.getClass().getName();
为进行一个“类型安全”的紧缩造型,可使用:
derived d = (derived)base;
这与旧式风格的C造型是一样的。编译器会自动调用动态造型机制,不要求使用额外的语法。尽管它并不象C++的“new casts”那样具有易于定位造型的优点,但Java会检查使用情况,并丢弃那些“异常”,所以它不会象C++那样允许坏造型的存在。
(37) Java采取了不同的异常控制机制,因为此时已经不存在构建器。可添加一个finally从句,强制执行特定的语句,以便进行必要的清除工作。Java中的所有异常都是从基础类Throwable里继承而来的,所以可确保我们得到的是一个通用接口。
public void f(Obj b) throws IOException { myresource mr = b.createResource(); try { mr.UseResource(); } catch (MyException e) { // handle my exception } catch (Throwable e) { // handle all other exceptions } finally { mr.dispose(); // special cleanup } }
(38) Java的异常规范比C++的出色得多。丢弃一个错误的异常后,不是象C++那样在运行期间调用一个函数,Java异常规范是在编译期间检查并执行的。除此以外,被取代的方法必须遵守那一方法的基础类版本的异常规范:它们可丢弃指定的异常或者从那些异常衍生出来的其他异常。这样一来,我们最终得到的是更为“健壮”的异常控制代码。
(39) Java具有方法过载的能力,但不允许运算符过载。String类不能用+和+=运算符连接不同的字串,而且String表达式使用自动的类型转换,但那是一种特殊的内建情况。
(40) 通过事先的约定,C++中经常出现的const问题在Java里已得到了控制。我们只能传递指向对象的句柄,本地副本永远不会为我们自动生成。若希望使用类似C++按值传递那样的技术,可调用clone(),生成自变量的一个本地副本(尽管clone()的设计依然尚显粗糙——参见第12章)。根本不存在被自动调用的副本构建器。为创建一个编译期的常数值,可象下面这样编码:
static final int SIZE = 255
static final int BSIZE = 8 * SIZE
(41) 由于安全方面的原因,“应用程序”的编程与“程序片”的编程之间存在着显著的差异。一个最明显的问题是程序片不允许我们进行磁盘的写操作,因为这样做会造成从远程站点下载的、不明来历的程序可能胡乱改写我们的磁盘。随着Java 1.1对数字签名技术的引用,这一情况已有所改观。根据数字签名,我们可确切知道一个程序片的全部作者,并验证他们是否已获得授权。Java 1.2会进一步增强程序片的能力。
(42) 由于Java在某些场合可能显得限制太多,所以有时不愿用它执行象直接访问硬件这样的重要任务。Java解决这个问题的方案是“固有方法”,允许我们调用由其他语言写成的函数(目前只支持C和C++)。这样一来,我们就肯定能够解决与平台有关的问题(采用一种不可移植的形式,但那些代码随后会被隔离起来)。程序片不能调用固有方法,只有应用程序才可以。
(43) Java提供对注释文档的内建支持,所以源码文件也可以包含它们自己的文档。通过一个单独的程序,这些文档信息可以提取出来,并重新格式化成HTML。这无疑是文档管理及应用的极大进步。
(44) Java包含了一些标准库,用于完成特定的任务。C++则依靠一些非标准的、由其他厂商提供的库。这些任务包括(或不久就要包括):
■连网
■数据库连接(通过JDBC)
■多线程
■分布式对象(通过RMI和CORBA)
■压缩
■商贸
由于这些库简单易用,而且非常标准,所以能极大加快应用程序的开发速度。
(45) Java 1.1包含了Java Beans标准,后者可创建在可视编程环境中使用的组件。由于遵守同样的标准,所以可视组件能够在所有厂商的开发环境中使用。由于我们并不依赖一家厂商的方案进行可视组件的设计,所以组件的选择余地会加大,并可提高组件的效能。除此之外,Java Beans的设计非常简单,便于程序员理解;而那些由不同的厂商开发的专用组件框架则要求进行更深入的学习。
(46) 若访问Java句柄失败,就会丢弃一次异常。这种丢弃测试并不一定要正好在使用一个句柄之前进行。根据Java的设计规范,只是说异常必须以某种形式丢弃。许多C++运行期系统也能丢弃那些由于指针错误造成的异常。
(47) Java通常显得更为健壮,为此采取的手段如下:
■对象句柄初始化成null(一个关键字)
■句柄肯定会得到检查,并在出错时丢弃异常
■所有数组访问都会得到检查,及时发现边界违例情况
■自动垃圾收集,防止出现内存漏洞
■明确、“傻瓜式”的异常控制机制
■为多线程提供了简单的语言支持
■对网络程序片进行字节码校验