第一篇:Java工程师浅谈java技术的8大优势(程序员必看,精心整理,免分数)
Java工程师浅谈java技术的8大优势
java工程师浅谈java技术的8大优势,与Java本身相比,Java API更是可贵的免费财富。想使用Socket操作网络?API中有;想连接到SQL数据库?API中有;想给应用程序一个漂亮的用户界面?API中有。
1.免费!
Sun(虽然现在已被甲骨文收购但我还是喜欢说Sun)免费提供用来开发Java应用程序的一切,你不必付任何的版税。或许你会将信将疑:资本家搞共产了?实际上,Sun在Java上的收益确实不大,远远比不过垄断Java应用服务器技术的IBM和BEA公司,似乎有替别人做嫁衣之嫌。对此,Sun董事长、总裁兼首席执行官Scott McNealy是这样解释的:“Sun并没有用Java赚钱,这就像使用英语不用上税一样,Sun并不通过Java本身来盈利,而是把Java应用到了业务中。”原来是放长线钓大鱼!
与Java本身相比,Java API更是可贵的免费财富。想使用Socket操作网络?API中有;想连接到SQL数据库?API中有;想给应用程序一个漂亮的用户界面?API中有;想要处理数字图形、播放音乐、解析字符串或者创建数字签名?API中全都有。
最后,Java发展了那么多年,优秀的Java教程、技术网站数不胜数。Bruce Eckel大师的名作Java编程思想(Thinking in java)更是不可不读的佳作,许多狂热爱好者甚至把它当做圣经一样一页一页仔细揣摩。你可到作者的主页http://免费下载此书的电子版。机械工业出版社也有引进台湾技术作家候捷的中译本,可惜不是免费。
或许你会问,有了那么多优秀的教程,还要你这个Java咖啡馆干什么呢?嗯哼,虽然那些教程和技术文章是如此优秀,但并不适合初学者。Java咖啡馆目的就在于帮助你打好Java技术的基础,掌握Java技术的主要脉络,帮助你迈出进入Java世界的第一步!
2.跨平台
“一次编写,随处运行”,Java系统可以运行在不同的操作系统和硬件上。随着Linux的持续增长以及Mac OSX完全支持Java技术,跨平台的特性变得越来越有分量。
由于Java跨平台,Java API自然也是平台统一的。对程序员而言,没有比统一的API函数能够让他们更欣慰的了——已经有了圆形的轮子,何必再从头发明轮子呢?我们拿Java API与C++的类库相比便可以知道它的可贵之处。有Windows编程经验的C++程序员肯定经历过被MFC(Microsoft Foundation Classes,微软基类库)折磨的日子,学习曲线陡峭,没有若干个月根本无法开始生产,一段时间不接触遗忘率又高。据说,即使在微软公司内部,除了 MFC开发小组,谁都不乐意用它。即便你熟悉了MFC,能够顺利开发Windows应用程序,如果你要编写一个Linux应用程序,MFC又派不上用场了,你必须学习Linux下C++开发的一套库函数。还有UNIX、FreeBSD、Mac OS„„你学得过来吗?反观Java API,操作系统,你爱谁是谁,只要编写一次便可随处运行!
3.在学术界获得了强有力的支持
由于免费、跨平台、Java语言本身技术先进,在高校中,Java 已经成为许多学科研究、课程和计算的首选语言,用Java做上机作业,一般都是鼓励的。据我所知,北大、清华许多院系的研究生入学考试都可以用Java语言答题。实际上,用Java来完成这些工作,大多数情况下要比用C或其他语言简洁得多,你可以把注意力集中在算法等核心部分,从而获得更高分数。
掌握Java技术的学生一般有更多的工作机会课余兼职,拿到更高报酬,不但减轻家里的负担,更可以让自己早日进入社会锻炼。所以,如果你还在求学,学习Java,一定没错的。
4.简单
与C++等语言相比较,语法上Java是简单的。
谢天谢地,Java提供了垃圾回收机制。以往C++的开发中,最容易出错误的地方便是内存管理,申请的内存用完以后必须释放,否则可使用的内存资源越来越少,直至耗尽系统资源而造成死机。而Java系统中,你可以任意申请内存,Java系统会在适当的时候自动释放无用的内存资源。这个神奇的机制叫做“垃圾回收”,节约了许多调试错误的时间。
在Java中,要写出低劣的代码也不是一件容易的事情。一方面,垃圾回收机制堵住了内存泄漏的可能性,另一方面就是异常捕捉机制,它强迫你做最坏的打算。编写程序时,难免会遇到一些意外,比如文件无法打开、网络读取失败等特殊情况。在C++等语言中是依靠返回值来判断的,如果一句句地检查返回值,那实在是太麻烦了。从而,程序员习惯性地忽略返回值的检查,并安慰自己一切都会好起来的。这便埋下了隐患。在Java中,Java的方法可以抛异常,而你必须应答异常,即使你不想进行任何操作。比如编写打开文件的代码,你不得不响应异常以防意外发生,否则程序根本不能够通过编译。未雨绸缪,使得 Java系统更稳健。
5.企业应用的成熟平台
这是Java技术目前最活跃的两大领域之一。我们在前面Java技术介绍中已经提到了不少,这里仅关注跟我们切身相关的优势。
Java技术的企业应用旨在提升企业竞争力,所以Java技术受到了企业的欣赏,市场份额是同类技术中最大的。同时,Java开放标准,所以供应商众多。市面上有许多的应用服务器、工具与构件可以选择,从高端的BEA WebLogic、IBM WebSphere等商业软件,到Tomcat、JBoss等开源的免费工具,一应俱全。作为Java技术的初学者,不需要任何花费就能够进行Java企业应用的自我培训,以后若参与Java的商业项目开发,便可以无缝地把软件移植到高端的商业平台上去。反观.Net,想免费自学,不盗版是不可能的啦。
最后谈谈Java和Web服务。Web服务是软件互操作历史上的里程碑,是技术发展的重要方向,是你绝不能不了解的技术。Sun公司是Java 语言的发明者,而作为一个开放的跨平台的技术体系,Java在Web服务的开发方面起着非常重要的作用。Sun被接纳为促进Web服务交互组织WS-I的董事成员后,作为活跃的参与者和业界的领导者,对Web服务互操作性的促进,有着相当重要的意义,也为Java技术的含金量加上了关键的砝码。
6.无线应用
这是Java技术目前最活跃的另一个领域,旨在提供更多、更方便的个性化服务的Java手机应用。未来几年内,势必将出现移动通讯运营商和移动设备应用软件的巨大商机和激烈竞争,并且该趋势很可能与电子政务、电子商务等其他发展相互影响。Java在手机市场的专有性和Java本身的开放性和标准性,使得越来越多的企业加入了Java阵营。
中国也不例外。2003年James Gosling博士首次来到中国,其中重要的一项工作便是与中国联通结盟。
黄糖故事
Java之父——James Gosling博士
James Gosling博士以“Java技术之父”闻名于世。他是Java技术的创始人,作为Sun研究院院士,亲手设计了Java语言,完成了Java技术的原始编译器和虚拟机。在他的带领下,Java现已成为互联网的标准编程模式以及分布式企业级应用的事实标准,其跨平台的技术优势为网络计算带来了划时代的变革。目前,Gosling博士积极致力于软件开发工具的研究,以使软件开发工具的功能更强大,更容易为开发人员所使用,确保应用、服务开发的迅速完成。
实际上,手机游戏开发也是一项不错的职业与机遇,成功的例子已经不在少数哦。
7.开放的Java社团——Java Community Process,JCP
JCP是一个让Java出名的功臣。JCP创造了一个开放型论坛,让同好在此交换意见,探索、定义新的平台,群策群力。Java欢迎竞争,因为只有这样才能最大限度地提高领域内的技术,这点与对手微软.Net技术大相径庭。在Java的舞台上有很多演员,任何人都可以参与到JCP的过程中去,帮助Sun决定Java的发展和未来,同时也挑战自己的影响力。从而,你可以发现Java世界中新的名词层出不穷,远远走在规范之前。而在微软.Net技术的舞台上,你只能看到一个演员,那就是微软自己。还有现在的Java技术交流论坛,J道等等。。都是很不错错的开放社区。
8.开源组织或者非盈利机构的支持
开源组织是无政府主义的梦想——没有政体,没有所属权,言论与行动自由,仅仅依靠渴望共享与交流的信仰及无私奉献来维系。Java世界中,开源组织与非盈利机构发挥到了极致,许多出色的工具都出自它们之手。比如JUnit、Cactus、Tomcat、Struts、JBoss、Eclipse、ANT、Xerces、Hibernate、Axis、AspectJ等等,许多工具还会出现在我们的咖啡馆中,扮演重要的角色。
Java世界中,便宜无好货绝对不成立,这些工具拥有足以和商业软件媲美的质量,很多商业IDE还集成了这些工具。对Java程序员而言,生活不单单会变得轻松,更重要的,你能够看到希望,有为大家贡献自己力量的机会!
第二篇:JAVA时间格式化处理-JAVA程序员JAVA工程师面试必看
-JAVA程序员JAVA工程师面试必看
JAVA时间格式化处理 日期格式化
import java.util.Date;import java.text.SimpleDateFormat;class dayTime { public static void main(String args[]){ Date nowTime=new Date();System.out.println(nowTime);SimpleDateFormat time=new SimpleDateFormat(“yyyy MM dd HH mm ss”);System.out.println(time.format(nowTime));} }
2007-05-17 09:54 转载地址
http://tb.blog.csdn.net/TrackBack.aspx?PostId=3809041、通过MessageFormat转化
String dateTime = MessageFormat.format(“{0,date,yyyy-MM-dd-HH-mm:ss:ms}” , new Object[] { new java.sql.Date(System.currentTimeMillis())});说明: yyyy-MM-dd-HH-mm:ss:ms 年yyyy 月MM 日dd 时(大写为24进制,小写为12进制)分mm 秒ss 微妙ms
2、修改数据库时用
queryDataSet.setDate(“dateField”, new java.sql.Date(new java.util.Date().getTime()));queryDataSet.setDate(“dateField”, new java.sql.Date.valueOf(“2005-05-03”));
3、通过SimpleDateFormat 转化
SimpleDateFormat dateFm = new SimpleDateFormat(“yyyy-MM-dd”);//格式化当前系统日期 String dateTime = dateFm.format(new java.util.Date());
4、具体讨论
Java 语言的Calendar(日历),Date(日期), 和DateFormat(日期格式)组成了Java标准的一个基本但是非常重要的部分.日期是商业逻辑计算一个关键的部分.所有的开发者都应该能够计算未来的日期, 定制日期的显示格式, 并将文本数据解析成日期对象.我们写了两篇文章, 这是第一篇, 我们将大概的学习日期, 日期格式, 日期的解析和日期的计算.我们将讨论下面的类:
1、具体类(和抽象类相对)java.util.Date
2、抽象类java.text.DateFormat 和它的一个具体子类,java.text.SimpleDateFormat
3、抽象类java.util.Calendar 和它的一个具体子类,java.util.GregorianCalendar
具体类可以被实例化, 但是抽象类却不能.你首先必须实现抽象类的一个具体子类.Date 类从Java 开发包(JDK)1.0 就开始进化, 当时它只包含了几个取得或者设置一个日期数据的各个部分的方法, 比如说月, 日, 和年.这些方法现在遭到了批评并且已经被转移到了Calendar类里去了, 我们将在本文中进一步讨论它.这种改进旨在更好的处理日期数据的国际化格式.就象在JDK 1.1中一样, Date 类实际上只是一个包裹类, 它包含的是一个长整型数据, 表示的是从GMT(格林尼治标准时间)1970年, 1 月 1日00:00:00这一刻之前或者是之后经历的毫秒数.一、创建一个日期对象
让我们看一个使用系统的当前日期和时间创建一个日期对象并返回一个长整数的简单例子.这个时间通常被称为Java 虚拟机(JVM)主机环境的系统时间.//-----------------------import java.util.Date;
public class DateExample1 { public static void main(String[] args){ // Get the system date/time Date date = new Date();
System.out.println(date.getTime());} } //-----------------------
在星期六, 2001年9月29日, 下午大约是6:50的样子, 上面的例子在系统输出设备上显示的结果是 1001803809710.在这个例子中,值得注意的是我们使用了Date 构造函数创建一个日期对象, 这个构造函数没有接受任何参数.而这个构造函数在内部使用了System.currentTimeMillis()方法来从系统获取日期.那么, 现在我们已经知道了如何获取从1970年1月1日开始经历的毫秒数了.我们如何才能以一种用户明白的格式来显示这个日期呢? 在这里类java.text.SimpleDateFormat 和它的抽象基类 java.text.DateFormat 就派得上用场了.二、日期数据的定制格式 假如我们希望定制日期数据的格式, 比方星期六-9月-29日-2001年.下面的例子展示了如何完成这个工作:
//-----------------------import java.text.SimpleDateFormat;import java.util.Date;
public class DateExample2 {
public static void main(String[] args){
SimpleDateFormat bartDateFormat = new SimpleDateFormat(“EEEE-MMMM-dd-yyyy”);
Date date = new Date();
System.out.println(bartDateFormat.format(date));} } //-----------------------
只要通过向SimpleDateFormat 的构造函数传递格式字符串“EEE-MMMM-dd-yyyy”, 我们就能够指明自己想要的格式.你应该可以看见, 格式字符串中的ASCII 字符告诉格式化函数下面显示日期数据的哪一个部分.EEEE是星期, MMMM是月, dd是日, yyyy是年.字符的个数决定了日期是如何格式化的.传递“EE-MM-dd-yy”会显示 Sat-09-29-01.请察看Sun 公司的Web 站点获取日期格式化选项的完整的指示.三、将文本数据解析成日期对象
假设我们有一个文本字符串包含了一个格式化了的日期对象, 而我们希望解析这个字符串并从文本日期数据创建一个日期对象.我们将再次以格式化字符串“MM-dd-yyyy” 调用SimpleDateFormat类, 但是这一次, 我们使用格式化解析而不是生成一个文本日期数据.我们的例子, 显示在下面, 将解析文本字符串“9-29-2001”并创建一个值为001736000000 的日期对象.//-----------------------import java.text.SimpleDateFormat;import java.util.Date;
public class DateExample3 {
public static void main(String[] args){ // Create a date formatter that can parse dates of // the form MM-dd-yyyy.SimpleDateFormat bartDateFormat = new SimpleDateFormat(“MM-dd-yyyy”);
// Create a string containing a text date to be parsed.String dateStringToParse = “9-29-2001”;
try { // Parse the text version of the date.// We have to perform the parse method in a // try-catch construct in case dateStringToParse // does not contain a date in the format we are expecting.Date date = bartDateFormat.parse(dateStringToParse);
// Now send the parsed date as a long value // to the system output.System.out.println(date.getTime());} catch(Exception ex){ System.out.println(ex.getMessage());} } } //-----------------------
四、使用标准的日期格式化过程
既然我们已经可以生成和解析定制的日期格式了, 让我们来看一看如何使用内建的格式化过程.方法 DateFormat.getDateTimeInstance()让我们得以用几种不同的方法获得标准的日期格式化过程.在下面的例子中, 我们获取了四个内建的日期格式化过程.它们包括一个短的, 中等的, 长的, 和完整的日期格式.//-----------------------import java.text.DateFormat;import java.util.Date;
public class DateExample4 {
public static void main(String[] args){ Date date = new Date();
DateFormat shortDateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
DateFormat mediumDateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
DateFormat longDateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
DateFormat fullDateFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
System.out.println(shortDateFormat.format(date));System.out.println(mediumDateFormat.format(date));System.out.println(longDateFormat.format(date));System.out.println(fullDateFormat.format(date));} } //-----------------------
注意我们在对 getDateTimeInstance的每次调用中都传递了两个值.第一个参数是日期风格, 而第二个参数是时间风格.它们都是基本数据类型int(整型).考虑到可读性, 我们使用了DateFormat 类提供的常量: SHORT, MEDIUM, LONG, 和 FULL.要知道获取时间和日期格式化过程的更多的方法和选项, 请看Sun 公司Web 站点上的解释.运行我们的例子程序的时候, 它将向标准输出设备输出下面的内容: 9/29/01 8:44 PM Sep 29, 2001 8:44:45 PM September 29, 2001 8:44:45 PM EDT Saturday, September 29, 2001 8:44:45 PM EDT
五、Calendar 类
我们现在已经能够格式化并创建一个日期对象了, 但是我们如何才能设置和获取日期数据的特定部分呢, 比如说小时, 日, 或者分钟? 我们又如何在日期的这些部分加上或者减去值呢? 答案是使用Calendar 类.就如我们前面提到的那样, Calendar 类中的方法替代了Date 类中被人唾骂的方法.假设你想要设置, 获取, 和操纵一个日期对象的各个部分, 比方一个月的一天或者是一个星期的一天.为了演示这个过程, 我们将使用具体的子类 java.util.GregorianCalendar.考虑下面的例子, 它计算得到下面的第十个星期五是13号.//-----------------------import java.util.GregorianCalendar;import java.util.Date;import java.text.DateFormat;
public class DateExample5 {
public static void main(String[] args){ DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);
// Create our Gregorian Calendar.GregorianCalendar cal = new GregorianCalendar();
// Set the date and time of our calendar // to the system&s date and time cal.setTime(new Date());
System.out.println(“System Date: ” + dateFormat.format(cal.getTime()));
// Set the day of week to FRIDAY cal.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.FRIDAY);System.out.println(“After Setting Day of Week to Friday: ” + dateFormat.format(cal.getTime()));
int friday13Counter = 0;
while(friday13Counter <= 10){
// Go to the next Friday by adding 7 days.cal.add(GregorianCalendar.DAY_OF_MONTH, 7);
// If the day of month is 13 we have // another Friday the 13th.if(cal.get(GregorianCalendar.DAY_OF_MONTH)== 13){ friday13Counter++;System.out.println(dateFormat.format(cal.getTime()));} } } } //-----------------------
在这个例子中我们作了有趣的函数调用: cal.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.FRIDAY);和: cal.add(GregorianCalendar.DAY_OF_MONTH, 7);
set 方法能够让我们通过简单的设置星期中的哪一天这个域来将我们的时间调整为星期五.注意到这里我们使用了常量 DAY_OF_WEEK 和 FRIDAY来增强代码的可读性.add 方法让我们能够在日期上加上数值.润年的所有复杂的计算都由这个方法自动处理.我们这个例子的输出结果是: System Date: Saturday, September 29, 2001 当我们将它设置成星期五以后就成了: Friday, September 28, 2001 Friday, September 13, 2002 Friday, December 13, 2002 Friday, June 13, 2003 Friday, February 13, 2004 Friday, August 13, 2004 Friday, May 13, 2005 Friday, January 13, 2006 Friday, October 13, 2006 Friday, April 13, 2007 Friday, July 13, 2007 Friday, June 13, 2008
六、时间掌握在你的手里
有了这些Date 和Calendar 类的例子, 你应该能够使用 java.util.Date, java.text.SimpleDateFormat, 和 java.util.GregorianCalendar 创建许多方法了.5、具体讨论2 这里只讨论java中对日期的几个简单类: 1.java.util.Date 2.java.text.DateFormat(Abstract),java.text.SimpleDateFormat 3.java.util.Calendar(Abstract),java.util。GregorianCalendar 首先看一下Date类,Date中只提供了几个获得本地时间的方法,具体用法见下: import java.util.Date; public class DateFormatTest { public DateFormatTest(){ }
public static void main(String[] args){ Date dt=new Date();
String localeString=dt.toLocaleString(); String gmtString=dt.toGMTString(); System.out.println(localeString); System.out.println(gmtString); System.out.println(dt.getTime());
System.out.println(System.currentTimeMillis()); } } 输出结果为: 2004-12-31 9:34:04 31 Dec 2004 01:34:04 GMT 1104456844281 1104456844500 从结果中可以看到,dt.getTime()与System.currentTimeMillis()这两个方法得到的时间是相同的。因为Date的构造函数中调用了System.currentTimeMillis()方法来从系统获得当前时间。其结果实际上是从1970年1月1日开始到当前所经历的毫秒数。以下的例子展示的是一个简单的格式化日期的代码: import java.text.*; import java.util.Locale; import java.util.Date; public class DateFormatTest { public DateFormatTest(){ }
public static void main(String[] args){ DateFormat df=DateFormat.getDateInstance();
SimpleDateFormat defaultSDF=new SimpleDateFormat(); SimpleDateFormat sdf=new SimpleDateFormat(“yyyy-MM-dd”); System.out.println(new Date());
System.out.println(df.format(new Date())); System.out.println(defaultSDF.format(new Date())); System.out.println(sdf.format(new Date())); }}
输出结果是:
Fri Dec 31 09:48:19 CST 2004 2004-12-31 04-12-31 上午9:48 2004-12-31
SimpleDateFormat的构造函数中String中字符的含义列如下表: Letter Date or Time Component Presentation Examples G Era designator Text AD y Year Year 1996; 96 M Month in year Month July; Jul; 07 w Week in year Number 27 W Week in month Number 2 D Day in year Number 189 d Day in month Number 10 F Day of week in month Number 2 E Day in week Text Tuesday; Tue a Am/pm marker Text PM H Hour in day(0-23)Number 0 k Hour in day(1-24)Number 24 K Hour in am/pm(0-11)Number 0 h Hour in am/pm(1-12)Number 12 m Minute in hour Number 30 s Second in minute Number 55 S Millisecond Number 978 z Time zone General time zone Pacific Standard Time; PST; GMT-08:00 Z Time zone RFC 822 time zon 上面展示的例子是将Date格式化成我们想要的格式,通常还会遇到需要将有些已经格式好的String再解析成Date的问题。在下面的文章中将会讲到。import java.text.*;import java.util.Locale;import java.util.Date;public class DateFormatTest { public DateFormatTest(){ } public static void main(String[] args){ String dateToparse=“30-12-2004”;
SimpleDateFormat sdf=new SimpleDateFormat(“dd-MM-yyyy”)Date dt=new Date()try{ dt=sdf.parse(dateToparse)System.out.print(dt)}catch(Exception e){ e.printStackTrace();}}}-JAVA程序员JAVA工程师面试必看
第三篇:java工程师技术集
Java 工程师
--高慧超
1.web技术:html、div、css、javascript、ajax、js框架(jquery,dwr、ext、prototype、dojo、等)、flax、mvc模式、xml
2.java技术:java基础(jvm、多线程、分布式、等)、jsp、servlet、java框架(struts、hibernate、spring、ibatis、ejb、jpa、等)、工作流(osworkflow、Jbpm、shark)、搜索引擎(Lucene)、报表等开源组件
3.数据库: sqlserver、mysql、orccle、db
24.工具:开发工具(eclipse、netbeans、等)、版本控制(cvs、svn)、uml建模(Rose、Jude、PowerDesigner、Visio等)、构建工具(ant、maven)、测试工具(junit、等)
5.系统服务:系统(Linux、Uinux)、服务器(Tomcat、Jboss、Weblogic、等)
6行业熟悉:电信、金融、电力、电子商务、门口网、等
7.应用程度:精通、熟悉、了解、开发、测试、等
8职业素质:工作经验、善于沟通、团队合作、学习能力、逻辑能力、兴趣爱好、工作
踏实、组织实施、善于思考、创新能力、解决问题、敬业主动、宽容易处、有责任心、承受压力、自我激励、刻苦钻研、性格开朗
9.职业岗位:CIO/CTO系统架构师CEO/VP 学生 技术总监分析师财务主管 技
术爱好者 技术经理 数据库开发工程师 产品主管/业务主管 媒体人员
项目经理 数据库管理员生产管理/质量管理 公关/会展人员IT顾问
软件工程师销售/市场 行业协会工作者硬件工程师咨询/培训 软件
测试行政/人力资源硬件测试客户服务 网站运营管理采购 系统
管理员基建网络管理员库管/物流 互联网软件开发工程师 网络
工程师网络与信息安全工程师程序员/开发者 技术支持
第四篇:Java之reference-JAVA程序员JAVA工程师面试必看
-JAVA程序员JAVA工程师面试必看
Reference
Java世界泰山北斗级大作《Thinking In Java》切入Java就提出“Everything is Object”。在Java这个充满Object的世界中,reference是一切谜题的根源,所有的故事都是从这里开始的。
Reference是什么?
如果你和我一样在进入Java世界之前曾经浪迹于C/C++世界,就一定不会对指针陌生。谈到指针,往日种种不堪回首的经历一下子涌上心头,这里不是抱怨的地方,让我们暂时忘记指针的痛苦,回忆一下最初接触指针的甜蜜吧!还记得你看过的教科书中,如何讲解指针吗?留在我印象中的一种说法是,指针就是地址,如同门牌号码一样,有了地址,你可以轻而易举找到一个人家,而不必费尽心力的大海捞针。
C++登上历史舞台,reference也随之而来,容我问个小问题,指针和reference区别何在?我的答案来自于在C++世界享誉盛名的《More Effective C++》。
1.2.3.4.没有null reference。reference必须有初值。使用reference要比使用指针效率高。因为reference不需要测试其有效性。指针可以重新赋值,而reference总是指向它最初获得的对象
设计选择:
当你指向你需要指向的某个东西,而且绝不会改指向其它东西,或是当你实作一个运算符而其语法需要无法有指针达成,你就应该选择reference。其它任何时候,请采用指针。
这和Java有什么关系?
初学Java,鉴于reference的名称,我毫不犹豫的将它和C++中的reference等同起来。不过,我错了。在Java中,reference可以随心所欲的赋值置空,对比一下上面列出的差异,就不难发现,Java的reference如果要与C/C++对应,它不过是一个穿着reference外衣的指针而已。
于是,所有关于C中关于指针的理解方式,可以照搬到Java中,简而言之,reference就是一个地址。我们可以把它想象成一个把手,抓住它,就抓住了我们想要操纵的数据。如同掌握C的关键在于掌握指针,探索Java的钥匙就是reference。
一段小程序
我知道,太多的文字总是令人犯困,那就来段代码吧!
public class ReferenceTricks {
public static void main(String[] args){
ReferenceTricks r = new ReferenceTricks();
// reset integer
r.i = 0;
System.out.println(“Before changeInteger:” + r.i);
changeInteger(r);
System.out.println(“After changeInteger:” + r.i);
// just for format
System.out.println();
// reset integer
r.i = 0;
System.out.println(“Before changeReference:” + r.i);
changeReference(r);
System.out.println(“After changeReference:” + r.i);
}
private static void changeReference(ReferenceTricks r){
r = new ReferenceTricks();
r.i = 5;
System.out.println(“In changeReference: ” + r.i);
}
private static void changeInteger(ReferenceTricks r){
r.i = 5;
System.out.println(“In changeInteger:” + r.i);
}
public int i;
}
对不起,我知道,把一个字段设成public是一种不好的编码习惯,这里只是为了说明问题。
如果你有兴趣自己运行一下这个程序,我等你!
OK,你已经运行过了吗?结果如何?是否如你预期?下面是我在自己的机器上运行的结果:
Before changeInteger:0
In changeInteger:5
After changeInteger:5
Before changeReference:0
In changeReference: 5
After changeReference:0
这里,我们关注的是两个change——changeReference和changeInteger。从输出的内容中,我们可以看出,两个方法在调用前和调用中完全一样,差异出现在调用后的结果。
糊涂的讲解
先让我们来分析一下changeInteger的行为。
前面说过了,Java中的reference就是一个地址,它指向了一个内存空间,这个空间存放着一个对象的相关信息。这里我们暂时不去关心这个内存具体如何排布,只要知道,通过地址,我们可以找到r这个对象的i字段,然后我们给它赋成5。既然这个字段的内容得到了修改,从函数中返回之后,它自然就是改动后的结果了,所以调用之后,r对象的i字段依然是5。下图展示了changeInteger调用前后内存变化。
Reference +--------+Reference +--------+
---------->| i = 0|---------->| i = 5|
|--------||--------|
| Memory || Memory |
||||
||||
+--------++--------+
调用changeInteger之前调用changeInteger之后
让我们把目光转向changeReference。
从代码上,我们可以看出,同changeInteger之间的差别仅仅在于多了这么一句。
r = new ReferenceTricks();
这条语句的作用是分配一块新的内存,然后将r指向它。
执行完这条语句,r就不再是原来的r,但它依然是一个ReferenceTricks的对象,所以我们依然可以对这个r的i字段赋值。到此为止,一切都是那么自然。
Reference +--------++--------+
---------->| i = 0|| i = 0|
|--------||--------|
| Memory || Memory |
||Reference |--------|
||---------->| i = 5|
+--------++--------+
调用changeReference之前调用changeReference之后
顺着这个思路继续下去的话,执行完changeReference,输出的r的i字段,那么应该是应该是新内存中的i,所以应该是5。至于那块被我们抛弃的内存,Java的GC功能自然会替我们善后的。
事与愿违。
实际的结果我们已经看到了,输出的是0。
肯定哪个地方错了,究竟是哪个地方呢?
参数传递的秘密
知道方法参数如何传递吗?
记得刚开始学编程那会儿,老师教导,所谓参数,有形式参数和实际参数之分,参数列表中写的那些东西都叫形式参数,在实际调用的时候,它们会被实际参数所替代。
编译程序不可能知道每次调用的实际参数都是什么,于是写编译器的高手就出个办法,让实际参数按照一定顺序放到一个大家都可以找得到的地方,以此作为方法调用的一种约定。所谓“没有规矩,不成方圆”,有了这个规矩,大家协作起来就容易多了。这个公共数据区,现在编译器的选择通常是“栈”,而所谓的顺序就是形式参数声明的顺序。
显然,程序运行的过程中,作为实际参数的变量可能遍布于内存的各个位置,而并不一定要老老实实的呆在栈里。为了守“规矩”,程序只好将变量复制一份到栈中,也就是通常所说的将参数压入栈中。
打起精神,谜底就要揭晓了。
我刚才说什么来着?将变量复制一份到栈中,没错,“复制”!
这就是所谓的值传递。
C语言的旷世经典《The C Programming Language》开篇的第一章中,谈到实际参数时说,“在C中,所有函数的实际参数都是传„值‟的”。
马上会有人站出来,“错了,还有传地址,比如以指针传递就是传地址”。
不错,传指针就是传地址。在把指针视为地址的时候,是否考虑过这样一个问题,它也是一个变量。前面的讨论中说过了,参数传递必须要把参数压入栈中,作为地址的指针也不例外。所以,必须把这个指针也复制一份。函数中对于指针操作实际上是对于这个指针副本的操作。
Java的reference等于C的指针。所以,在Java的方法调用中,reference也要复制一份压入堆栈。在方法中对reference的操作就是对这个reference副本的操作。
谜底揭晓
好,让我们回到最初的问题上。
在changeReference中对于reference的赋值实际上是对这个reference的副本进行赋值,而对于reference的本尊没有产生丝毫的影响。
回到调用点,本尊醒来,它并不知道自己睡去的这段时间内发生过什么,所以只好当作什么都没发生过一般。就这样,副本消失了,在方法中对它的修改也就烟消云散了。
也许你会问出这样的问题,“听了你的解释,我反而对changeInteger感到迷惑了,既然是对于副本的操作,为什么changeInteger可以运作正常?”
呵呵,很有趣的大脑短路现象。
好,那我就用前面的说法解释一下changeInteger的运作。
所谓复制,其结果必然是副本完全等同于本尊。reference复制的结果必然是两个reference指向同一块内存空间。
虽然在方法中对于副本的操作并不会影响到本尊,但对内存空间的修改确实实实在在的。
回到调用点,虽然本尊依然不知道曾经发生过的一切,但它按照原来的方式访问内存的时候,取到的确是经过方法修改之后的内容。
于是方法可以把自己的影响扩展到方法之外。
多说几句
这个问题起源于我对C/C++中同样问题的思考。同C/C++相比,在changeReference中对reference赋值可能并不会造成什么很严重的后果,而在C/C++中,这么做却会造成臭名昭著的“内存泄漏”,根本的原因在于Java拥有了可爱的GC功能。即便这样,我仍不推荐使用这种的手法,毕竟GC已经很忙了,我们怎么好意思再麻烦人家。
在C/C++中,这个问题还可以继续引申。既然在函数中对于指针直接赋值行不通,那么如何在函数中修改指针呢?答案很简单,指针的指针,也就是把原来的指针看作一个普通的数据,把一个指向它的指针传到函数中就可以了。
同样的问题到了Java中就没有那么美妙的解决方案了,因为Java中可没有reference的reference这样的语法。可能的变通就是将reference进行封装成类。至于值不值,公道自在人心。
评论 09:50浏览(171)评论(1)分类:收藏相关推荐
2008-06-27
public class ReferenceTricks {
public static void main(String[] args){
ReferenceTricks r = new ReferenceTricks();
// reset integer
r.i = 0;
System.out.println(“Before changeInteger:” + r.i);
changeInteger(r);
System.out.println(“After changeInteger:” + r.i);
// just for format
System.out.println();
// reset integer
r.i = 0;
System.out.println(“Before changeReference:” + r.i);
changeReference(r);
System.out.println(“After changeReference:” + r.i);
}
private static void changeReference(ReferenceTricks r){
r = new ReferenceTricks();
r.i = 5;
System.out.println(“In changeReference: ” + r.i);
}
private static void changeInteger(ReferenceTricks r){
r.i = 5;
System.out.println(“In changeInteger:” + r.i);
}
public
举的例子不太相符,用来理解java传 参机制倒是不错的例子
-JAVA程序员JAVA工程师面试必看
第五篇:华为公司招聘java程序员面试题-JAVA程序员JAVA工程师面试必看
-JAVA程序员JAVA工程师面试必看
第一部分:选择题
QUESTION NO: 1
1、public class Test {
public static void changeStr(String str){
str=“welcome”;
}
public static void main(String[] args){
String str=“1234”;
changeStr(str);
System.out.println(str);
1234
}
}
Please write the output result :
QUESTION NO:2
1.public class Test {
2.static boolean foo(char c){
3.System.out.print(c);
4.return true;
5.}
6.public static void main(String[] argv){
7.int i =0;
8.for(foo('A');foo('B')&&(i<2);foo('C')){
9.i++;
10.foo('D');
12.}
13.}
14.}
What is the result?
A.ABDCBDCB
B.ABCDABCD
C.Compilation fails.D.An exception is thrown at runtime.QUESTION NO: 3
1.class A {
2.protected int method1(int a, int b){ return 0;}
3.}
Which two are valid in a class that extends class A?(Choose two)
A.public int method1(int a, int b){ return 0;}
B.private int method1(int a, int b){ return 0;}
C.private int method1(int a, long b){ return 0;}
D.public short method1(int a, int b){ return 0;}
E.static protected int method1(int a, int b){ return 0;}
QUESTION NO: 4
1.public class Outer{
2.public void someOuterMethod(){
3.// Line 3
4.}
5.public class Inner{}
6.public static void main(String[]argv){
7.Outer o = new Outer();
8.// Line 8
9.}
10.}
Which instantiates an instance of Inner?
A.new Inner();// At line 3
B.new Inner();// At line 8
C.new o.Inner();// At line 8
D.new Outer.Inner();// At line 8//new Outer().new Inner()
QUESTION NO: 5
Which method is used by a servlet to place its session ID in a URL that is written to the servlet’s response output stream?
A.The encodeURL method of the HttpServletRequest interface.B.The encodeURL method of the HttpServletResponse interface.C.The rewriteURL method of the HttpServletRequest interface.D.The rewriteURL method of the HttpServletResponse interface.QUESTION NO: 6
Which two are equivalent?(Choose two)
A.B.C.D.E.F.G.QUESTION NO: 7
Which of the following statements regarding the lifecycle of a session bean are correct?
1.java.lang.IllegalStateException is thrown if SessionContext.getEJBObject()is invoked when a stateful session bean instance is passivated.2.SessionContext.getRollbackOnly()does not throw an exception when a session bean with bean-managed transaction demarcation is activated.3.An exception is not thrown when SessionContext.getUserTransaction()is called in the afterBegin method of a bean with container-managed transactions.4.JNDI access to java:comp/env is permitted in all the SessionSynchronization methods of a stateful session bean with container-managed transaction demarcation.5.Accessing resource managers in the SessionSynchronization.afterBegin method of a stateful session bean with bean-managed transaction does not throw an exception.第二部分:概念题
1.描述Struts体系结构?对应各个部分的开发工作主要包括哪些?
3.JSP有哪些内置对象和动作?它们的作用分别是什么?
4、SQL问答题
SELECT * FROM TABLE
和
SELECT * FROM TABLE
WHERE NAME LIKE '%%' AND ADDR LIKE '%%'
AND(1_ADDR LIKE '%%' OR 2_ADDR LIKE '%%'
OR 3_ADDR LIKE '%%' OR 4_ADDR LIKE '%%')的检索结果为何不同?
5、SQL问答题
表结构:
1、表名:g_cardapply
字段(字段名/类型/长度):
g_applyno varchar 8;//申请单号(关键字)
g_applydate bigint 8;//申请日期
g_state varchar 2;//申请状态
2、表名:g_cardapplydetail
字段(字段名/类型/长度):
g_applyno varchar 8;//申请单号(关键字)
g_name varchar 30;//申请人姓名
g_idcard varchar 18;//申请人身份证号
g_state varchar 2;//申请状态
其中,两个表的关联字段为申请单号。
题目:
1、查询身份证号码为***的申请日期
2、查询同一个身份证号码有两条以上记录的身份证号码及记录个数
3、将身份证号码为***的记录在两个表中的申请状态均改为07
4、删除g_cardapplydetail表中所有姓李的记录
用友公司Java面试题
1.Hashtable和HashMap有什么区别?
a.Hashtable是继承自陈旧的Dictionary类的,HashMap继承自AbstractMap类同时是Java 1.2引进的Map接口的一个实现。
b.也许最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。这就意味着,虽然你可以不用采取任何特殊的行为就可以在一个
多线程的应用程序中用一个Hashtable,但你必须同样地为一个HashMap提供外同步。一个方便的方法就是利用Collections类的静态的synchronizedMap()方法,它创建一个线程安全的Map对象,并把它作为一个封装的对象来返回。这个对象的方法可以让你同步访问潜在的HashMap。
这么做的结果就是当你不需要同步时,你不能切断Hashtable中的同步(比如在一个单线程的应用程序中),而且同步增加了很多处理费用。
c.第三点不同是,只有HashMap可以让你将空值作为一个表的条目的key或value。
HashMap中只有一条记录可以是一个空的key,但任意数量的条目可以是空的value。
这就是说,如果在表中没有发现搜索键,或者如果发现了搜索键,但它是一个空的值,那么get()将返回null。
如果有必要,用containKey()方法来区别这两种情况。
d.HashMap去掉了Hashtable的contains方法,保留了containsValue和containsKey方法
e.Hashtable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数
2.你怎么理解MVC模式?
MVC是SUN早期提出的model2开发模式,强制的把视图控制和模型层分开
不仅实现了功能模块和显示模块的分离,同时它还提高了应用系统的可维护性、可扩展性、可移植性和组件的可复用性
3.SQLServer中左联接查询用left join,Oracle中用什么?
左连接:select(nvl(a.c,0)-nvl(b.c,0))from a,b where a.id(+)=b.id
右连接:select(nvl(a.c,0)-nvl(b.c,0))from a,b where a.id=b.id(+)
自连接:select(nvl(a.c,0)-nvl(b.c,0))from a,b where a.id(+)=b.id(+)
说明:加号写在左就是左连接,写在右就是右连接,看加号的方法来定
4.SQLServer中的数据库,在Oracle中对应的是什么?
表空间
5.如果SQLServer中有两个数据库,那么让你把这两个数据库对应到Oracle中,你应该怎么做?
在Oracle中建一个用户,对应两个表空间
6.有两个页面a.jsp和b.jsp,要从a.jsp传值到b.jsp有几种方法?分别是什么?
a:最常用的方法是用form中的text,,然后在b.jsp页面中这样获取
String username=request.getParameter(“username”);
b:直接在Url地址栏里面输入第一个页面的地址,在后加问号,然后把要传的参数及值写在后面,如有多个用&隔开,然后在下一页面用
request.getParameter(“
在b.jsp
参
数
名
”)
来
获
取,例
如
:http://localhost:8080/a.jsp?username=admin&password=111
中可用这样获取:String
username=request.getParameter(“username”);String username=request.getParameter(“password”);
c:在form中放hidden,如:,获取方法同上
说明:传值的方法有很多种,以上是最常用最简单的几种方式,当然,如果传的值有中文的话,需另做处理
6.有三个页面,a.jsp,b.jsp和c.jsp,流程是:a.jsp->b.jsp->c.jsp,其中a.jsp中提交的数据要在c.jsp中访问,用最简单的方法
怎么做?注意不能放在session里
用隐藏表单域,即在b.jsp页面中用N个hidden把上一页面提交过来的信息保存下来,然后和当前一起提交,再到c.jsp里面获取
说明:尽量不要用session和少用session 7.jsp和servlet有什么区别?
a:servlet是在java代码里面放html,jsp是在html里面放java代码(最后运行的时候服务器会把JSP解析成servlet)
b:servlet是一个java类,有自己的映射,而jsp不是
说明:区别太多,请参考http://00000000.net.cn/200606/200606097/97681.htm 8.映射是什么?你怎么理解映射?
映射即别名,通过别名可以访问
9.Hibernate中:不看数据库,不看XML文件,不看查询语句,怎么样能知道表结构?
看表结构对应的类文件,比如UserInfo表对应的UserInfo.java文件
10.SQLServer支持集群吗?
支持,但是是属于热备份类型,不能做负载平衡。不过符合你的条件。
首先系统做集群,数据库文件放到磁盘阵列里,双机或多机共同访问磁盘阵列,就可以了
IIS可以做集群后负载平衡。
11.为什么要用MVC?我从JSP页面直接访问数据库不是更简单吗,为什么非要先提交到控制再做处理?
MVC各施其职,互不干涉
在MVC模式中,三个层各施其职,所以如果一旦哪一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其它层中的代码。
有利于开发中的分工
在MVC模式中,由于按层把系统开,那么就能更好的实现开发中的分工。网页设计人员可以进行开发视图层中的JSP,对业务熟悉的开发人员可开发业务层,而其它开发人员可开发控制层。
有利于组件的重用
分层后更有利于组件的重用。如控制层可独立成一个能用的组件,视图层也可做成通用的操作界面
说明:这个好处就太多了!!
12.在struts中,假设有一个对数据库中一张表的增删改查的操作,你是写一个action还是写多个action?为什么?
写一个action,让这个action继承自DispatchAction,然后在struts-config.xml中给这个action映射加一参数,parameter=“method”
这个在提交到这个action中时,会根据传来的参数中method的值来执行相应的action的方法,比如,http://localhost:8080/login.do?method=doLogin
这个提交到action的时会自动找方法名叫doLogin的方法,参数返回值原来一样ActionForward 13.struts中的actionform有什么好处?
struts的actionform其实不好,里面有一堆属性,虽然可以自动填充,但是你会发现,在很多情况下(比如你用到Hibernate)
你还要需要自动写一个数据库表的映射类,通常是domain.UserInfo.java,这样就和strutsform中的属性重复,所以他很多余,struts1.1版本,保留了actionform,struts1.2中已经有了新的LazyValidatorForm,但仍然保留了原有的actionform,而在struts 2.0中已经把actionform去掉了
下面是解决方法
a: 把actionform换成DynaActionForm,和原来不同的是在dynaActionForm可以domain.UserInfo.java的一个实例做为他的一个属性
这样你就不需要在里面写一堆的get,set方法,只是在页面上绑定稍有不同
b: 把actionform换成org.apache.struts.validator.LazyValidatorForm,这样你完全不用写你的actionform这个类,直接在xml里面做
相应配置,当然也可以加上验证框架
警告:这个问题是陷阱,实际上struts的actionform很不好,非常麻烦,用久了你会发现他其实是多余的,所以这个问题你应该说他的坏处,和怎么把actonform去掉,请参考http://tqyq.blog.hexun.com/2911285_d.html 14.用过Hibernate吗,用它有什么好处?
Hibernate的最大的好处就是简化数据库的操作,允许你的代码以对象模式来访问数据库内容,比如通常我们找一个User的资料需要select出所需要的资料,而通过hibnate我们可以把这个User的资料作为一个对象来看待
,通过User.getName()或者User.getId()等操作来获得,这样就完全统一了上层JAVA或者C#等OO语言中对于数据库的非OO操作的不和谐了.另外对于复杂的表和表之间的关联我们也不用去使用复杂的Select等SQL来操作,而使用对象可以方便获得,比如多对多关系某用户属于的部门的名称,虽然底层数据库使用了3个表的主键关联操作,但是我们可以通过User.getDep().getName()来简单的获得,这个就是持久化对象的好处了
说明:好处太多,只能在用的过程中慢慢体会
只能说一个字:爽
15.通常所说的web应用程序分3层,即MVC,如果我想分四层,应该怎么分?
加一个Hibernate数据持久层
-JAVA程序员JAVA工程师面试必看