借如何编译learndiaryV0.9源码说说javac命令的基本用法

前两天,一位朋友在QQ上向我问一个问题,他说他下载了一个人力资源管理系统,可是不知道怎么编译它?

我答:一般的源码都有Readme文件或ant脚本,可以照此编译。。。

他回复说:里面的说明只有3行:数据库文件在data中,用户名**,密码**;其余什么都没有?

我答:您看它是用什么IDE开发的,最简单的方法是导入开发它的IDE环境中,如果没有,那就只有用javac命令手工编译了。。。

看到这,我给这个人力资源系统下了一个大概的结论,没有详细的文档,没有自动编译脚本,初学者难以把它编译成功。

恰好,我的"学习日记V0.9"也是这样一个“初学都难以编译成功”的程序。它是我初学JAVA完成的第一个成形的程序,可以运行,但是正由于是初学的实习之作。毛病不少。其中一个毛病就是源代码组织不合理,没有详细的文档,没有自动编译脚本。

于是,我们就只有用javac命令来手工编译这些程序了,关于javac命令,您用javac -help在线帮助可以看到全部的用法,只不过初学者可能对其中的含义不是很明白。我也是一个入门级的水平,对其中的全部用法也不是都用过和明白。所以,与其说我开展的是JAVA学习日记网站免费提供JAVA学习入门咨询服务,还不如说是借此机会和大家聊聊JAVA学习,共同交流、共同进步。下面我就借怎样编译成功learndiaryV0.9源码说说javac命令的基本用法,包括:-classpath -cp -sourcepath -d 各个选项。也算是对那位朋友的一个详细的解答。

1、您下载了learndiaryV0.9.rar并解开后,会看到以下文件清单:

  learndairydbV0.9.sql,数据库文件;learndiaryV0.9.war,编译好的程序文件;src,源代码文件目录;readme.html,使用说明。

  您按照里面readme.html文件的步骤应该能把这个程序运行起来(如果您不知道怎样导入数据库,请参考一下这篇日记:mysql数据库的导出和导入)。但是,初学者想修改src里面的源文件并编译运行只能用javac命令手工编译。而且,因为这个程序是用ultraedit手工写的,您想把它导入一个集成开发环境也不太容易。所以,我就用编译src里面的源码为例说说javac命令的基本用法;

2、我们把编译好的类文件放在哪里呢?

跟源文件放在一起肯定不是一个好办法,那么,在解开的目录中建一个名为build的文件夹,与src文件夹在同一目录下。build文件夹用于保存编译好的class文件;

3、让我们来初步试一试编译src里的源文件吧。(我用的是ubuntu 6.06 linux平台+jdk1.5,在windows平台下的路径表示有所不同,您需要改一下

learndiaryV0.9源码没有按包结构存放,如:src文件夹下面包含4个文件夹:action  actionform  dao  model  util,其中的一个类文件:LearnDiaryDB.java就直接放在dao文件夹下面,而LearnDiaryDB.java中的包结构是: package com.learndiary.website.dao;

标准的存放位置是./src/com/learndiary/website/dao。但是,这不妨害我们把源文件编译成类文件。

进入src文件夹所在的目录:


mdx@ubuntu:~/mdxhome/learndiaryV0.9.rar_FILES$ dir

build  learndiarydbV0.9.sql  learndiaryV0.9.war  readme.html  src

用javac命令编译src文件夹下的源文件到build文件夹下面:


mdx@ubuntu:~/mdxhome/learndiaryV0.9.rar_FILES$ javac -d ./build ./src/*/*.java ./src/*/*/*.java

结果如何呢?

长长的报错和警告,片断如下:


...(略)

./src/dao/LearnDiaryDB.java:290: 警告:编码 UTF8 的不可映射字符

      userInfo.setUserName("�ο�");

                            ^

...(略)

./src/actionform/ForbidForm.java:7: 软件包 org.apache.struts.action 不存在

import org.apache.struts.action.ActionErrors;

                                ^

./src/actionform/ForbidForm.java:23: 找不到符号

符号: 类 ActionForm

public class ForbidForm extends ActionForm {

                                ^

...(略)

./src/action/account/LoginAction.java:42: 找不到符号

符号: 类 ServletException

位置: 类 com.learndiary.website.action.account.LoginAction

                throws IOException, ServletException {

                                    ^

./src/action/account/LogoutAction.java:5: 软件包 javax.servlet 不存在

import javax.servlet.ServletException;

                     ^

...(略)

“警告:编码 UTF8 的不可映射字符”是怎么一回事呢?

原来learndiaryV0.9源程序里面有硬编码的中文字符,我用的是gb2312编码,而我现在的编译环境(ubuntu 6.06 linux)的默认编码是utf8,于是,需要指定encoding选项为: -encoding gb2312

而后面那些“找不到符号”、“软件包***不存在”的提示就是没有指定源码中引用到的其它类的路径了,这需要在classpath选项中指定,根据出错信息,我们为了方便,我们在当前目录下建一个名为compilelib的文件夹,把编译需要的库文件拷贝到这个文件夹下面,compilelib与src目录是同级的。确认编译需要的库文件可能不是一次尝试就能全部找出的,有时您需要根据出错信息从网上搜索,以判断是需要哪个库文件,一般来说,这些库文件在我下面说的两个地方都应该找得到,即:程序的WEB-INF/lib目录下面和web程序容器的通用库目录(如tomcat5.0是common/lib)下面。

到哪里去找哪些需要的库文件呢?

1)、用解压软件解开当前目录下面那个learndiaryV0.9.war文件,进入里面的那个WEB-INF/lib目录,把里面的activation.jar, mail.jar, struts.jar库文件拷贝到compilelib目录中;

2)、把您使用的tomcat(我用的是5.0版)安装目录下面common/lib下面的servlet-api.jar也拷贝到compilelib目录中;

于是,compilelib目录下面有如下库文件:


mdx@ubuntu:~/mdxhome/learndiaryV0.9.rar_FILES/compilelib$ dir

activation.jar  mail.jar  servlet-api.jar  struts.jar

然后,执行:


mdx@ubuntu:~/mdxhome/learndiaryV0.9.rar_FILES$ javac -classpath ./compilelib/struts.jar:./compilelib/servlet-api.jar:./compilelib/mail.jar:./compilelib/activation.jar -d ./build -encoding gb2312 ./src/*/*.java ./src/*/*/*.java

(windows下面的classpath分隔符是分号; ,而不是这里linux下面的冒号: )

再解释一下"./src/*/*.java"通配符,它表示编译src目录下面第一层所有目录中的所有java文件,而“./src/*/*/*.java”则表示编译src目录下面第二层所有目录中的所有java文件,learndiaryV0.9的源码只有两层深,如果碰到有的程序的源码有多层深,那您就多添几层了,我还没有找到手工用javac命令把一个目录下面所有目录层次的java文件在一句里面指定好一次全部编译的方法,有谁知道提示一下,谢谢:)

于是,按package组织好的类文件就被编译好放在build目录了,它的组织结构是这样的: ./build/com/learndiary/website/action/...

然后,您就可以把这些编译好的类拷贝到程序的WEB-INF/classes目录下面了。

按理说,我们已经成功的编译了learndiaryV0.9,那还需要我们做什么呢?

我们这里的目的是借编译learndiaryV0.9说说javac命令的用法,所以,我还得继续把字打下去:)

4、您会发现上面的-classpath的选项里没有当前目录. (点号),难道不需要当前目录吗?在javac命令里的-sourcepath选项与-classpath选项有什么区别呢?这两个问题我们以只编译./src/action/disgoal/DisGoalContentAction.java这个文件来说明。

首先,我们把整个源码根据包结构重新组织好,即在src目录下面建一个./src/com/learndiary/website/的目录结构(据个人经验,这样才能单独编译成功DisGoalContentAction.java),再把原来src目录下的那些文件夹移到website文件夹下面去,这样DisGoalContentAction.java的路径就是:./src/com/learndiary/website/action/disgoal/DisGoalContentAction.java

然后,我们回到src目录的上层目录,执行javac命令如下:


mdx@ubuntu:~/mdxhome/learndiaryV0.9.rar_FILES$ javac -classpath ./compilelib/struts.jar:./compilelib/servlet-api.jar:./compilelib/mail.jar:./compilelib/activation.jar -d ./build -encoding gb2312 ./src/com/learndiary/website/action/disgoal/DisGoalContentAction.java

但是,您会发现报错如下:


...(略)

./src/com/learndiary/website/action/disgoal/DisGoalContentAction.java:4: 软件包 com.learndiary.website.dao 不存在

import com.learndiary.website.dao.LearnDiaryDB;

                                  ^

./src/com/learndiary/website/action/disgoal/DisGoalContentAction.java:47: 找不到符号

符号: 类 LearnDiaryDB

...(略)

这是因为DisGoalContentAction.java中引用的用户源文件找不到,这时,我们的-sourcepath选项出场了,添加这个选项的命令如下:


mdx@ubuntu:~/mdxhome/learndiaryV0.9.rar_FILES$ javac -classpath ./compilelib/struts.jar:./compilelib/servlet-api.jar:./compilelib/mail.jar:./compilelib/activation.jar -sourcepath ./src -d ./build -encoding gb2312 ./src/com/learndiary/website/action/disgoal/DisGoalContentAction.java

一切OK了,并且,DisGoalContentAction.java引用到的几个源文件同时被编译进build目录了。

其中,“-sourcepath ./src”的作用是告诉javac到这个目录下面去找它要的东西。

实际上,-sourcepath这个选项完全可以被-classpath代替,只不过classpath除了可以找源文件,还可以找类文件,而sourcepath却只可以找源文件。也就是说,下面这个命令与上面的命令是等效的:


mdx@ubuntu:~/mdxhome/learndiaryV0.9.rar_FILES$ javac -classpath ./compilelib/struts.jar:./compilelib/servlet-api.jar:./compilelib/mail.jar:./compilelib/activation.jar:./src -d ./build -encoding gb2312 ./src/com/learndiary/website/action/disgoal/DisGoalContentAction.java

但是,反过来,用-sourcepath代替-classpath却不行,如下面的命令是不会执行成功的:


mdx@ubuntu:~/mdxhome/learndiaryV0.9.rar_FILES$ javac -sourcepath ./compilelib/struts.jar:./compilelib/servlet-api.jar:./compilelib/mail.jar:./compilelib/activation.jar:./src -d ./build -encoding gb2312 ./src/com/learndiary/website/action/disgoal/DisGoalContentAction.java

于是,我们再来说说classpath中当前路径 .  的作用。

假如您在当前目录下建了一个目录mypackage,再在mypackage下面写了一个Hello.java文件,并以mypackage为包,即它的头部有一句 package mypackage;

然后,您在当前目录(mypackage的父目录)下执行 javac ./mypackage/Hello.java,编译成功。在mypackage目录生成类文件Hello.class,然后,您在当前目录下执行:java -classpath test mypackage.Hello ,其中test是一个不存在的目录,目的是屏蔽系统的classpath中环境变量中定义的当前路径。您会发现类似下面的报错:


mdx@ubuntu:~$ java -classpath test mypackage.Hello

Exception in thread "main" java.lang.NoClassDefFoundError: mypackage/Hello

改过来,使当前路径生效:java -classpath . mypackage.Hello

执行结果就正常了。

所以,classpath当前路径 . 的作用就是告诉java从当前路径开始找它要的东西。

另外,javac中选项 -cp是选项-classpath的缩写,是完全等效的。

以上用编译learndiaryV0.9来说了javac命令的基本用法包括:-classpath -cp -sourcepath -d 各个选项。javac命令还有其它的选项,您用javac -help在线帮助可以看到,不过不常用,我也没有用过,就不写了。

5、一个疑问:

在我们编译DisGoalContentAction.java这一个java源文件的时候为什么必须要告诉它引用的其它源文件的搜索路径(用选项 -sourcepath ./src 告知),而前面编译learndiaryV0.9中src目录中全部源文件时却不用告诉它们彼此引用的其它源文件的搜索路径呢?而且,上面编译全部源文件时还并没有按包的结构组织源代码。大家可以探讨一下这是为什么?

今天就写到这里了。如您要转载本文请注明原始出处为:借如何编译learndiaryV0.9源码说说javac命令的基本用法: http://java.learndiary.com/diaries/3262.jsp 和作者信息: littlebat。我会在本文的原始出处随时对本文进行修定或补充。由于本人水平有限,错漏之处在所难免,欢迎您的批评指正和交流。谢谢。

                   JAVA学习日记  孟大兴

                                        

                                                         2007年5月28日早上初稿

JAVA学习日记网站怎样进行JAVA学习入门咨询服务?

所谓“咨询服务”,不过是先走一步者告诉后来一步者,哪儿有陷阱,别走弯路。

据我的观点,有两种“咨询服务”:

一种是问题驱动的,碰到一个问题向人提问,得到一个解决问题的答案,短平快,结束;

一种是全面系统的、从多方面的学习潜能的开发出发,针对个人的基础和学习习惯,个性化的跟踪咨询者的学习状态和提供相关建议的咨询,这个咨询服务是不能立马看到效果的,但是对咨询者的长远学习能力的培养有利。JAVA学习日记着重于后面这种咨询服务,当然,也不完全排除对当前问题的解答,但解答的出发点和方式还是诱导出您长远的、良好的解决问题的素质。

那么,我们怎么开展JAVA学习入门咨询服务呢?

1、首先,您要有自己的JAVA学习目标。

您需要问自己为什么学JAVA?学到哪个程度?是做网站?做手机程序?做桌面程序?做游戏?或者您是学软件工程的,学JAVA的目的是为软件工程作辅助的?还是仅仅是为增加知识面的泛泛了解?还有,您准备用多少时间来达到这个目标?您一天能用多少时间来学JAVA?

2、评估您的现有知识结构。

您学过程序吗?您学过C语言吗?您知道OOP吗?您学过数据库吗?您对网页制作和网站建设了解多少?做JAVA游戏您有没有丰富的想像力以构建故事情节?。。。

3、向我们提出您参加JAVA学习入门咨询的意愿。

经过您的上面两个方面的自我评估,您需要用我们给出的联系方式(见:JAVA学习日记网站免费提供JAVA学习入门咨询服务

)提交您的意愿。我们会为您建立学习档案(为了大家交流,如果您没有反对,您的学习档案将被公开),并提交您对上面两个方面的自我评估。我们根据您的评估为您制定学习策略和建议学习路线。

4、您需要在本站注册,写下您的JAVA学习目标或加入别人已经建立的JAVA学习目标。

我们要求您在本站注册,像本站已有的用户那样。写下您自己的JAVA学习目标或加入别人已经建立的JAVA学习目标。在平时的学习过程中,您可以记下自己的学习日记。这样,一方面方便大家的交流,另一方面我们可以更好的跟踪您的学习进度,为您随时调整学习路线提出建议。

5、您需要每周都与我们进行沟通。

沟通的方式包括:在本站记下您的学习日记、用本站提供的联系方式(见:JAVA学习日记网站免费提供JAVA学习入门咨询服务)与我们联系。我们需要及时跟踪咨询效果,并为您调整学习策略的建议。如果,您没有事先的告知,中断与本站的咨询联系一周。本站视您为自动放弃咨询资格。并将把您的咨询资格留给别人。(本站咨询人数限3人)

6、本站咨询服务完全免费。

                   JAVA学习日记  孟大兴

                                  2007年5月25日上午

JAVA学习入门标准之我见

在我建立的JAVA学习日记网站提供JAVA学习入门咨询服务的目标中(我把拥有帮助别人JAVA学习入门的能力作为了一个自己的目标),我提到的咨询服务的最终效果是“入门为止”,那么,什么是我心里的“JAVA学习入门”呢?

说老实话,我学习JAVA至今5年了,由于自己没有进一步提高的需要,我的JAVA水平也仅是我想像中的“入门”而已。

所谓“入门”,有一句中国的古话“师傅领进门,修行在个人。”,也就是说,入门之后,您已经具备根据自己的需要,能进一步的自主的有效的学习并拥有技能。再打个比方,就像卫星已经被火箭送入了太空,可以自由的遨游了。这里,学习的技能将让您能够如您所愿的达成您的学习目标,您已经得到了“点金之术”,而不仅仅是金子。

下面把这个“入门”的概念运用在“JAVA学习”上,来聊一下“JAVA学习入门”的标准。这也是JAVA学习日记网站承诺的JAVA学习入门咨询的最终咨询效果的标准。

1、您对JAVA的整个家族成员有了一个全局性的了解。

您已经来到JAVA海洋的岸边,您能够看见海洋中的一座座闪着金光(您可以把它当成是金子的光,也可以当作是知识的光。。。)的岛屿,它们是JAVA的各个运用领域,如:J2EE, JAVA桌面程序,JAVA手机程序,JAVA游戏,JAVA图形,等等。您知道它们大概是什么样子,您也知道怎样才能到达那些岛屿。

2、您对怎样达到您的JAVA学习目标了然于胸。

您知道怎样解决日常工作中的问题,您知道到哪儿去找答案,您知道要达到您的学习需要去读哪些书,需要去哪些网站。您知道为了达到您的学习目标,哪些知识是重点要掌握的,哪些是需要了解的。也就是说,您能分清主次。

3、您能知道如何正确的与人交流JAVA学习问题。

您能知道什么时候向人提问,怎样提问,您能知道怎么样与人共享学习目标和学习经验,从而达到共同进步目的。您不会吝惜自己回答别人以正确的方式和正确的态度向您提的问题,因为能够提出好问题的人就是值得您交往的学友和老师,毫无疑问,您最终将从回答别人的问题中获益。

4、您对JAVA周边技术都有恰当的掌握。

JAVA不是孤立的,它与数据库,应用服务器,操作系统,数据结构,网页设计,您的想像力。。。等等,都是互相联系的。只掌握JAVA语法,您是永远作不出一个完整的程序的;所以,您根据自己的侧重点,对JAVA的周边技术都有主次分明的、恰当的掌握。

以上说的都是JAVA学习入门后必须具备的基本素质。下面谈谈我认为JAVA学习入门后需要掌握的JAVA技能与知识。相对于以上几点,我反而认为这些技能和知识是次要的。而我们JAVA学习日记网站JAVA学习入门咨询服务的重点也在上面几点素质的诱导和启发--这些素质您本来就有的,我们的咨询服务只不过是把您的这些未被开发的素质显现出来,从而为您进一步的JAVA技能的获取和人生各种技能的获取打下基础。

5、您能够根据自己的需要作出一个完整的可运行的程序或小系统。

您能根据自己的需要,自己设计,编码,调试运行成功一个程序。在完成这个小程序的过程中,您可以模仿和借鉴别人的系统和代码,但绝不是照抄,您能读懂自己代码和设计的含义,您能够根据出现的问题,去用多种途径解决问题:捕捉出错信息;看文档,如必备的J2SE文档;上网用搜索引擎查答案;上论坛或向周围的人提问请教。。。您在自己完成的系统中,有自己的思想,有自己的代码,您能知道您的代码中的绝大部分代码的含义,对暂时不甚了了的部分您也能圈定问题的影响范围和评估其重要性,以确定解决它的紧迫性--要知道,不是您碰到的任何一个问题都需要挖根问底的,您要根据自己的目的把时间花在最关键的地方。而在完成这个小系统的过程中,尽量不要使用Eclipse, JBuilder, Netbean等集成IDE环境,虽然它们有利于已入门者提高生产效率,但却不利于初学者练习和掌握基础知识;也不要求您用UML来设计,但您最好能用自己的方式作一个简单的设计,如:把需求列出来,把页面布局用草图画出来。。。,而且,作为周边知识的掌握,您最好是能看懂UML设计图;初学者作的系统,我觉得没有必要要求您有良好的面向对象设计,对系统有恰当的分层--我觉得这些是入门以后要做的事,您要做好这些事,设计模式之类的东西肯定是要学的。再强调一点,我不认为未入门者看设计模式是恰当的。

这个问题写多了,但要说完整不容易,也许后面为有专门的日记来写这个问题。

6、您已经比较完整和认真的精读过一本JAVA基础知识的书了,对JAVA基础有比较完整和重点突出的掌握。您有良好的面向对象的概念--虽然您还不能自如的运用它。

关于JAVA基础知识的书,我首推《JAVA编程思想》,英文书名:Thinking in Java。对这类书,您不能泛泛的读,要精读,对上面的例子和习题都要尽量认真的去做完。学这些书的时候,建议只用记事本,或UltraEdit之类的文本编辑器+Jdk,或者再加上一个mysql数据库和Tomcat服务器就行了。根据您的需要,如您暂时不打算做JAVA桌面程序,那么关于AWT(Abstract Window Toolkit)和Swing之类的东西可以大概看一下,知道是怎么一回事。但是,作为JAVA的基础,那些基础的包的东西一定要掌握,如lang的包,util的包等等,其中,J2SE中的容器类(Collections)必须要掌握,因为它们能够帮您省很多事,您需要知道什么时候用List,Set 或 Map?什么时候用ArrayList, LinkedList?您能正确的、熟练的使用如:Comparator,Iterator等重要的辅助性质的类。。。

良好的面向对象概念非常重要,您需要知道什么是面向对象,什么是封装、继承、多态?什么是包?并在编程中能有意识的运用这些概念。

7、您已经拥有良好的编码习惯和规范。

如JAVA的各个元素的命名规范,代码的缩进写作,甚至数组的排列等等。良好的写作规范是一个很重要的基本功。对代码的可读性和可维护性都很重要。

JAVA学习入门的标准是一个见仁见智的问题,可能每个人都有自己的JAVA学习入门标准。而上面仅是我的一人之见,自己也是一个入门者而已,偏颇和错漏之处还望批评和指正。谢谢。

今天就写到这里了。如您要转载本文请注明原始出处为:JAVA学习入门标准之我见: http://java.learndiary.com/diaries/3256.jsp 和作者信息: littlebat。我会在本文的原始出处随时对本文进行修定或补充。并欢迎您的留言反馈和交流。谢谢。

                   JAVA学习日记  孟大兴

                                        

                                                         2007年5月24日上午初稿

我为什么要免费提供JAVA学习入门咨询服务?

学习JAVA有5年了,本来自己的水平也很有限,但我为什么还要大张其鼓、斗胆免费提供JAVA学习入门咨询服务呢?

我自己总结了一下,主要是如下几点:

1、我对某位教育专家讲的信息时代的个人学习理论有些认同和心得,他的主要观点我比较有感觉的是(其中加了我对学习的理解,可能与原来那位专家的说法不尽一致):

1)、信息时代知识大爆炸,知识更新速度很快,我们要学会终身学习,快速学习;

2)、信息时代人人都是学生,又人人都是老师,不存在真正传统意义上的老师,所谓老师,只不过比学习多往前走了几步;而且,人各有所长,您在某方面是老师,但是在另一个方面可能就是学生了;

3)、学校的教育应该转型,转型为学生自主学习为主提供服务,也就是说,教育产业应该是服务产业。

基于以上的观点,我认为自己能够向人提供JAVA学习入门咨询服务。

2、个人对教师的职业有一种敬佩的心理,想体验一下作一个业余“老师”的滋味;为自己的人生尝试一下另一类的感受;

3、与人交流,在为别人服务的同时也能促进自己的思想的成熟,和有可能促进自己进一步的JAVA学习;

4、为以后有可能会开展的收费JAVA学习咨询服务打下基础。

如何迅速成为Java高手(cjsdn)(转帖)

转自:如何迅速成为Java高手(cjsdn): http://www.javaresearch.org/article/17565.htm

(转载者littlebat注:从http://www.javaresearch.org/article/17565.htm上cherami的转载日期:2004-09-29 22:10:14可以看到,这篇在互联网上广泛转载的文章应该至少是27个月之前发表的,其间,Java技术也有了很多变化,所以阅读者应该知道这个时间概念。所以,对互联网上的文章来说,发表的原始出处和发表日期非常重要,尤其是对飞速发展的IT技术来说。)

转帖正文

*********************************************************************************************************

如何迅速成为Java高手(cjsdn)

cherami 转贴   更新:2004-09-29 22:10:14  版本: 1.0  

很多网友问我学习Java有没有什么捷径,我说“无他,唯手熟尔”。但是我却很愿意将自己学习的一些经验写出来,以便后来者少走弯路,帮助别人是最大的快乐嘛!

要想学好Java,首先要知道Java的大致分类。我们知道,自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。J2SE开发桌面应用软件比起VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。所以现在应用最广泛又最好学的就是J2EE了。J2EE又包括许多组件,如Jsp,Servlet, JavaBean,EJB,JDBC,JavaMail等。要学习起来可不是一两天的事。

那么又该如何学习J2EE呢?当然Java语法得先看一看的,I/O包,Util包,Lang包你都熟悉了吗?然后再从JSP学起。如果你学过HTML,那么事情要好办的多,如果没有,那你快去补一补 HTML基础吧。其实JSP中的Java语法也不多,它更象一个脚本语言,有点象ASP。然后你就该学一学Servlet了。Servlet就是服务器端小程序,他负责生成发送给客户端的HTML文件。JSP在执行时,也是先转换成Servlet再运行的。虽说JSP理论上可以完全取代Servlet,这也是SUN推出JSP的本意,可是Servlet用来控制流程跳转还是挺方便的,也令程序更清晰。接下来你应该学习一下Javabean了,可能你早就看不管JSP在HTML中嵌Java代码的混乱方式了,这种方式跟ASP又有什么区别呢?还好,SUN提供了Javabean可以把你的JSP中的Java 代码封装起来,便于调用也便于重用。接着就是EJB了,EJB就是Enterprise JavaBean,看名字好象它是Javabean,可是它和 Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的Weblogic, Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。至于JDBC,就不用我多说了,你如果用java编过存取数据库的程序,就应该很熟悉。还有,如果你要用Java编发送电子邮件的程序,你就得看看Javamail了。

好了,对 Java和J2EE有了一些基本概念之后,你就应该编一些程序了,千万不要纸上谈兵哦。最好找一些有实例且带光盘的书来看,这样看到好的程序就可以直接 Ctrl+C再Ctrl+V,也不用劳您老大架再亲自把它 再输一遍吧,再说直接复制还不用怕出错,何乐而不为呢!还有就是要经常上一些好的Java编程文章,有好的文章要Cut下来,有问题尽管问,只要问题不是太傻,一般高手都会回答你的。下面介绍几个好的Java方面的编程网站:

CSDN论坛 http://www.csdn.net/ 中国最有名的技术论坛,《程序员》杂志就是他们出版的,你可以在上面提出问题,马上就有人回答你,如果你觉得好,你可以给那人加分;

Java研究组织http://www.javaresearch.org/ 上面有很多原创文章,高手还是挺多的;

Java开发者 http://www.chinajavaworld.com/ 那里Java资料比较全;

java.com.cn http://www.java.com.cn/ 看这域名就知道有多牛,注册用户快接近一万了,同时在线人数也在一千左右,人气很旺的;

IBM的开发者网络http://www-900.ibm.com/developerWorks/cn/java/index.shtml IBM永远的蓝色巨人;

那么我书也看了,程序也做了,别人问我的问题我都能解决了,是不是就成为高手了呢?当然没那么简单,这只是万里长征走完了第一步。不信?那你出去接一个项目,你知道怎么下手吗,你知道怎么设计吗,你知道怎么组织人员进行开发吗?你现在脑子里除了一些散乱的代码之外,可能再没有别的东西了吧!你现在最缺的是实际的工作经验,而不是书本上那些凭空想出来的程序。所以你快去找一份Java的编程工作来做吧(如果是在校学生可以去做兼职啊),在实践中提高自己,那才是最快的。不过你得祈祷在公司里碰到一个高手,而且他还愿意不厌其烦地教你,这样好象有点难哦!

还有一个办法就是读开放源码的程序了。我们知道开放源码大都出自高手,他们设计合理,考虑周到,再加上有广大的程序员参与,代码的价值自然是字字珠叽,铿锵有力(对不起,偶最近《金装四大才子》看多了)。学Java必读的两个开源程序就是Jive和Pet Store.。Jive是国外一个非常著名的BBS程序,完全开放源码。论坛的设计采用了很多先进的技术,如Cache、用户认证、Filter、XML等,而且论坛完全屏蔽了对数据库的访问,可以很轻易的在不同数据库中移植。论坛还有方便的安装和管理程序,这是我们平时编程时容易忽略的一部份(中国程序员一般只注重编程的技术含量,却完全不考虑用户的感受,这就是我们与国外软件的差距所在)。 Jive的资料在很多网站上都有,大家可以找来研究一下。相信你读完代码后,会有脱胎换骨的感觉。遗憾的是Jive从2.5以后就不再无条件的开放源代码,同时有licence限制。不过幸好还有中国一流的Java程序员关注它,外国人不开源了,中国人就不能开源吗?这里向大家推荐一个汉化的Jive版本?J道。Jive(J道版)是由中国Java界大名鼎鼎的banq在Jive 2.1版本基础上改编而成, 全中文,增加了一些实用功能,如贴图,用户头像和用户资料查询等,而且有一个开发团队在不断升级。你可以访问banq的网站http://www.jdon.com/  去下载,或到同济技术论坛的服务器上ftp://nro.shtdu.edu.cn去下,安装上有什么问题,可以到论坛上去提问。Pet Store. (宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要错过了。

你一定会高兴地说,哈哈,原来成为Java高手就这么简单啊!记得Tomjava也曾碰到过一个项目经理,号称Java很简单,只要三个月就可以学会。其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧,让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。关于设计模式的资料,还是向大家推荐banq的网站http://www.jdon.com/ ,他把GOF的23种模式以通俗易懂的方式诠释出来,纯Java描述,真是经典中的经典。有时间再研究一下MVC结构(把Model-View- Control分离开的设计思想)吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring(重整)和极限XP编程,相信你又会上一个台阶。

做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧,你可以去承接一些项目做了,一开始可能有些困难,可是你有技术积累,又考虑周全,接下项目来可以迅速作完,相信大家以后都会来找你的,所以 Money就哗啦啦的来了。。。。。。

当然你也可以参加一些开源项目,一方面可以提高自己,另一方面也是为中国软件事业做贡献嘛!开发者在互联网上用CVS合作开发,用QQ,MSN,E-mail讨论联系,天南海北的程序员分散在各地却同时开发同一个软件,是不是很有意思呢?

下面介绍两个好的开源项目网站:

湖北省软件公共开发平台http://gro.clinux.org/

共创联盟http://cosoft.org.cn/

哇,好高兴哦,我终于成为高手了!非也,非也。古人云:“识时务者为俊杰”。你知道计算机界现在的发展形势吗?你知道微软的.NET蓝图和SUN ONE计划之间的明争暗斗吗?你知道计算机技术将向何处发展吗?其实从各大计算机厂商最近的动作,都可以看出来“Web服务将是下一代互联网应用的制高点”,而微软的.NET蓝图和SUN ONE计划的斗争焦点,也就是Web服务。Web服务就是一个崭新的分布式计算模型,它是一系列标准的综合(XML,SOAP, UDDI,WSDL和WSFL等)。它使得不同语言编写的软件能够轻易的集成起来,使网络资源和Web站点变成一种服务而不是混乱的垃圾场。不远的将来,我们就可以在家里点击一下鼠标,就可以完成出门旅游的全部准备工作,包括定飞机票,定旅游线路,定好房间等。请注意,这所有的一切都是Web站点间自动完成的,再也不用象现在一样,表面上是电子商务,实际上很多环节都是人工操作。也许你会觉得这是天方夜谈,不过就近的说,你也很有可能承接一个项目,要集成两个企业的ERP系统。很有可能上游企业的系统是用Dephi编的,而下游企业的系统是用Java编的。你说你是Java高手,大家都看者你怎么做呢。所以啊,你还得学习新技术,如Web服务,而且你Dephi也要懂一点吧(Dephi6现在已经提供Web服务的控件了)。 你编的Java系统,可能要和.NET集成,所以你.NET要懂一点吧?到最后,你可能发现你已经成为Java高手了,但很多时间却在搞别的技术。太极张三丰里说,最厉害的招式就是没有招式,可能就是这个道理吧!

因为刚刚兴起,所以网上Web服务的资料不是很多,我还是给大家推荐几个网站吧:

中国UDDI技术联盟http://www.uddi-china.org/

CSDN的柴晓路专栏http://www.csdn.net/develop/author/ColumnAuthor/fennivel/ (注:柴晓路也是互联网上一个有名的人物,他发表过很多关于Web服务的文章,还出了一书,应该称的上是中国Web服务技术的先行者)

IBM的开发者网络的XML&Web Service专栏:

http://www-900.ibm.com/developerWorks/cn/xml/index.shtml?csdn IBM可是Web服务的力推者

呜…你费劲千心万苦,总算成为Java高手了,怎叫人不由喜极而泣呢!是啊,真不容易,真不简单,真叫人感动啊!那么打个电话告诉我吧,什么?我的电话号码是多少?昏到,你打电话问不就知道了吗,真是的……

********************************************************************************************************

                                                                    转帖完毕  

Java中的静态内部类(static inner class)

在学习Thinking in Patterns with Java的Pattern refactoring中的//: refactor:trash:Trash.java的源代码时,发现静态内部类的使用,如下:


//: refactor:trash:Trash.java

// Base class for Trash recycling examples.

package refactor.trash;

import java.util.*;

import java.lang.reflect.*;

public abstract class Trash {

  ...//略去部分代码

  public static class Messenger {

    public String id;

    public double data;

    public Messenger(String name, double val) {

      id = name;

      data = val;

    }

  }

  ...//略去部分代码

  public static Trash factory(Messenger info) {

    ...//略去部分代码

  }

} ///:~

后面使用Messager类是这样的:


Trash.factory(new Trash.Messenger(type, weight))

经过查阅资料,得出下面的理解:

1、为什么用内部类?

答:因为Messenger的作用仅是为产生Trash而使用来封装信息的辅助类,其它地方也用不着,所以放在Trash类的内部;

2、为什么用静态的内部类?

答:因为使用静态的内部类可以在其包含它的外部类没有生成实际对象时生成这个内部类,而在这里,在Messenger对象生成之前根本就不能生成它的外部类Trash的对象;就算是其它某种情况可以先生成外部类,如果没有先生成外部类的必要性,我认为,应该尽量使用静态内部类,因为,何必要生成一个没有用的多余的外部类对象呢?(这个观点没有深入的的学习和验证,也许不正确!

参考资料:

1、Thinking in Java, 3rd ed. Revision 4.0 Nested classes

./aaa-TIJ3-distribution/html/TIJ310.htm#Heading7630


when you say an inner class is static. A nested class means: Feedback

   1. You don’t need an outer-class object in order to create an object of a nested class. Feedback

   2. You can’t access a non-static outer-class object from an object of a nested class. Feedback

2、一篇完整叙述Java内部类的文章:

转:java内部类

始终没有搞懂Java中的字符编码问题

在本站动态页面静态化中,使用的是用程序访问网页,然后把返回的内容写入静态文件。由于本站是采用UTF-8编码,所以,保存的静态文件就要以UTF-8格式保存。

在我本机的环境下(redhat linux9.0 + jdk1.4.2 + tomcat5 )和现在的空间环境windows2000 advanced + jdk1.5 + Resin3.0.18下,使用下面的代码可以正确保存为UTF-8静态文件:


/*

 * Created on 2006-12-1

 */

package com.learndiary.website.util;

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import com.learndiary.website.model.UserInfo;

public class ToHtml extends HttpServlet {

private static Log __log = LogFactory.getFactory().getInstance("com.learndiary.website.util.ToHtml");

public void service(

HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

String url = "";

String name = "";

ServletContext sc = getServletContext();

String fileName = request.getParameter("fileName");

String artID = request.getParameter("artID");

String pageNum = request.getParameter("pageNum");

String webPath = null;

        if (fileName.equals("main")){

url = "/main.do";

webPath = "/index.htm";

__log.info("main url is: " + url +" ; static html file name is: " + webPath);

}else if(fileName.equals("goal")){

url = "/disGoalContentAction.do?goalID=" + artID; // 你要生成的页面的文件名。

webPath = "/goals/" + artID + ".htm";

__log.info("goal url is: " + url +" ; static html file name is: " + webPath);

}else if(fileName.equals("diary")){

    url = "/disDiaryContentAction.do?goalID=" + artID; // 你要生成的页面的文件名。

    webPath = "/diaries/" + artID + ".htm";

    __log.info("diary url is: " + url +" ; static html file name is: " + webPath);

    }else if(fileName.equals("sitemap")){

    url = "/mapGenerateAction.do?artID=" + artID + "&pageNum=" + pageNum ; // 你要生成的页面的文件名。

    int articleID = Integer.parseInt(artID);

    if (articleID == 0){

        webPath = "/sitemaps/goals-" + pageNum + ".htm";

    }else if (articleID > 0){

        webPath = "/sitemaps/goal" + artID + "-" + pageNum + ".htm";

    }

    __log.info("sitemap url is: " + url +" ; static html file name is: " + webPath);

    }

        name = request.getRealPath(webPath);

       

        __log.info("real name is: " + name);

       

RequestDispatcher rd = sc.getRequestDispatcher(url);

final ByteArrayOutputStream os = new ByteArrayOutputStream();

final ServletOutputStream stream = new ServletOutputStream() {

public void write(byte[] data, int offset, int length) {

os.write(data, offset, length);

}

public void write(int b) throws IOException {

os.write(b);

}

};

final PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));

HttpServletResponse rep = new HttpServletResponseWrapper(response) {

public ServletOutputStream getOutputStream() {

return stream;

}

public PrintWriter getWriter() {

return pw;

}

};

rep.setContentType("text/html; charset=UTF-8");

rd.include(request, rep);

pw.flush();

FileOutputStream fos = new FileOutputStream(name);



byte[] ob= os.toByteArray();

//String string =new String(ob, "GB2312");//在本站如果输入繁体字等这样不能显示繁体字(应该是只能正确处理GB2312的内容)

String string =new String(ob);//这样才能正确处理繁体字

byte[] ob2 = string.getBytes("UTF-8");

fos.write(ob2);

        //os.writeTo(fos);

fos.close();

String jspName = webPath.replaceAll(".htm", ".jsp");

if (!HtmlsManager.isExist(jspName, request)){ //write another same name's jsp static file that will include html file

FileOutputStream jspFos = new FileOutputStream(name.replaceAll(".htm", ".jsp"));

String content = "<%@ include file=\"/common/jsp301.jsp\" %>".concat("<jsp:include page=\"" + webPath + "\" />");

byte[] jspOb = content.getBytes("UTF-8");

jspFos.write(jspOb);

jspFos.close();

__log.info("wrote static file name in ToHtml.java is: " + jspName + ", and content is: " + content);

}

__log.info("wrote static file name in ToHtml.java is: " + name);



}

}

而在原来的空间环境下:windows2000 advanced + jdk1.5 + Resin2下,上面红色的部分必须为下面的代码才行,否则是乱码:


FileOutputStream fos = new FileOutputStream(name);

        os.writeTo(fos);

fos.close();

String jspName = webPath.replaceAll(".htm", ".jsp");

if (!HtmlsManager.isExist(jspName, request)){ //write another same name's jsp static file that will include html file

FileOutputStream jspFos = new FileOutputStream(name.replaceAll(".htm", ".jsp"));

String content = "<%@ include file=\"/common/jsp301.jsp\" %>".concat("<jsp:include page=\"" + webPath + "\" />");

byte[] jspOb = content.getBytes();

jspFos.write(jspOb);

jspFos.close();

__log.info("wrote static file name in ToHtml.java is: " + jspName + ", and content is: " + content);

}

__log.info("wrote static file name in ToHtml.java is: " + name);

由于我对上面文件操作和字符编码的掌握也是模棱两可的,也不知道为什么要这样做,只知道这样做的结果是正确的。所以,就算是结果正确,上面的代码也很有可能有问题。像这些基础的技术确实应该真正理解和掌握。

这里有一个JAVA字符编码讲得比较透彻的文章,以后可以照着学一下。

    上篇:http://www.pconline.com.cn/pcedu/empolder/gj/java/0404/366404.html

    下篇:http://www.pconline.com.cn/pcedu/empolder/gj/java/0405/368760.html

搞懂java中的synchronized关键字

实际上,我关于java的基础知识的90%以上都来自Thinking in Java。对于其中的synchronized关键字,当时就是浏览一下,大概知道意思,也没有细看。后来一直没有用过这个关键字。昨天看Thinking in Patterns with Java中的Observer模式,看了其中的Observable类的源码,发现里面几乎所有的方法都用了synchronized关键字(不是全部),其中个别用了synchronized(this){}的区块。于是,我发觉有必要好好理解一下这个关键字了。

我再次看了侯捷译的Thinking in Java第二版中文版,得到有关synchronized的如下信息:

1、synchronized关键字的作用域有二种:

1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;

2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;

4、疑问:

我知道了有static区块(其中的加载时机好像也不清楚,需要学习一下,原来看Thinking in Java好像是说: static区块加载的时机是类的一个对象实例创建或类的一个static方法被访问,但是我今天早上看了javaeye.com上面的一个关于“<static块到底什么时候执行?-eway -JavaEye技术社区>”的文章后又有点迷糊了:),也许,需要认真学习一下JVM的内在机制才是理解这类问题最根本的途径),也有synchronized区块,那么,有synchronized static 区块吗?意思是问:有没有一个类作用域内的synchronized区块?