首页 > 代码库 > Java面试宝典2013版(超长版)
Java面试宝典2013版(超长版)
一. Java基础部分......................................................................................................2
1、一个".java"源文件里能否够包含多个类(不是内部类)?有什么限制?.....2
2、Java有没有goto?..........................................................................................2
3、说说&和&&的差别。......................................................................................2
4、在JAVA中怎样跳出当前的多重嵌套循环?...................................................2
5、switch语句是否能作用在byte上,是否能作用在long上,是否能作用在String上?...2
6、short s1 =1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?..................2
7、char型变量中能不能存贮一个中文汉字?为什么?............................................2
8、用最有效率的方法算出2乘以8等於几?2
9、请设计一个一百亿的计算器..........................................................................2
10、使用finalkeyword修饰一个变量时,是引用不能变,还是引用的对象不能变?2
11、"=="和equals方法到底有什么差别?...........................................................2
12、静态变量和实例变量的差别?.....................................................................2
13、能否够从一个static方法内部发出对非static方法的调用?........................2
14、Integer与int的差别.....................................................................................2
15、Math.round(11.5)等於多少?Math.round(-11.5)等於多少?...............................2
16、以下的代码有什么不妥之处?.......................................................................2
17、请说出作用域public,private,protected,以及不写时的差别.......................2
18、Overload和Override的差别。Overloaded的方法能否够改变返回值的类型?2
19、构造器Constructor是否可被override?..........................................................2
20、接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承详细类(concreteclass)?抽象类中能否够有静态的main方法?.......................................................................2
21、写clone()方法时,通常都有一行代码,是什么?.........................................2
22、面向对象的特征有哪些方面.........................................................................2
23、java中实现多态的机制是什么?..................................................................2
24、abstractclass和interface有什么差别?...........................................................2
25、abstract的method是否可同一时候是static,是否可同一时候是native,是否可同一时候是synchronized?2
26、什么是内部类?StaticNested Class 和 Inner Class的不同。..........................2
27、内部类能够引用它的包括类的成员吗?有没有什么限制?...........................2
28、AnonymousInner Class (匿名内部类)能否够extends(继承)其他类,能否够implements(实现)interface(接口)?...................................................................................................................2
29、super.getClass()方法调用.....................................................................2
30、String是最主要的数据类型吗?.....................................................................2
31、String s = "Hello";s = s + " world!";这两行代码运行后,原始的String对象中的内容究竟变了没有? 2
32、能否够继承String类?..............................................................................2
33、String s =new String("xyz");创建了几个String Object?二者之间有什么差别? 2
34、String和StringBuffer的差别.......................................................................2
35、怎样把一段逗号切割的字符串转换成一个数组?...........................................2
36、数组有没有length()这种方法?String有没有length()这种方法?...................2
37、以下这条语句一共创建了多少个对象:Strings="a"+"b"+"c"+"d";.................2
38、try {}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被运行,什么时候被运行,在return前还是后?.................................................................................................2
39、以下的程序代码输出的结果是多少?...........................................................2
40、final,finally, finalize的差别。......................................................................2
41、执行时异常与一般异常有何异同?..............................................................2
42、error和exception有什么差别?.....................................................................2
43、Java中的异常处理机制的简单原理和应用。................................................2
44、请写出你最常见到的5个runtimeexception。...............................................2
45、JAVA语言怎样进行异常处理,keyword:throws,throw,try,catch,finally分别代表什么意义?在try块中能够抛出异常吗?............................................................................................................2
46、java中有几种方法能够实现一个线程?用什么keyword修饰同步方法? stop()和suspend()方法为何不推荐使用?..........................................................................................................................2
47、sleep()和 wait() 有什么差别?.....................................................................2
48、同步和异步有何异同,在什么情况下分别使用他们?举例说明。.................2
49.以下两个方法同步吗?(自己发明)...........................................................2
50、多线程有几种实现方法?同步有几种实现方法?.............................................2
51、启动一个线程是用run()还是start()?............................................................2
52、当一个线程进入一个对象的一个synchronized方法后,其他线程是否可进入此对象的其他方法? 2
53、线程的基本概念、线程的基本状态以及状态之间的关系...............................2
54、简述synchronized和java.util.concurrent.locks.Lock的异同?.......................2
55、设计4个线程,当中两个线程每次对j添加1,另外两个线程对j每次降低1。写出程序。 2
56、子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。..................................................................................2
57、介绍Collection框架的结构..........................................................................2
58、Collection框架中实现比較要实现什么接口..................................................2
59、ArrayList和Vector的差别............................................................................2
60、HashMap和Hashtable的差别.......................................................................2
61、List和 Map 差别?......................................................................................2
62、List, Set,Map是否继承自Collection接口?....................................................2
63、List、Map、Set三个接口,存取元素时,各有什么特点?............................2
64、说出ArrayList,Vector,LinkedList的存储性能和特性......................................2
65、去掉一个Vector集合中反复的元素..............................................................2
66、Collection和 Collections的差别。...............................................................2
67、Set里的元素是不能反复的,那么用什么方法来区分反复与否呢?是用==还是equals()?它们有何差别? 2
68、你所知道的集合类都有哪些?主要方法?....................................................2
69、两个对象值同样(x.equals(y)== true),但却可有不同的hash code,这句话对不正确? 2
70、TreeSet里面放对象,假设同一时候放入了父类和子类的实例对象,那比較时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常!.................................................2
71、说出一些经常使用的类,包,接口,请各举5个................................................2
72、java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们各自是哪些类? 2
73、字节流与字符流的差别................................................................................2
74、什么是java序列化,怎样实现java序列化?或者请解释Serializable接口的作用。 2
75、描写叙述一下JVM载入class文件的原理机制?...................................................2
76、heap和stack有什么差别。..........................................................................2
77、GC是什么?为什么要有GC?.......................................................................2
78、垃圾回收的长处和原理。并考虑2种回收机制。.........................................2
79、垃圾回收器的基本原理是什么?垃圾回收器能够立即回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?..........................................................................................................................2
80、什么时候用assert。.....................................................................................2
81、java中会存在内存泄漏吗,请简单描写叙述。....................................................2
82、能不能自己写个类,也叫java.lang.String?.................................................2
83.Java代码查错......................................................................................................2
二.算法与编程.........................................................................................................2
1、编写一个程序,将a.txt文件里的单词与b.txt文件里的单词交替合并到c.txt文件里,a.txt文件里的单词用回车符分隔,b.txt文件里用回车或空格进行分隔。...................................................2
2、编写一个程序,将d:\java文件夹下的全部.java文件拷贝到d:\jad文件夹下,并将原来文件的扩展名从.java改为.jad。..........................................................................................................................2
3、编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串,但要保证汉字不被截取半个,如“我ABC”,4,应该截取“我AB”,输入“我ABC汉DEF”,6,应该输出“我ABC”,而不是“我ABC+汉的半个”。....................................................................................2
4、有一个字符串,当中包括中文字符、英文字符和数字字符,请统计和打印出各个字符的个数。 2
5、说明生活中遇到的二叉树,用java实现二叉树..............................................2
6、从类似例如以下的文本文件里读取出全部的姓名,并打印出反复的姓名和反复的次数,并按反复次数排序: 2
7、写一个Singleton出来。................................................................................2
8、递归算法题1................................................................................................2
9、递归算法题2................................................................................................2
10、排序都有哪几种方法?请列举。用JAVA实现一个高速排序。.....................2
11、有数组a[n],用java代码将数组元素顺序颠倒.............................................2
12.金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出。 2
三.html&JavaScript&ajax部分...................................................................................2
1.推断第二个日期比第一个日期大....................................................................2
2.用table显示n条记录,每3行换一次颜色,即1,2,3用红色字体,4,5,6用绿色字体,7,8,9用红颜色字体。...................................................................................................................2
3、HTML的 form 提交之前怎样验证数值文本框的内容所有为数字?否则的话提示用户并终止提交? 2
4、请写出用于校验HTML文本框中输入的内容所有为数字的javascript代码......2
5、说说你用过那些ajax技术和框架,说说它们的差别.......................................2
四. Java web部分......................................................................................................2
1、Tomcat的优化经验........................................................................................2
2、HTTP请求的GET与POST方式的差别.........................................................2
3、解释一下什么是servlet;.................................................................................2
4、说一说Servlet的生命周期?...........................................................................2
5、Servlet的基本架构........................................................................................2
6、SERVLET API中forward()与redirect()的差别?...........................................2
7、什么情况下调用doGet()和doPost()?............................................................2
8、Request对象的主要方法:.............................................................................2
9、forward和redirect的差别.............................................................................2
10、request.getAttribute()和 request.getParameter() 有何差别?............................2
11.jsp有哪些内置对象?作用各自是什么?分别有什么方法?..............................2
12.jsp有哪些动作?作用各自是什么?..................................................................2
13、JSP的经常使用指令...........................................................................................2
14.JSP中动态INCLUDE与静态INCLUDE的差别?.........................................2
15、两种跳转方式各自是什么?有什么差别?........................................................2
16、页面间对象传递的方法................................................................................2
17、JSP和Servlet有哪些同样点和不同点,他们之间的联系是什么?................2
18、MVC的各个部分都有那些技术来实现?怎样实现?........................................2
19、我们在web应用开发过程中常常遇到输出某种编码的字符,如iso8859-1等,怎样输出一个某种编码的字符串?..........................................................................................................................2
20.如今输入n个数字,以逗号,分开;然后可选择升或者降序排序;按提交键就在还有一页面显示按什么排序,结果为,提供reset.............................................................................................2
五.数据库部分.........................................................................................................2
1、用两种方式依据部门号从高到低,工资从低到高列出每一个员工的信息。........2
2、列出各个部门中工资高于本部门的平均工资的员工数和部门号,并按部门号排序 2
3、存储过程与触发器必须讲,常常被面试到?....................................................2
4、数据库三范式是什么?...................................................................................2
5、说出一些数据库优化方面的经验?..................................................................2
6、union和union all有什么不同?.......................................................................2
7.分页语句.........................................................................................................2
8.用一条SQL语句查询出每门课都大于80分的学生姓名..................................2
9.全部部门之间的比赛组合................................................................................2
10.每一个月份的发生额都比101科目多的科目......................................................2
11.统计每年每月的信息......................................................................................2
12.显示文章标题,发帖人、最后回复时间..........................................................2
13.删除除了id号不同,其它都同样的学生冗余信息.............................................2
14.航空网的几个航班查询题:...........................................................................2
15.查出比经理薪水还高的员工信息:.................................................................2
16、求出小于45岁的各个老师所带的大于12岁的学生人数...............................2
17.求出发帖最多的人:......................................................................................2
18、一个用户表中有一个积分字段,假如数据库中有100多万个用户,若要在每年第一天凌晨将积分清零,你将考虑什么,你将想什么办法解决?.......................................................................2
19、一个用户具有多个角色,请查询出该表中具有该用户的全部角色的其它用户。 2
20.xxx公司的sql面试.......................................................................................2
21、注冊Jdbc驱动程序的三种方式....................................................................2
22、用JDBC怎样调用存储过程.........................................................................2
23、JDBC中的PreparedStatement相比Statement的优点.....................................2
24.写一个用jdbc连接并訪问oracle数据的程序代码..........................................2
25、Class.forName的作用?为什么要用?..............................................................2
26、大数据量下的分页解决方法。.....................................................................2
27、用 JDBC 查询学生成绩单,把主要代码写出来(考试概率极大)................2
28、这段代码有什么不足之处?...........................................................................2
29、说出数据连接池的工作机制是什么?.............................................................2
30、为什么要用ORM? 和 JDBC 有何不一样?.................................................2
六. XML部分............................................................................................................2
1、xml有哪些解析技术?差别是什么?.................................................................2
2、你在项目中用到了xml技术的哪些方面?怎样实现的?....................................2
3、用jdom解析xml文件时怎样解决中文问题?怎样解析?...................................2
4、编程用JAVA解析XML的方式......................................................................2
5、XML文档定义有几种形式?它们之间有何本质差别?解析XML文档有哪几种方式? 2
七.流行的框架与新技术...........................................................................................2
1、谈谈你对Struts的理解。...............................................................................2
2、谈谈你对Hibernate的理解。.........................................................................2
3、AOP的作用。...............................................................................................2
4、你对Spring的理解。....................................................................................2
5、谈谈Struts中的Actionservlet。.....................................................................2
6、Struts优缺点 长处: 1.实现MVC模式,结构清晰,使开发人员仅仅关注业务逻辑的实现. 2
7、STRUTS的应用(如STRUTS架构).................................................................2
8、说说struts1与struts2的差别。......................................................................2
9、hibernate中的update()和saveOrUpdate()的差别,session的load()和get()的差别。 2
10、简述Hibernate和 JDBC 的优缺点?怎样书写一个 one to many配置文件..2
11、iBatis与Hibernate有什么不同?....................................................................2
12、写Hibernate的一对多和多对一双向关联的orm配置?...................................2
9、hibernate的inverse属性的作用?.....................................................................2
13、在DAO中怎样体现DAO设计模式?............................................................2
14、spring+Hibernate中托付方案怎么配置?........................................................2
15、spring+Hibernate中托付方案怎么配置?........................................................2
16.hibernate进行多表查询每一个表中各取几个字段,也就是说查询出来的结果集没有一个实体类与之相应怎样解决;..........................................................................................................................2
17.介绍一下Hibernate的二级缓存......................................................................2
18、Spring的依赖注入是什么意思?给一个 Bean的 message属性,字符串类型,注入值为 "Hello"的 XML配置文件该怎么写?................................................................................................2
19、Jdo是什么?.................................................................................................2
20、什么是spring的IOC AOP.........................................................................2
21、STRUTS的工作流程!................................................................................2
22、spring与EJB的差别!!............................................................................2
八.软件project与设计模式...........................................................................................2
1、UML方面.....................................................................................................2
2、j2ee经常使用的设计模式?说明工厂模式。.........................................................2
3、开发中都用到了那些设计模式?用在什么场合?...............................................2
九. j2ee部分..............................................................................................................2
1、BS与CS的联系与差别。..............................................................................2
2、应用server与WEBSERVER的差别?..........................................................2
3、应用server有那些?.....................................................................................2
4、J2EE是什么?..............................................................................................2
5、J2EE是技术还是平台还是框架?什么是J2EE.............................................2
6、请对下面在J2EE中经常使用的名词进行解释(或简单描写叙述)...................................2
7、怎样给weblogic指定大小的内存?..................................................................2
8、怎样设定的weblogic的热启动模式(开发模式)与产品公布模式?.....................2
9、怎样启动时不需输入username与password?..............................................................2
10、在weblogic管理制台中对一个应用域(或者说是一个站点,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么文件里?.................................................................................2
11、说说weblogic中一个Domain的缺省文件夹结构?比方要将一个简单的helloWorld.jsp放入何文件夹下,然的在浏览器上就可打入http://主机:port号//helloword.jsp就能够看到执行结果了?又比方这当中用到了一个自己写的javaBean该怎样办?..........................................................................................................2
12、在weblogic中公布ejb需涉及到哪些配置文件..............................................2
13、怎样在weblogic中进行ssl配置与client的认证配置或说说j2ee(标准)进行ssl的配置? 2
14、怎样查看在weblogic中已经公布的EJB?......................................................2
十. EBJ部分.............................................................................................................2
1、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的差别,StatefulBean和StatelessBean的差别。..........................................................................................................................2
2、简要讲一下 EJB 的 7 个Transaction Level?.................................................2
3、EJB与JAVA BEAN的差别?........................................................................2
4、EJB包含(SessionBean,EntityBean)说出他们的生命周期,及怎样管理事务的? 2
5、EJB容器提供的服务.....................................................................................2
6、EJB的激活机制............................................................................................2
7、EJB的几种类型............................................................................................2
8、客服端调用EJB对象的几个基本步骤............................................................2
十一. webservice部分................................................................................................2
1、WEBSERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。 2
2、CORBA是什么?用途是什么?.........................................................................2
3.Linux.....................................................................................................................2
4、LINUX下线程,GDI类的解释。..................................................................2
5.问得稀里糊涂的题................................................................................................2
6、四种会话跟踪技术........................................................................................2
7、简述逻辑操作(&,|,^)与条件操作(&&,||)的差别。............................................2
十二.其它................................................................................................................2
1、请用英文简介一下自己..........................................................................2
2、请把http://tomcat.apache.org/ 首页的这一段话用中文翻译一下?.....................2
3、美资软件公司JAVAproject师电话面试题目......................................................2
这套面试题主要目的是帮助那些还没有java软件开发实际工作经验,而正在努力寻找java软件开发工作的朋友在笔试时更好地赢得笔试和面试。因为这套面试题涉及的范围非常泛,非常广,非常杂,大家不可能一天两天就看完和学完这套面试宝典,即使你已经学过了有关的技术,那么至少也须要一个月的时间才干消化和掌握这套面试宝典,所以,大家应该早作准备,从拿到这套面试宝典之日起,就要坚持在每天闲暇之余学习当中几道题目,日积月累,等到出去面试时,一切都水到渠成,面试时就自然会游刃有余了。
答题时,先答是什么,再答有什么作用和要注意什么(这部分最重要,展现自己的心得)
答案的段落分别,层次分明,条理清晰都很重要,从这些表面的东西也能够看出一个人的习惯、办事风格、条理等。
要讲你做出答案的思路过程,或者说你记住答案的思想都写下来。把答题想着是辩论赛。答题就是给别人讲道理、摆事实。答题不局限于什么格式和形式,就是要将自己的学识展现出来!
别由于人家题目本来就模棱两可,你就心里胆怯和没底气了,不敢回答了。你要大胆地指出对方题目非常模糊和你的观点,不要把面试官想得有多高,事实上他和你就是差点儿相同的,你想想,假设他把你招进去了,你们以后就是同事了,可不是差点儿相同的吗?
关于就业薪水,假设你是应届生,那不能要高工资,好比大饼的故事,没有文凭还想拿高工资,就去中关村缺什么补什么吧!少数人基础确实非常好,在校期间确实又做过一些项目,那仍然是能够要到相对高的工资的。
1. Java基础部分
基础部分的顺序:基本的语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io的语法,虚拟机方面的语法。
1、一个".java"源文件里能否够包含多个类(不是内部类)?有什么限制?
能够有多个类,但仅仅能有一个public的类,而且public的类名必须与文件名称相一致。
2、Java有没有goto?
java中的保留字,如今没有在java中使用。
3、说说&和&&的差别。
&和&&都能够用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,仅仅要有一方为false,则结果为false。
&&还具有短路的功能,即假设第一个表达式为false,则不再计算第二个表达式,比如,对于if(str != null&& !str.equals(“”))表达式,当str为null时,后面的表达式不会运行,所以不会出现NullPointerException假设将&&改为&,则会抛出NullPointerException异常。If(x==33 &++y>0) y会增长,If(x==33 && ++y>0)不会增长
&还能够用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,比如,0x31 & 0x0f的结果为0x01。
备注:这道题先说两者的共同点,再说出&&和&的特殊之处,并列举一些经典的样例来表明自己理解透彻深入、实际经验丰富。 f
4、在JAVA中怎样跳出当前的多重嵌套循环?
在Java中,要想跳出多重循环,能够在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break语句,就可以跳出外层循环。比如,
ok:
for(int i=0;i<10;i++) {
for(int j=0;j<10;j++) {
System.out.println(“i=” + i + “,j=” + j);
if(j == 5) break ok;
}
}
另外,我个人通常并不使用标号这样的方式,而是让外层的循环条件表达式的结果能够受到里层循环体代码的控制,比如,要在二维数组中查找到某个数字。
int arr[][] ={{1,2,3},{4,5,6,7},{9}};
boolean found = false;
for(int i=0;i<arr.length&& !found;i++) {
for(int j=0;j<arr[i].length;j++){
System.out.println(“i=” + i + “,j=” + j);
if(arr[i][j] ==5) {
found = true;
break;
}
}
}
5、switch语句是否能作用在byte上,是否能作用在long上,是否能作用在String上?
在switch(expr1)中,expr1仅仅能是一个整数表达式或者枚举常量(更大字体),整数表达式能够是int基本类型或Integer包装类型,因为,byte,short,char都能够隐含转换为int,所以,这些类型以及这些类型的包装类型也是能够的。显然,long和String类型都不符合switch的语法规定,而且不能被隐式转换成int类型,所以,它们不能作用于swtich语句中。
6、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
对于short s1 = 1; s1 = s1 + 1;因为s1+1运算时会自己主动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告须要强制转换类型的错误。
对于short s1 = 1; s1 += 1;因为 +=是java语言规定的运算符,java编译器会对它进行特殊处理,因此能够正确编译。
7、char型变量中能不能存贮一个中文汉字?为什么?
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包括了汉字,所以,char型变量中当然能够存储汉字啦。只是,假设某个特殊的汉字没有被包括在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。
备注:后面一部分回答尽管不是在正面回答题目,可是,为了展现自己的学识和表现自己对问题理解的透彻深入,能够回答一些相关的知识,做到知无不言,言无不尽。
8、用最有效率的方法算出2乘以8等於几?
2 << 3,
由于将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8仅仅要将其左移3位就可以,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2 << 3。
9、请设计一个一百亿的计算器
首先要明确这道题目的考查点是什么,一是大家首先要对计算机原理的底层细节要清楚、要知道加减法的位运算原理和知道计算机中的算术运算会发生越界的情况,二是要具备一定的面向对象的设计思想。
首先,计算机中用固定数量的几个字节来存储的数值,所以计算机中可以表示的数值是有一定的范围的,为了便于解说和理解,我们先以byte类型的整数为例,它用1个字节进行存储,表示的最大数值范围为-128到+127。-1在内存中相应的二进制数据为11111111,假设两个-1相加,不考虑Java运算时的类型提升,运算后会产生进位,二进制结果为1,11111110,因为进位后超过了byte类型的存储空间,所以进位部分被舍弃,即终于的结果为11111110,也就是-2,这正好利用溢位的方式实现了负数的运算。-128在内存中相应的二进制数据为10000000,假设两个-128相加,不考虑Java运算时的类型提升,运算后会产生进位,二进制结果为1,00000000,因为进位后超过了byte类型的存储空间,所以进位部分被舍弃,即终于的结果为00000000,也就是0,这种结果显然不是我们期望的,这说明计算机中的算术运算是会发生越界情况的,两个数值的运算结果不能超过计算机中的该类型的数值范围。因为Java中涉及表达式运算时的类型自己主动提升,我们无法用byte类型来做演示这种问题和现象的实验,大家可以用以下一个使用整数做实验的样例程序体验一下:
int a = Integer.MAX_VALUE;
int b = Integer.MAX_VALUE;
int sum = a + b;
System.out.println(“a=”+a+”,b=”+b+”,sum=”+sum);
先不考虑long类型,因为int的正数范围为2的31次方,表示的最大数值约等于2*1000*1000*1000,也就是20亿的大小,所以,要实现一个一百亿的计算器,我们得自己设计一个类能够用于表示非常大的整数,而且提供了与另外一个整数进行加减乘除的功能,大概功能例如以下:
()这个类内部有两个成员变量,一个表示符号,还有一个用字节数组表示数值的二进制数
()有一个构造方法,把一个包括有多位数值的字符串转换到内部的符号和字节数组中
()提供加减乘除的功能
public class BigInteger{
int sign;
byte[] val;
public Biginteger(String val) {
sign = ;
val = ;
}
public BigInteger add(BigInteger other) {
}
public BigInteger subtract(BigInteger other) {
}
public BigInteger multiply(BigInteger other){
}
public BigInteger divide(BigInteger other){
}
}
备注:要想写出这个类的完整代码,是非常复杂的,假设有兴趣的话,能够參看jdk中自带的java.math.BigInteger类的源代码。面试的人也知道谁都不可能在短时间内写出这个类的完整代码的,他要的是你是否有这方面的概念和意识,他最重要的还是考查你的能力,所以,你不要由于自己无法写出完整的终于结果就放弃答这道题,你要做的就是你比别人写得多,证明你比别人强,你有这方面的思想意识就能够了,毕竟别人可能连题目的意思都看不懂,什么都没写,你要敢于答这道题,即使仅仅答了一部分,那也与那些什么都不懂的人差别出来,拉开了距离,算是矮子中的高个,机会当然就属于你了。另外,答案中的框架代码也非常重要,体现了一些面向对象设计的功底,特别是当中的方法命名非常专业,用的英文单词非常精准,这也是能力、经验、专业性、英语水平等多个方面的体现,会给人留下非常好的印象,在编程能力和其它方面条件差点儿相同的情况下,英语好除了能够使你获得很多其它机会外,薪水能够高出一千元。
10、使用finalkeyword修饰一个变量时,是引用不能变,还是引用的对象不能变?
使用finalkeyword修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是能够改变的。比如,对于例如以下语句:
final StringBuffer a=new StringBuffer("immutable");
运行例如以下语句将报告编译期错误:
a=new StringBuffer("");
可是,运行例如以下语句则能够通过编译:
a.append(" broken!");
有人在定义方法的參数时,可能想採用例如以下形式来阻止方法内部改动传进来的參数对象:
public void method(final StringBuffer param){
}
实际上,这是办不到的,在该方法内部仍然能够添加例如以下代码来改动參数对象:
param.append("a");
11、"=="和equals方法到底有什么差别?
(单独把一个东西说清楚,然后再说清楚还有一个,这样,它们的差别自然就出来了,混在一起说,则非常难说清楚)
==操作符专门用来比較两个变量的值是否相等,也就是用于比較变量所相应的内存中所存储的数值是否同样,要比較两个基本类型的数据或两个引用变量是否相等,仅仅能用==操作符。
假设一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,比如Objet obj = newObject();变量obj是一个内存,new Object()是还有一个内存,此时,变量obj所相应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,假设要比較两个变量是否指向同一个对象,即要看这两个变量所相应的内存中的数值是否相等,这时候就须要用==操作符进行比較。
equals方法是用于比較两个独立对象的内容是否同样,就好比去比較两个人的长相是否同样,它比較的两个对象是独立的。比如,对于以下的代码:
String a=new String("foo");
String b=new String("foo");
两条new语句创建了两个对象,然后用a/b这两个变量分别指向了当中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不同样的,所以,表达式a==b将返回false,而这两个对象中的内容是同样的,所以,表达式a.equals(b)将返回true。
在实际开发中,我们常常要比較传递进行来的字符串内容是否等,比如,String input = …;input.equals(“quit”),很多人稍不注意就使用==进行比較了,这是错误的,随便从网上找几个项目实战的教学视频看看,里面就有大量这种错误。记住,字符串的比較基本上都是使用equals方法。
假设一个类没有自定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码例如以下:
boolean equals(Object o){
return this==o;
}
这说明,假设一个类没有自定义equals方法,它默认的equals方法(从Object类继承的)就是使用==操作符,也是在比較两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,假设比較的是两个独立的对象则总返回false。假设你编写的类希望可以比較该类创建的两个实例对象的内容是否同样,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况就可以觉得两个对象的内容是同样的。
12、静态变量和实例变量的差别?
在语法定义上的差别:静态变量前要加statickeyword,而实例变量前则不加。
在程序执行时的差别:实例变量属于某个对象的属性,必须创建了实例对象,当中的实例变量才会被分配空间,才干使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,仅仅要程序载入了类的字节码,不用创建不论什么实例对象,静态变量就会被分配空间,静态变量就能够被使用了。总之,实例变量必须创建对象后才干够通过这个对象来使用,静态变量则能够直接使用类名来引用。
比如,对于以下的程序,不管创建多少个实例对象,永远都仅仅分配了一个staticVar变量,而且每创建一个实例对象,这个staticVar就会加1;可是,每创建一个实例对象,就会分配一个instanceVar,就可以能分配多个instanceVar,而且每一个instanceVar的值都仅仅自加了1次。
public class VariantTest{
public static int staticVar = 0;
public int instanceVar = 0;
public VariantTest(){
staticVar++;
instanceVar++;
System.out.println(“staticVar=” + staticVar + ”,instanceVar=”+ instanceVar);
}
}
备注:这个解答除了说清楚两者的差别外,最后还用一个详细的应用样例来说明两者的差异,体现了自己有非常好的讲解问题和设计案例的能力,思维敏捷,超过一般程序猿,有写作能力!
13、能否够从一个static方法内部发出对非static方法的调用?
不能够。由于非static方法是要与对象关联在一起的,必须创建一个对象后,才干够在该对象上进行方法调用,而static方法调用时不须要创建对象,能够直接调用。也就是说,当一个static方法被调用时,可能还没有创建不论什么实例对象,假设从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。
14、Integer与int的差别
int是java提供的8种原始数据类型之中的一个。Java为每一个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer能够区分出未赋值和值为0的差别,int则无法表达出未赋值的情况,比如,要想表达出没有參加考试和考试成绩为0的差别,则仅仅能使用Integer。在JSP开发中,Integer的默觉得null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。
在Hibernate中,假设将OID定义为Integer类型,那么Hibernate就能够依据其值是否为null而推断一个对象是否是暂时的,假设将OID定义为了int类型,还须要在hbm映射文件里设置其unsaved-value属性为0。
另外,Integer提供了多个与整数相关的操作方法,比如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。
15、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math类中提供了三个与取整有关的方法:ceil、floor、round,这些方法的作用与它们的英文名称的含义相相应,比如,ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;floor的英文意义是地板,该方法就表示向下取整,Math.ceil(11.6)的结果为11,Math.ceil(-11.6)的结果是-12;最难掌握的是round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。
16、以下的代码有什么不妥之处?
1. if(username.equals(“zxx”){}
2. int x = 1;
return x==1?true:false;
17、请说出作用域public,private,protected,以及不写时的差别
这四个作用域的可见范围例如以下表所看到的。
说明:假设在修饰的元素上面没有写不论什么訪问修饰符,则表示friendly。
作用域 当前类同一package子孙类其它package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
备注:仅仅要记住了有4种訪问权限,4个訪问范围,然后将全选和范围在水平和垂直方向上分别按排从小到大或从大到小的顺序排列,就非常easy画出上面的图了。
18、Overload和Override的差别。Overloaded的方法能否够改变返回值的类型?
Overload是重载的意思,Override是覆盖的意思,也就是重写。
重载Overload表示同一个类中能够有多个名称同样的方法,但这些方法的參数列表各不同样(即參数个数或类型不同)。
重写Override表示子类中的方法能够与父类中的某个方法的名称和參数全然同样,通过子类创建的实例对象调用这种方法时,将调用子类中的定义方法,这相当于把父类中定义的那个全然同样的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,仅仅能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,由于子类能够解决父类的一些问题,不能比父类有很多其它的问题。子类方法的訪问权限仅仅能比父类的更大,不能更小。假设父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中添加了一个全新的方法。
至于Overloaded的方法能否够改变返回值的类型这个问题,要看你倒底想问什么呢?这个题目非常模糊。假设几个Overloaded的方法的參数列表不一样,它们的返回者类型当然也能够不一样。但我预计你想问的问题是:假设两个方法的參数列表全然一样,能否够让它们的返回值不同来实现重载Overload。这是不行的,我们能够用反证法来说明这个问题,由于我们有时候调用一个方法时也能够不定义返回结果变量,即不要关心其返回结果,比如,我们调用map.remove(key)方法时,尽管remove方法有返回值,可是我们通常都不会定义接收返回结果的变量,这时候假设该类中有两个名称和參数列表全然同样的方法,不过返回类型不同,java就无法确定编程者倒底是想调用哪个方法了,由于它无法通过返回结果类型来推断。
override能够翻译为覆盖,从字面就能够知道,它是覆盖了一个方法而且对其重写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般仅仅是对方法进行了声明,而我们在实现时,就须要实现接口声明的全部方法。除了这个典型的使用方法以外,我们在继承中也可能会在子类覆盖父类中的方法。在覆盖要注意下面的几点:
1、覆盖的方法的标志必需要和被覆盖的方法的标志全然匹配,才干达到覆盖的效果;
2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;
3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
4、被覆盖的方法不能为private,否则在其子类中仅仅是新定义了一个方法,并没有对其进行覆盖。
overload对我们来说可能比較熟悉,能够翻译为重载,它是指我们能够定义一些名称同样的方法,通过定义不同的输入參数来区分这些方法,然后再调用时,VM就会依据不同的參数样式,来选择合适的方法运行。在使用重载要注意下面的几点:
1、在使用重载时仅仅能通过不同的參数样式。比如,不同的參数类型,不同的參数个数,不同的參数顺序(当然,同一方法内的几个參数类型必须不一样,比如能够是fun(int,float),可是不能为fun(int,int));
2、不能通过訪问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
4、对于继承来说,假设某一方法在父类中是訪问权限是priavte,那么就不能在子类对其进行重载,假设定义的话,也仅仅是定义了一个新方法,而不会达到重载的效果。
19、构造器Constructor是否可被override?
构造器Constructor不能被继承,因此不能重写Override,但能够被重载Overload。
20、接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承详细类(concrete class)?抽象类中能否够有静态的main方法?
接口能够继承接口。抽象类能够实现(implements)接口,抽象类是否可继承详细类。抽象类中能够有静态的main方法。
备注:仅仅要明确了接口和抽象类的本质和作用,这些问题都非常好回答,你想想,假设你是java语言的设计者,你是否会提供这种支持,假设不提供的话,有什么理由吗?假设你没有道理不提供,那答案就是肯定的了。
仅仅有记住抽象类与普通类的唯一差别就是不能创建实例对象和同意有abstract方法。
21、写clone()方法时,通常都有一行代码,是什么?
clone 有缺省行为,super.clone();由于首先要把父类中的成员拷贝到位,然后才是复制自己的成员。
22、面向对象的特征有哪些方面
计算机软件系统是现实生活中的业务在计算机中的映射,而现实生活中的业务事实上就是一个个对象协作的过程。面向对象编程就是按现实业务一样的方式将程序代码按一个个对象进行组织和编写,让计算机系统可以识别和理解用对象方式组织和编写的程序代码,这样就行把现实生活中的业务对象映射到计算机系统中。
面向对象的编程语言有,吗等4个基本的特征。
1封装:
封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。在面向对象的编程语言中,对象是封装的最基本单位,面向对象的封装比传统语言的封装更为清晰、更为有力。面向对象的封装就是把描写叙述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法能够直接訪问同一个对象中的属性。通常情况下,仅仅要记住让变量和訪问这个变量的方法放在一起,将一个类中的成员变量所有定义成私有的,仅仅有这个类自己的方法才干够訪问到这些成员变量,这就基本上实现对象的封装,就非常easy找出要分配到这个类上的方法了,就基本上算是会面向对象的编程了。把握一个原则:把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和它操作的数据放在同一个类中。
比如,人要在黑板上画圆,这一共涉及三个对象:人、黑板、圆,画圆的方法要分配给哪个对象呢?由于画圆须要使用到圆心和半径,圆心和半径显然是圆的属性,假设将它们在类中定义成了私有的成员变量,那么,画圆的方法必须分配给圆,它才干訪问到圆心和半径这两个属性,人以后仅仅是调用圆的画圆方法、表示给圆发给消息而已,画圆这种方法不应该分配在人这个对象上,这就是面向对象的封装性,即将对象封装成一个高度自治和相对封闭的个体,对象状态(属性)由这个对象自己的行为(方法)来读取和改变。一个更便于理解的样例就是,司机将火车刹住了,刹车的动作是分配给司机,还是分配给火车,显然,应该分配给火车,由于司机自身是不可能有那么大的力气将一个火车给停下来的,仅仅有火车自己才干完毕这一动作,火车须要调用内部的离合器和刹车片等多个器件协作才干完毕刹车这个动作,司机刹车的过程仅仅是给火车发了一个消息,通知火车要运行刹车动作而已。
抽象:
抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类仅仅考虑这些事物的相似和共性之处,而且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。比如,看到一仅仅蚂蚁和大象,你可以想象出它们的同样之处,那就是抽象。抽象包含行为抽象和状态抽象两个方面。比如,定义一个Person类,例如以下:
classPerson{
String name;
int age;
}
人本来是非常复杂的事物,有非常多方面,但由于当前系统仅仅须要了解人的姓名和年龄,所以上面定义的类中仅仅包括姓名和年龄这两个属性,这就是一种抽像,使用抽象能够避免考虑一些与目标无关的细节。我对抽象的理解就是不要用显微镜去看一个事物的全部方面,这样涉及的内容就太多了,而是要善于划分问题的边界,当前系统须要什么,就仅仅考虑什么。
继承:
在定义和实现一个类的时候,能够在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并能够增加若干新的内容,或改动原来的方法使之更适合特殊的须要,这就是继承。继承是子类自己主动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。
多态:
多态是指程序中定义的引用变量所指向的详细类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序执行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用究竟是哪个类中实现的方法,必须在由程序执行期间才干决定。由于在程序执行时才确定详细的类,这样,不用改动源程序代码,就能够让引用变量绑定到各种不同的类实现上,从而导致该引用调用的详细方法随之改变,即不改动程序代码就能够改变程序执行时所绑定的详细代码,让程序能够选择多个执行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。比如,以下代码中的UserDao是一个接口,它定义引用变量userDao指向的实例对象由daofactory.getDao()在执行的时候返回,有时候指向的是UserJdbcDao这个实现,有时候指向的是UserHibernateDao这个实现,这样,不用改动源码,就能够改变userDao指向的详细类实现,从而导致userDao.insertUser()方法调用的详细代码也随之改变,即有时候调用的是UserJdbcDao的insertUser方法,有时候调用的是UserHibernateDao的insertUser方法:
UserDao userDao =daofactory.getDao();
userDao.insertUser(user);
比喻:人吃饭,你看到的是左手,还是右手?
23、java中实现多态的机制是什么?
靠的是父类或接口定义的引用变量能够指向子类或详细实现类的实例对象,而程序调用的方法在执行期才动态绑定,就是引用变量所指向的详细实例对象的方法,也就是内存里正在执行的那个对象的方法,而不是引用变量的类型中定义的方法。
24、abstract class和interface有什么差别?
含有abstract修饰符的class即为抽象类,abstract类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在详细(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。假设的子类没有实现抽象父类中的全部抽象方法,那么子类也必须定义为abstract类型。
接口(interface)能够说成是抽象类的一种特例,接口中的全部方法都必须是抽象的。接口中的方法定义默觉得public abstract类型,接口中的成员变量类型默觉得public static final。
以下比較一下两者的语法差别:
1.抽象类能够有构造方法,接口中不能有构造方法。
2.抽象类中能够有普通成员变量,接口中没有普通成员变量
3.抽象类中能够包括非抽象的普通方法,接口中的全部方法必须都是抽象的,不能有非抽象的普通方法。
4. 抽象类中的抽象方法的訪问类型能够是public,protected和(默认类型,尽管
eclipse下不报错,但应该也不行),但接口中的抽象方法仅仅能是public类型的,而且默认即为public abstract类型。
5. 抽象类中能够包括静态方法,接口中不能包括静态方法
6. 抽象类和接口中都能够包括静态成员变量,抽象类中的静态成员变量的訪问类型能够随意,但接口中定义的变量仅仅能是public static final类型,而且默认即为public static final类型。
7. 一个类能够实现多个接口,但仅仅能继承一个抽象类。
以下接着再说说两者在应用上的差别:
接口很多其它的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,能够实现代码的重用,比如,模板方法设计模式是抽象类的一个典型应用,如果某个项目的全部Servlet类都要用同样的方式进行权限推断、记录訪问日志和处理异常,那么就能够定义一个抽象的基类,让全部的Servlet都继承这个抽象基类,在抽象基类的service方法中完毕权限推断、记录訪问日志和处理异常的代码,在各个子类中仅仅是完毕各自的业务逻辑代码,伪代码例如以下:
public abstract classBaseServlet extends HttpServlet{
public final void service(HttpServletRequest request,HttpServletResponse response) throws IOExcetion,ServletException {
记录訪问日志
进行权限推断
if(具有权限){
try{
doService(request,response);
}
catch(Excetpion e) {
记录异常信息
}
}
}
protected abstract void doService(HttpServletRequest request,HttpServletResponse response) throws IOExcetion,ServletException;
//注意訪问权限定义成protected,显得既专业,又严谨,由于它是专门给子类用的
}
public class MyServlet1 extendsBaseServlet
{
protected voiddoService(HttpServletRequest request, HttpServletResponse response) throwsIOExcetion,ServletException
{
本Servlet仅仅处理的详细业务逻辑代码
}
}
父类方法中间的某段代码不确定,留给子类干,就用模板方法设计模式。
备注:这道题的思路是先从整体解释抽象类和接口的基本概念,然后再比較两者的语法细节,最后再说两者的应用差别。比較两者语法细节差别的条理是:先从一个类中的构造方法、普通成员变量和方法(包含抽象方法),静态变量和方法,继承性等6个方面逐一去比較回答,接着从第三者继承的角度的回答,特别是最后用了一个典型的样例来展现自己深厚的技术功底。
25、abstract的method是否可同一时候是static,是否可同一时候是native,是否可同一时候是synchronized?
abstract的method不能够是static的,由于抽象的方法是要被子类实现的,而static与子类扯不上关系!
native方法表示该方法要用第二种依赖平台的编程语言实现的,不存在着被子类实现的问题,所以,它也不能是抽象的,不能与abstract混用。比如,FileOutputSteam类要硬件打交道,底层的实现用的是操作系统相关的api实现,比如,在windows用c语言实现的,所以,查看jdk的源码,能够发现FileOutputStream的open方法的定义例如以下:
private native void open(Stringname) throws FileNotFoundException;
假设我们要用java调用别人写的c语言函数,我们是无法直接调用的,我们须要依照java的要求写一个c语言的函数,又我们的这个c语言函数去调用别人的c语言函数。因为我们的c语言函数是按java的要求来写的,我们这个c语言函数就能够与java对接上,java那边的对接方式就是定义出与我们这个c函数相相应的方法,java中相应的方法不须要写详细的代码,但须要在前面声明native。
关于synchronized与abstract合用的问题,我认为也不行,由于在我几年的学习和开发中,从来没见到过这样的情况,并且我认为synchronized应该是作用在一个详细的方法上才有意义。并且,方法上的synchronized同步所使用的同步锁对象是this,而抽象方法上无法确定this是什么。
26、什么是内部类?Static Nested Class和Inner Class的不同。
内部类就是在一个类的内部定义的类,内部类中不能定义静态成员(静态成员不是对象的特性,仅仅是为了找一个容身之处,所以须要放到一个类中而已,这么一点小事,你还要把它放到类内部的一个类中,过分了啊!提供内部类,不是为让你干这样的事情,无聊,不让你干。我想可能是既然静态成员类似c语言的全局变量,而内部类一般是用于创建内部对象用的,所以,把“全局变量”放在内部类中就是毫无意义的事情,既然是毫无意义的事情,就应该被禁止),内部类能够直接訪问外部类中的成员变量,内部类能够定义在外部类的方法外面,也能够定义在外部类的方法体中,例如以下所看到的:
public class Outer
{
int out_x = 0;
public void method()
{
Inner1 inner1 = new Inner1();
public class Inner2 //在方法体内部定义的内部类
{
public method()
{
out_x = 3;
}
}
Inner2 inner2 = new Inner2();
}
public class Inner1 //在方法体外面定义的内部类
{
}
}
在方法体外面定义的内部类的訪问类型能够是public,protecte,默认的,private等4种类型,这就好像类中定义的成员变量有4种訪问类型一样,它们决定这个内部类的定义对其它类是否可见;对于这样的情况,我们也能够在外面创建内部类的实例对象,创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象,代码例如以下:
Outer outer = new Outer();
Outer.Inner1 inner1 = outer.newInnner1();
在方法内部定义的内部类前面不能有訪问类型修饰符,就好像方法中定义的局部变量一样,但这样的内部类的前面能够使用final或abstract修饰符。这样的内部类对其它类是不可见的其它类无法引用这样的内部类,可是这样的内部类创建的实例对象能够传递给其它类訪问。这样的内部类必须是先定义,后使用,即内部类的定义代码必须出如今使用该类之前,这与方法中的局部变量必须先定义后使用的道理也是一样的。这样的内部类能够訪问方法体中的局部变量,可是,该局部变量前必须加final修饰符。
对于这些细节,仅仅要在eclipse写代码试试,依据开发工具提示的各类错误信息就能够立即了解到。
在方法体内部还能够採用例如以下语法来创建一种匿名内部类,即定义某一接口或类的子类的同一时候,还创建了该子类的实例对象,无需为该子类定义名称:
public class Outer
{
public void start()
{
new Thread(
new Runable(){
public void run(){};
}
).start();
}
}
最后,在方法外部定义的内部类前面能够加上statickeyword,从而成为Static Nested Class,它不再具有内部类的特性,全部,从狭义上讲,它不是内部类。Static Nested Class与普通类在执行时的行为和功能上没有什么区别,仅仅是在编程引用时的语法上有一些区别,它能够定义成public、protected、默认的、private等多种类型,而普通类仅仅能定义成public和默认的这两种类型。在外面引用Static Nested Class类的名称为“外部类名.内部类名”。在外面不须要创建外部类的实例对象,就能够直接创建Static Nested Class,比如,如果Inner是定义在Outer类中的Static Nested Class,那么能够使用例如以下语句创建Inner类:
Outer.Inner inner = newOuter.Inner();
因为static Nested Class不依赖于外部类的实例对象,所以,static Nested Class能訪问外部类的非static成员变量。当在外部类中訪问Static Nested Class时,能够直接使用Static Nested Class的名字,而不须要加上外部类的名字了,在Static Nested Class中也能够直接引用外部类的static的成员变量,不须要加上外部类的名字。
在静态方法中定义的内部类也是Static Nested Class,这时候不能在类前面加statickeyword,静态方法中的Static Nested Class与普通方法中的内部类的应用方式非常相似,它除了能够直接訪问外部类中的static的成员变量,还能够訪问静态方法中的局部变量,可是,该局部变量前必须加final修饰符。
备注:首先依据你的印象说出你对内部类的整体方面的特点:比如,在两个地方能够定义,能够訪问外部类的成员变量,不能定义静态成员,这是大的特点。然后再说一些细节方面的知识,比如,几种定义方式的语法差别,静态内部类,以及匿名内部类。
27、内部类能够引用它的包括类的成员吗?有没有什么限制?
全然能够。假设不是静态内部类,那没有什么限制!
假设你把静态嵌套类当作内部类的一种特例,那在这样的情况下不能够訪问外部类的普通成员变量,而仅仅能訪问外部类中的静态成员,比如,以下的代码:
class Outer
{
static int x;
static class Inner
{
void test()
{
syso(x);
}
}
}
答题时,也要能察言观色,揣摩提问者的心思,显然人家希望你说的是静态内部类不能訪问外部类的成员,但你一上来就顶牛,这不好,要先顺着人家,让人家惬意,然后再说特殊情况,让人家惊讶。
28、Anonymous Inner Class (匿名内部类)能否够extends(继承)其他类,能否够implements(实现)interface(接口)?
能够继承其它类或实现其它接口。不仅是能够,而是必须!
29、super.getClass()方法调用
以下程序的输出结果是多少?
importjava.util.Date;
public classTestextends Date{
public static voidmain(String[] args) {
new Test().test();
}
public void test(){
System.out.println(super.getClass().getName());
}
}
非常奇怪,结果是Test
这属于脑筋急转弯的题目,在一个qq群有个网友正好问过这个问题,我认为挺有趣,就研究了一下,没想到今天还被你面到了,哈哈。
在test方法中,直接调用getClass().getName()方法,返回的是Test类名
因为getClass()在Object类中定义成了final,子类不能覆盖该方法,所以,在
test方法中调用getClass().getName()方法,事实上就是在调用从父类继承的getClass()方法,等效于调用super.getClass().getName()方法,所以,super.getClass().getName()方法返回的也应该是Test。
假设想得到父类的名称,应该用例如以下代码:
getClass().getSuperClass().getName();
30、String是最主要的数据类型吗?
基本数据类型包含byte、int、char、long、float、double、boolean和short。
java.lang.String类是final类型的,因此不能够继承这个类、不能改动这个类。为了提高效率节省空间,我们应该用StringBuffer类
31、String s = "Hello";s = s + " world!";这两行代码运行后,原始的String对象中的内容究竟变了没有?
没有。由于String被设计成不可变(immutable)类,所以它的全部对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是 "Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了还有一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,仅仅是s这个引用变量不再指向它了。
通过上面的说明,我们非常easy导出还有一个结论,假设常常对字符串进行各种各样的改动,或者说,不可预见的改动,那么使用String来代表字符串的话会引起非常大的内存开销。由于 String对象建立之后不能再改变,所以对于每个不同的字符串,都须要一个String对象来表示。这时,应该考虑使用StringBuffer类,它同意改动,而不是每个不同的字符串都要生成一个新的对象。而且,这两种类的对象转换十分easy。
同一时候,我们还能够知道,假设要使用内容同样的字符串,不必每次都new一个String。比如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,而且没有意义,由于String对象不可改变,所以对于内容同样的字符串,仅仅要一个String对象来表示就能够了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,假设内容同样,Java觉得它们代表同一个String对象。而用keywordnew调用构造器,总是会创建一个新的对象,不管内容是否同样。
至于为什么要把String类设计成不可变类,是它的用途决定的。事实上不仅仅String,非常多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也须要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些长处,比方由于它的对象是仅仅读的,所以多线程并发訪问也不会有不论什么问题。当然也有一些缺点,比方每一个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本号,即 StringBuffer。
32、能否够继承String类?
String类是final类故不能够继承。
33、String s = new String("xyz");创建了几个String Object?二者之间有什么差别?
两个或一个,”xyz”相应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”无论出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它一句那个常量”xyz”对象的内容来创建出一个新String对象。假设曾经就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。
34、String和StringBuffer的差别
JAVA平台提供了两个类:String和StringBuffer,它们能够储存和操作字符串,即包括多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行改动。当你知道字符数据要改变的时候你就能够使用StringBuffer。典型地,你能够使用StringBuffers来动态构造字符数据。另外,String实现了equals方法,new String(“abc”).equals(newString(“abc”)的结果为true,而StringBuffer没有实现equals方法,所以,new StringBuffer(“abc”).equals(newStringBuffer(“abc”)的结果为false。
接着要举一个详细的样例来说明,我们要把1到100的全部数字拼起来,组成一个串。
StringBuffer sbf = new StringBuffer();
for(int i=0;i<100;i++)
{
sbf.append(i);
}
上面的代码效率非常高,由于仅仅创建了一个StringBuffer对象,而以下的代码效率非常低,由于创建了101个对象。
String str = new String();
for(int i=0;i<100;i++)
{
str = str + i;
}
在讲两者差别时,应把循环的次数搞成10000,然后用endTime-beginTime来比較两者运行的时间差异,最后还要讲讲StringBuilder与StringBuffer的差别。
String覆盖了equals方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,所以,将StringBuffer对象存储进Java集合类中时会出现故障。
35、怎样把一段逗号切割的字符串转换成一个数组?
假设不查jdk api,我非常难写出来!我能够说说我的思路:
1 用正則表達式,代码大概为:String [] result = orgStr.split(“,”);
2 用 StingTokenizer ,代码为:StringTokenizer tokener = StringTokenizer(orgStr,”,”);
String [] result =new String[tokener .countTokens()];
Int i=0;
while(tokener.hasNext(){result[i++]=toker.nextToken();}
36、数组有没有length()这种方法? String有没有length()这种方法?
数组没有length()这种方法,有length的属性。String有有length()这种方法。
37、以下这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";
答:对于例如以下代码:
String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");
第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译能够对字符串常量直接相加的表达式进行优化,不必要等到执行期去进行加法运算处理,而是在编译时去掉当中的加号,直接将其编译成一个这些常量相连的结果。
题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,上面的代码应该仅仅创建了一个String对象。写例如以下两行代码,
String s ="a" + "b" + "c" + "d";
System.out.println(s== "abcd");
终于打印的结果应该为true。
38、try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被运行,什么时候被运行,在return前还是后?
或许你的答案是在return之前,但往更细地说,我的答案是在return中间执行,请看以下程序代码的执行结果:
public classTest {
/**
* @paramargs add by zxx ,Dec 9, 2008
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
System.out.println(newTest().test());;
}
static int test()
{
int x = 1;
try
{
returnx;
}
finally
{
++x;
}
}
}
---------运行结果 ---------
1
执行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不执行了,你主函数继续执行吧,这没什么结果可言,结果是在说这话之前放进罐子里的。
39、以下的程序代码输出的结果是多少?
public class smallT
{
public staticvoid main(String args[])
{
smallT t = new smallT();
int b = t.get();
System.out.println(b);
}
public int get()
{
try
{
return1 ;
}
finally
{
return2 ;
}
}
}
返回的结果是2。
我能够通过以下一个样例程序来帮助我解释这个答案,从以下样例的运行结果中能够发现,try中的return语句调用的函数先于finally中调用的函数运行,也就是说return语句先运行,finally语句后运行,所以,返回的结果是2。Return并非让函数立即返回,而是return语句运行后,将把返回结果放置进函数栈中,此时函数并非立即返回,它要运行finally语句后才真正開始返回。
在解说答案时能够用以下的程序来帮助分析:
public classTest {
/**
* @paramargs add by zxx ,Dec 9, 2008
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
System.out.println(newTest().test());;
}
int test()
{
try
{
return func1();
}
finally
{
return func2();
}
}
int func1()
{
System.out.println("func1");
return 1;
}
int func2()
{
System.out.println("func2");
return 2;
}
}
-----------运行结果-----------------
func1
func2
2
结论:finally中的代码比return和break语句后运行
40、final, finally, finalize的差别。
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
内部类要訪问局部变量,局部变量必须定义成final类型,比如,一段代码……
finally是异常处理语句结构的一部分,表示总是运行。
finalize是Object类的一个方法,在垃圾收集器运行的时候会调用被回收对象的此方法,能够覆盖此方法提供垃圾收集时的其它资源回收,比如关闭文件等。JVM不保证此方法总被调用
41、执行时异常与一般异常有何异同?
异常表示程序执行过程中可能出现的非正常状态,执行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见执行错误。java编译器要求方法必须声明抛出可能发生的非执行时异常,可是并不要求必须声明抛出未被捕获的执行时异常。
42、error和exception有什么差别?
error 表示恢复不是不可能但非常困难的情况下的一种严重问题。比方说内存溢出。不可能指望程序能处理这种情况。 exception表示一种设计或实现问题。也就是说,它表示假设程序执行正常,从不会发生的情况。
43、Java中的异常处理机制的简单原理和应用。
异常是指java程序执行时(非编译)所发生的非正常情况或错误,与现实生活中的事件非常相似,现实生活中的事件能够包括事件发生的时间、地点、人物、情节等信息,能够用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每一个异常也都分别封装到一个对象来表示的,该对象中包括有异常的信息。
Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,全部异常的根类为java.lang.Throwable,Throwable以下又派生了两个子类:Error和Exception,Error表示应用程序本身无法克服和恢复的一种严重问题,程序仅仅有死的份了,比如,说内存溢出和线程死锁等系统问题。Exception表示程序还可以克服和恢复的问题,当中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发者考虑不周所导致的问题,软件使用者无法克服和恢复这样的问题,但在这样的问题下还可以让软件系统继续执行或者让软件死掉,比如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是执行环境的变化或异常所导致的问题,是用户可以克服的问题,比如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。
java为系统异常和普通异常提供了不同的解决方式,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常能够处理也能够不处理,所以,编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常。
提示答题者:就依照三个级别去思考:虚拟机必须宕机的错误,程序能够死掉也能够不死掉的错误,程序不应该死掉的错误;
44、请写出你最常见到的5个runtime exception。
这道题主要考你的代码量究竟多大,假设你长期写代码的,应该常常都看到过一些系统方面的异常,你不一定真要回答出5个详细的系统异常,但你要可以说出什么是系统异常,以及几个系统异常就行了,当然,这些异常全然用其英文名称来写是最好的,假设实在写不出,那就用中文吧,有总比没有强!
所谓系统异常,就是…..,它们都是RuntimeException的子类,在jdk doc中查RuntimeException类,就能够看到其全部的子类列表,也就是看到了全部的系统异常。我比較有印象的系统异常有:NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。
45、JAVA语言怎样进行异常处理,keyword:throws,throw,try,catch,finally分别代表什么意义?在try块中能够抛出异常吗?
46、java中有几种方法能够实现一个线程?用什么keyword修饰同步方法? stop()和suspend()方法为何不推荐使用?
java5曾经,有例如以下两种:
第一种:
new Thread(){}.start();这表示调用Thread子类对象的run方法,new Thread(){}表示一个Thread的匿名子类的实例对象,子类加上run方法后的代码例如以下:
new Thread(){
public void run(){
}
}.start();
另外一种:
new Thread(new Runnable(){}).start();这表示调用Thread对象接受的Runnable对象的run方法,new Runnable(){}表示一个Runnable的匿名子类的实例对象,runnable的子类加上run方法后的代码例如以下:
new Thread(new Runnable(){
public voidrun(){
}
}
).start();
从java5開始,还有例如以下一些线程池创建多线程的方式:
ExecutorService pool = Executors.newFixedThreadPool(3)
for(int i=0;i<10;i++)
{
pool.execute(newRunable(){public void run(){}});
}
Executors.newCachedThreadPool().execute(new Runable(){publicvoid run(){}});
Executors.newSingleThreadExecutor().execute(new Runable(){publicvoid run(){}});
有两种实现方法,分别使用new Thread()和new Thread(runnable)形式,第一种直接调用thread的run方法,所以,我们往往使用Thread子类,即new SubThread()。另外一种调用runnable的run方法。
有两种实现方法,各自是继承Thread类与实现Runnable接口
用synchronizedkeyword修饰同步方法
反对使用stop(),是由于它不安全。它会解除由线程获取的全部锁定,并且假设对象处于一种不连贯状态,那么其它线程能在那种状态下检查和改动它们。结果非常难检查出真正的问题所在。suspend()方法easy发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其它不论什么线程都不能訪问锁定的资源,除非被"挂起"的线程恢复执行。对不论什么线程来说,假设它们想恢复目标线程,同一时候又试图使用不论什么一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()又一次启动线程。
47、sleep()和 wait()有什么差别?
(网上的答案:sleep是线程类(Thread)的方法,导致此线程暂停运行指定时间,给运行机会给其它线程,可是监控状态依旧保持,到时后会自己主动恢复。调用sleep不会释放对象锁。 wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,仅仅有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。)
sleep就是正在运行的线程主动让出cpu,cpu去运行其它线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下运行,假设当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其它被同步锁挡住了的线程也无法得到运行。wait是指在一个已经进入了同步锁的线程内,让自己临时让出同步锁,以便其它正在等待此锁的线程能够得到同步锁并运行,仅仅有其它线程调用了notify方法(notify并不释放锁,仅仅是告诉调用过wait方法的线程能够去參与获得锁的竞争了,但不是立即得到锁,由于锁还在别人手里,别人还没释放。假设notify方法后面的代码还有非常多,须要这些代码运行完后才会释放锁,能够在notfiy方法后添加一个等待和一些代码,看看效果),调用wait方法的线程就会解除wait状态和程序能够再次得到锁后继续向下运行。对于wait的解说一定要配合样例代码来说明,才显得自己真明确。
package com.huawei.interview;
publicclass MultiThread {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
new Thread(newThread1()).start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catchblock
e.printStackTrace();
}
new Thread(newThread2()).start();
}
private static classThread1implements Runnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
//由于这里的Thread1和以下的Thread2内部run方法要用同一对象作为监视器,我们这里不能用this,由于在Thread2里面的this和这个Thread1的this不是同一个对象。我们用MultiThread.class这个字节码对象,当前虚拟机里引用这个变量时,指向的都是同一个对象。
synchronized (MultiThread.class){
System.out.println("enterthread1...");
System.out.println("thread1is waiting");
try {
//释放锁有两种方式,第一种方式是程序自然离开监视器的范围,也就是离开了synchronizedkeyword管辖的代码范围,还有一种方式就是在synchronizedkeyword管辖的代码内部调用监视器对象的wait方法。这里,使用wait方法释放锁。
MultiThread.class.wait();
} catch(InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
System.out.println("thread1is going on...");
System.out.println("thread1is being over!");
}
}
}
private static classThread2implements Runnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
synchronized (MultiThread.class){
System.out.println("enterthread2...");
System.out.println("thread2notify other thread can release wait status..");
//由于notify方法并不释放锁,即使thread2调用以下的sleep方法歇息了10毫秒,但thread1仍然不会运行,由于thread2没有释放锁,所以Thread1无法得不到锁。
MultiThread.class.notify();
System.out.println("thread2is sleeping ten millisecond...");
try {
Thread.sleep(10);
} catch (InterruptedExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
System.out.println("thread2is going on...");
System.out.println("thread2is being over!");
}
}
}
}
48、同步和异步有何异同,在什么情况下分别使用他们?举例说明。
假设数据将在线程间共享。比如正在写的数据以后可能被还有一个线程读到,或者正在读的数据可能已经被还有一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个须要花费非常长时间来运行的方法,而且不希望让程序等待方法的返回时,就应该使用异步编程,在非常多情况下採用异步途径往往更有效率。
49. 以下两个方法同步吗?(自己发明)
class Test
{
synchronizedstatic voidsayHello3()
{
}
synchronizedvoid getX(){}
}
50、多线程有几种实现方法?同步有几种实现方法?
多线程有两种实现方法,各自是继承Thread类与实现Runnable接口
同步的实现方面有两种,各自是synchronized,wait与notify
wait():使一个线程处于等待状态,而且释放所持有的对象的lock。
sleep():使一个正在执行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,并且不是按优先级。
Allnotity():唤醒全部处入等待状态的线程,注意并非给全部唤醒线程一个对象的锁,而是让它们竞争。
51、启动一个线程是用run()还是start()? .
启动一个线程是调用start()方法,使线程就绪状态,以后能够被调度为运行状态,一个线程必须关联一些详细的运行代码,run()方法是该线程所关联的运行代码。
52、当一个线程进入一个对象的一个synchronized方法后,其他线程是否可进入此对象的其他方法?
分几种情况:
1.其它方法前是否加了synchronizedkeyword,假设没加,则能。
2.假设这种方法内部调用了wait,则能够进入其它synchronized方法。
3.假设其它个方法都加了synchronizedkeyword,而且内部没有调用wait,则不能。
4.假设其它方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,由于非静态的方法用的是this。
53、线程的基本概念、线程的基本状态以及状态之间的关系
一个程序中能够有多条运行线索同一时候运行,一个线程就是程序中的一条运行线索,每一个线程上都关联有要运行的代码,即能够有多段程序代码同一时候运行,每一个程序至少都有一个线程,即main方法运行的那个线程。假设仅仅是一个cpu,它怎么能够同一时候运行多段程序呢?这是从宏观上来看的,cpu一会运行a线索,一会运行b线索,切换时间非常快,给人的感觉是a,b在同一时候运行,好比大家在同一个办公室上网,仅仅有一条链接到外部网线,事实上,这条网线一会为a传数据,一会为b传数据,因为切换时间非常短暂,所以,大家感觉都在同一时候上网。
状态:就绪,执行,synchronize堵塞,wait和sleep挂起,结束。wait必须在synchronized内部调用。
调用线程的start方法后线程进入就绪状态,线程调度系统将就绪状态的线程转为执行状态,遇到synchronized语句时,由执行状态转为堵塞,当synchronized获得锁后,由堵塞转为执行,在这样的情况能够调用wait方法转为挂起状态,当线程关联的代码执行完后,线程变为结束状态。
54、简述synchronized和java.util.concurrent.locks.Lock的异同?
主要同样点:Lock能完毕synchronized所实现的全部功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自己主动释放锁,而Lock一定要求程序猿手工释放,而且必须在finally从句中释放。Lock还有更强大的功能,比如,它的tryLock方法能够非堵塞方式去拿锁。
举例说明(对以下的题用lock进行了改写):
package com.huawei.interview;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
publicclass ThreadTest {
/**
* @paramargs
*/
private int j;
private Lock lock =newReentrantLock();
public static voidmain(String[] args) {
// TODO Auto-generated method stub
ThreadTest tt = new ThreadTest();
for(int i=0;i<2;i++)
{
new Thread(tt.new Adder()).start();
new Thread(tt.new Subtractor()).start();
}
}
private class SubtractorimplementsRunnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j--="+ j--);
//这里抛异常了,锁能释放吗?
}*/
lock.lock();
try
{
System.out.println("j--="+ j--);
}finally
{
lock.unlock();
}
}
}
}
private class AdderimplementsRunnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j++="+ j++);
}*/
lock.lock();
try
{
System.out.println("j++="+ j++);
}finally
{
lock.unlock();
}
}
}
}
}
55、设计4个线程,当中两个线程每次对j添加1,另外两个线程对j每次降低1。写出程序。
下面程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。
public class ThreadTest1
{
private int j;
public static void main(String args[]){
ThreadTest1 tt=newThreadTest1();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(inti=0;i<2;i++){
Thread t=newThread(inc);
t.start();
t=new Thread(dec);
t.start();
}
}
private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+"-inc:"+j);
}
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
}
class Inc implements Runnable{
public void run(){
for(inti=0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
public void run(){
for(inti=0;i<100;i++){
dec();
}
}
}
}
----------随手再写的一个-------------
class A
{
JManger j =new JManager();
main()
{
new A().call();
}
void call
{
for(int i=0;i<2;i++)
{
new Thread(
newRunnable(){ public void run(){while(true){j.accumulate()}}}
).start();
new Thread(newRunnable(){ public void run(){while(true){j.sub()}}}).start();
}
}
}
class JManager
{
private j = 0;
public synchronized voidsubtract()
{
j--
}
public synchronized voidaccumulate()
{
j++;
}
}
56、子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。
终于的程序代码例如以下:
publicclass ThreadTest {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
new ThreadTest().init();
}
public void init()
{
final Business business =newBusiness();
new Thread(
new Runnable()
{
public voidrun() {
for(inti=0;i<50;i++)
{
business.SubThread(i);
}
}
}
).start();
for(int i=0;i<50;i++)
{
business.MainThread(i);
}
}
private class Business
{
booleanbShouldSub =true;//这里相当于定义了控制该谁运行的一个信号灯
public synchronized voidMainThread(int i)
{
if(bShouldSub)
try {
this.wait();
} catch(InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
for(int j=0;j<5;j++)
{
System.out.println(Thread.currentThread().getName()+ ":i=" + i +",j=" + j);
}
bShouldSub =true;
this.notify();
}
public synchronized voidSubThread(int i)
{
if(!bShouldSub)
try {
this.wait();
} catch (InterruptedExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ":i=" + i +",j=" + j);
}
bShouldSub =false;
this.notify();
}
}
}
备注:不可能一上来就写出上面的完整代码,最初写出来的代码例如以下,问题在于两个线程的代码要參照同一个变量,即这两个线程的代码要共享数据,所以,把这两个线程的运行代码搬到同一个类中去:
package com.huawei.interview.lym;
publicclass ThreadTest {
private static booleanbShouldMain=false;
public static void main(String[]args) {
// TODO Auto-generated method stub
/*new Thread(){
public void run()
{
for(int i=0;i<50;i++)
{
for(int j=0;j<10;j++)
{
System.out.println("i="+ i + ",j=" + j);
}
}
}
}.start();*/
//final String str = newString("");
new Thread(
new Runnable()
{
public voidrun()
{
for(inti=0;i<50;i++)
{
synchronized(ThreadTest.class) {
if(bShouldMain)
{
try {
ThreadTest.class.wait();}
catch(InterruptedException e) {
e.printStackTrace();
}
}
for(intj=0;j<10;j++)
{
System.out.println(
Thread.currentThread().getName()+
"i="+ i + ",j=" + j);
}
bShouldMain= true;
ThreadTest.class.notify();
}
}
}
}
).start();
for(int i=0;i<50;i++)
{
synchronized (ThreadTest.class){
if(!bShouldMain)
{
try {
ThreadTest.class.wait();}
catch(InterruptedException e) {
e.printStackTrace();
}
}
for(intj=0;j<5;j++)
{
System.out.println(
Thread.currentThread().getName()+
"i=" + i +",j=" + j);
}
bShouldMain =false;
ThreadTest.class.notify();
}
}
}
}
以下使用jdk5中的并发库来实现的:
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
public class ThreadTest
{
private static Locklock = new ReentrantLock();
private staticCondition subThreadCondition = lock.newCondition();
private staticboolean bBhouldSubThread = false;
public static voidmain(String [] args)
{
ExecutorServicethreadPool = Executors.newFixedThreadPool(3);
threadPool.execute(newRunnable(){
publicvoid run()
{
for(inti=0;i<50;i++)
{
lock.lock();
try
{
if(!bBhouldSubThread)
subThreadCondition.await();
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ",j=" + j);
}
bBhouldSubThread= false;
subThreadCondition.signal();
}catch(Exceptione)
{
}
finally
{
lock.unlock();
}
}
}
});
threadPool.shutdown();
for(inti=0;i<50;i++)
{
lock.lock();
try
{
if(bBhouldSubThread)
subThreadCondition.await();
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ",j=" + j);
}
bBhouldSubThread= true;
subThreadCondition.signal();
}catch(Exceptione)
{
}
finally
{
lock.unlock();
}
}
}
}
57、介绍Collection框架的结构
答:任意发挥题,天南海北谁便谈,仅仅要让别认为你知识渊博,理解透彻就可以。
58、Collection框架中实现比較要实现什么接口
comparable/comparator
59、ArrayList和Vector的差别
答:
这两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后能够按位置索引號取出某个元素,,而且当中的数据是同意反复的,这是HashSet之类的集合的最大不同处,HashSet之类的集合不能够按索引號去检索当中的元素,也不同意有反复的元素(本来题目问的与hashset没有不论什么关系,但为了说清楚ArrayList与Vector的功能,我们使用对例如式,更有利于说明问题)。
接着才说ArrayList与Vector的差别,这主要包含两个方面:.
(1)同步性:
Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。假设仅仅有一个线程会訪问到集合,那最好是使用ArrayList,由于它不考虑线程安全,效率会高些;假设有多个线程会訪问到集合,那最好是使用Vector,由于不须要我们自己再去考虑和编写线程安全的代码。
备注:对于Vector&ArrayList、Hashtable&HashMap,要记住线程安全的问题,记住Vector与Hashtable是旧的,是java一诞生就提供了的,它们是线程安全的,ArrayList与HashMap是java2时才提供的,它们是线程不安全的。所以,我们讲课时先讲老的。
(2)数据增长:
ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就须要添加ArrayList与Vector的存储空间,每次要添加存储空间时,不是仅仅添加一个存储单元,而是添加多个存储单元,每次添加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明白规定(从源码看到的是增长为原来的1.5倍)。ArrayList与Vector都能够设置初始的空间大小,Vector还能够设置增长的空间大小,而ArrayList没有提供设置增长空间的方法。
总结:即Vector增长原来的一倍,ArrayList添加原来的0.5倍。
60、HashMap和Hashtable的差别
(条理上还须要整理,也是先说同样点,再说不同点)
HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完毕了Map接口,主要差别在于HashMap同意空(null)键值(key),因为非线程安全,在仅仅有一个线程訪问的情况下,效率要高于Hashtable。
HashMap同意将null作为一个entry的key或者value,而Hashtable不同意。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。由于contains方法easy让人引起误解。
Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程訪问Hashtable时,不须要自己为它的方法实现同步,而HashMap就必须为之提供外同步。
Hashtable和HashMap採用的hash/rehash算法都大概一样,所以性能不会有非常大的差异。
就HashMap与HashTable主要从三方面来说。
一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现
二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的
三.值:仅仅有HashMap能够让你将空值作为一个表的条目的key或value
61、List和 Map差别?
一个是存储单列数据的集合,还有一个是存储键和值这种双列数据的集合,List中存储的数据是有顺序,而且同意反复;Map中存储的数据是没有顺序的,其键是不能反复的,它的值是能够有反复的。
62、List, Set, Map是否继承自Collection接口?
List,Set是,Map不是
63、List、Map、Set三个接口,存取元素时,各有什么特点?
这种题属于任意发挥题:这种题比較考水平,两个方面的水平:一是要真正明确这些内容,二是要有较强的总结和表述能力。假设你明确,但表述不清楚,在别人那里则等同于不明确。
首先,List与Set具有相似性,它们都是单列元素的集合,所以,它们有一个功共同的父接口,叫Collection。Set里面不同意有反复的元素,所谓反复,即不能有两个相等(注意,不是不过同样)的对象,即如果Set集合中有了一个A对象,如今我要向Set集合再存入一个B对象,但B对象与A对象equals相等,则B对象存储不进去,所以,Set集合的add方法有一个boolean的返回值,当集合中没有某个元素,此时add方法可成功增加该元素时,则返回true,当集合含有与某个元素equals相等的元素时,此时add方法无法增加该元素,返回结果为false。Set取元素时,没法说取第几个,只能以Iterator接口取得全部的元素,再逐一遍历各个元素。
List表示有先后顺序的集合,注意,不是那种按年龄、按大小、按价格之类的排序。当我们多次调用add(Obj e)方法时,每次增加的对象就像火车站买票有排队顺序一样,按先来后到的顺序排序。有时候,也能够插队,即调用add(int index,Obj e)方法,就能够指定当前对象在集合中的存放位置。一个对象能够被重复存储进List中,每调用一次add方法,这个对象就被插入进集合中一次,事实上,并非把这个对象本身存储进了集合中,而是在集合中用一个索引变量指向这个对象,当这个对象被add多次时,即相当于集合中有多个索引指向了这个对象,如图x所看到的。List除了能够以Iterator接口取得全部的元素,再逐一遍历各个元素之外,还能够调用get(index i)来明白说明取第几个。
Map与List和Set不同,它是双列的集合,当中有put方法,定义例如以下:put(obj key,objvalue),每次存储时,要存储一对key/value,不能存储反复的key,这个反复的规则也是按equals比較相等。取则能够依据key获得相应的value,即get(Object key)返回值为key所相应的value。另外,也能够获得全部的key的结合,还能够获得全部的value的结合,还能够获得key和value组合成的Map.Entry对象的集合。
List 以特定次序来持有元素,可有反复元素。Set无法拥有反复元素,内部排序。Map保存key-value值,value可多值。
HashSet依照hashcode值的某种运算方式进行存储,而不是直接按hashCode值的大小进行存储。比如,"abc"---> 78,"def" ---> 62,"xyz" ---> 65在hashSet中的存储顺序不是62,65,78,这些问题感谢曾经一个叫崔健的学员提出,最后通过查看源代码给他解释清楚,看本次培训学员其中有多少能看懂源代码。LinkedHashSet按插入的顺序存储,那被存储对象的hashcode方法还有什么作用呢?学员想想!hashset集合比較两个对象是否相等,首先看hashcode方法是否相等,然后看equals方法是否相等。new两个Student插入到HashSet中,看HashSet的size,实现hashcode和equals方法后再看size。
同一个对象能够在Vector中增加多次。往集合里面加元素,相当于集合里用一根绳子连接到了目标对象。往HashSet中却加不了多次的。
64、说出ArrayList,Vector, LinkedList的存储性能和特性
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便添加和插入元素,它们都同意直接按序号索引元素,可是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector因为使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据须要进行前向或后向遍历,可是插入数据时仅仅须要记录本项的前后项就可以,所以插入速度较快。
LinkedList也是线程不安全的,LinkedList提供了一些方法,使得LinkedList能够被当作堆栈和队列来使用。
65、去掉一个Vector集合中反复的元素
Vector newVector = new Vector();
For (int i=0;i<vector.size();i++)
{
Object obj = vector.get(i);
if(!newVector.contains(obj);
newVector.add(obj);
}
另一种简单的方式,HashSet set = new HashSet(vector);
66、Collection和 Collections的差别。
Collection是集合类的上级接口,继承与他的接口主要有Set和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
67、Set里的元素是不能反复的,那么用什么方法来区分反复与否呢?是用==还是equals()?它们有何差别?
Set里的元素是不能反复的,元素反复与否是使用equals()方法进行推断的。
equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。
68、你所知道的集合类都有哪些?主要方法?
最经常使用的集合类是 List 和 Map。 List的详细实现包含 ArrayList和 Vector,它们是可变大小的列表,比較适合构建、存储和操作不论什么类型对象的元素列表。 List适用于按数值索引訪问元素的情形。
Map 提供了一个更通用的元素存储方法。 Map集合类用于存储元素对(称作"键"和"值"),当中每一个键映射到一个值。
ArrayList/VectoràList
àCollection
HashSet/TreeSetàSet
PropetiesàHashTable
àMap
Treemap/HashMap
我记的不是方法名,而是思想,我知道它们都有增删改查的方法,但这些方法的详细名称,我记得不是非常清楚,对于set,大概的方法是add,remove, contains;对于map,大概的方法就是put,remove,contains等,由于,我仅仅要在eclispe下按点操作符,非常自然的这些方法就出来了。我记住的一些思想就是List类会有get(int index)这个方案,由于它能够按顺序取元素,而set类中没有get(int index)这个方案。List和set都能够迭代出全部元素,迭代时先要得到一个iterator对象,所以,set和list类都有一个iterator方法,用于返回那个iterator对象。map能够返回三个集合,一个是返回全部的key的集合,另外一个返回的是全部value的集合,再一个返回的key和value组合成的EntrySet对象的集合,map也有get方法,參数是key,返回值是key相应的value。
69、两个对象值同样(x.equals(y) == true),但却可有不同的hash code,这句话对不正确?
对。
假设对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。
假设不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是能够的,比如arrayList存储的对象就不用实现hashcode,当然,我们没有理由不实现,通常都会去实现的。
70、TreeSet里面放对象,假设同一时候放入了父类和子类的实例对象,那比較时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常!
(应该是没有针对问题的确切的答案,当前的add方法放入的是哪个对象,就调用哪个对象的compareTo方法,至于这个compareTo方法怎么做,就看当前这个对象的类中是怎样编写这种方法的)
实验代码:
publicclass ParentimplementsComparable {
private int age = 0;
public Parent(int age){
this.age = age;
}
public int compareTo(Object o){
// TODO Auto-generated method stub
System.out.println("method ofparent");
Parent o1 = (Parent)o;
returnage>o1.age?1:age<o1.age?-1:0;
}
}
publicclass Childextends Parent {
public Child(){
super(3);
}
public int compareTo(Object o){
// TODO Auto-generated methodstub
System.out.println("methodof child");
// Child o1 = (Child)o;
return 1;
}
}
publicclass TreeSetTest {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
TreeSet set = new TreeSet();
set.add(newParent(3));
set.add(new Child());
set.add(newParent(4));
System.out.println(set.size());
}
}
71、说出一些经常使用的类,包,接口,请各举5个
要让人家感觉你对java ee开发非常熟,所以,不能只只列core java中的那些东西,要多列你在做ssh项目中涉及的那些东西。就写你近期写的那些程序中涉及的那些类。
经常使用的类:BufferedReader BufferedWriter FileReader FileWirter String Integer
java.util.Date,System,Class,List,HashMap
经常使用的包:java.lang java.io java.util java.sql,javax.servlet,org.apache.strtuts.action,org.hibernate
经常使用的接口:Remote List Map Document NodeList,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)、Session(Hibernate),HttpSession
72、java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们各自是哪些类?
字节流,字符流。字节流继承于InputStream OutputStream,字符流继承于InputStreamReaderOutputStreamWriter。在java.io包中还有更多的流,主要是为了提高性能和使用方便。
73、字节流与字符流的差别
要把一片二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一片二进制数据,无论输入输出设备是什么,我们要用统一的方式来完毕这些操作,用一种抽象的方式进行描写叙述,这个抽象描写叙述方式起名为IO流,相应的抽象类为OutputStream和InputStream,不同的实现类就代表不同的输入和输出设备,它们都是针对字节进行操作的。
在应用中,常常要全然是字符的一段文本输出去或读进来,用字节流能够吗?计算机中的一切终于都是二进制的字节形式存在。对于“中国”这些字符,首先要得到其相应的字节,然后将字节写入到输出流。读取时,首先读到的是字节,但是我们要把它显示为字符,我们须要将字节转换成字符。因为这种需求非常广泛,人家专门提供了字符流的包装类。
底层设备永远仅仅接受字节数据,有时候要写字符串究竟层设备,须要将字符串转成字节再进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向IO设别写入或读取字符串提供了一点点方便。
字符向字节转换时,要注意编码的问题,由于字符串转成字节数组,
事实上是转成该字符的某种编码的字节形式,读取也是反之的道理。
解说字节流与字符流关系的代码案例:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class IOTest {
public static void main(String[]args) throws Exception {
String str = "中国人";
/*FileOutputStreamfos = newFileOutputStream("1.txt");
fos.write(str.getBytes("UTF-8"));
fos.close();*/
/*FileWriter fw =new FileWriter("1.txt");
fw.write(str);
fw.close();*/
PrintWriter pw =new PrintWriter("1.txt","utf-8");
pw.write(str);
pw.close();
/*FileReader fr =new FileReader("1.txt");
char[] buf = newchar[1024];
int len =fr.read(buf);
String myStr = newString(buf,0,len);
System.out.println(myStr);*/
/*FileInputStreamfr = new FileInputStream("1.txt");
byte[] buf = newbyte[1024];
int len =fr.read(buf);
String myStr = newString(buf,0,len,"UTF-8");
System.out.println(myStr);*/
BufferedReader br =new BufferedReader(
newInputStreamReader(
newFileInputStream("1.txt"),"UTF-8"
)
);
String myStr =br.readLine();
br.close();
System.out.println(myStr);
}
}
74、什么是java序列化,怎样实现java序列化?或者请解释Serializable接口的作用。
我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,比如,要将java对象存储到硬盘或者传送给网络上的其它计算机,这个过程我们能够自己写代码去把一个java对象变成某个格式的字节流再传输,可是,jre本身就提供了这样的支持,我们能够调用OutputStream的writeObject方法来做,假设要让java帮我们做,要被传输的对象必须实现serializable接口,这样,javac编译时就会进行特殊处理,编译的类才干够被writeObject方法操作,这就是所谓的序列化。须要被序列化的类必须实现Serializable接口,该接口是一个mini接口,当中没有须要实现的方法,implementsSerializable仅仅是为了标注该对象是可被序列化的。
比如,在web开发中,假设对象被保存在了Session中,tomcat在重新启动时要把Session对象序列化到硬盘,这个对象就必须实现Serializable接口。假设对象要经过分布式系统进行网络传输或通过rmi等远程调用,这就须要在网络上传输对象,被传输的对象就必须实现Serializable接口。
75、描写叙述一下JVM载入class文件的原理机制?
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader是一个重要的Java执行时系统组件。它负责在执行时查找和装入类文件的类。
76、heap和stack有什么差别。
java的内存分为两类,一类是栈内存,一类是堆内存。栈内存是指程序进入一个方法时,会为这种方法单独分配一块私属存储空间,用于存储这种方法内部的局部变量,当这种方法结束时,分配给这种方法的栈会释放,这个栈中的变量也将随之释放。
堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,比如,使用new创建的对象都放在堆里,所以,它不会随方法的结束而消失。方法中的局部变量使用final修饰后,放在堆中,而不是栈中。
77、GC是什么?为什么要有GC?
GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员easy出现故障的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能能够自己主动监測对象是否超过作用域从而达到自己主动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
78、垃圾回收的长处和原理。并考虑2种回收机制。
Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序猿最头疼的内存管理的问题迎刃而解,它使得Java程序猿在编敲代码的时候不再须要考虑内存管理。因为有个垃圾回收机制,Java中的对象不再有"作用域"的概念,仅仅有对象的引用才有"作用域"。垃圾回收能够有效的防止内存泄露,有效的使用能够使用的内存。垃圾回收器一般是作为一个单独的低级别的线程执行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序猿不能实时的调用垃圾回收器对某个对象或全部对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。
79、垃圾回收器的基本原理是什么?垃圾回收器能够立即回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
对于GC来说,当程序猿创建对象时,GC就開始监控这个对象的地址、大小以及使用情况。通常,GC採用有向图的方式记录和管理堆(heap)中的全部对象。通过这样的方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。能够。程序猿能够手动运行System.gc(),通知GC运行,可是Java语言规范并不保证GC一定会运行。
80、什么时候用assert。
assertion(断言)在软件开发中是一种经常使用的调试方式,非常多开发语言中都支持这样的机制。在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;假设该值为false,说明程序已经处于不对的状态下,assert将给出警告或退出。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和測试时开启。为了提高性能,在软件公布后,assertion检查一般是关闭的。
package com.huawei.interview;
publicclass AssertTest {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
int i = 0;
for(i=0;i<5;i++)
{
System.out.println(i);
}
//如果程序不小心多了一句--i;
--i;
assert i==5;
}
}
81、java中会存在内存泄漏吗,请简单描写叙述。
所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占领在内存中。java中有垃圾回收机制,它能够保证一对象不再被引用的时候,即对象编程了孤儿的时候,对象将自己主动被垃圾回收器从内存中清除掉。因为Java使用有向图的方式进行垃圾回收管理,能够消除引用循环的问题,比如有两个对象,相互引用,仅仅要它们和根进程不可达的,那么GC也是能够回收它们的,比如以下的代码能够看到这样的情况的内存回收:
package com.huawei.interview;
import java.io.IOException;
publicclass GarbageTest {
/**
* @paramargs
* @throwsIOException
*/
public static voidmain(String[] args)throws IOException {
// TODO Auto-generated method stub
try {
gcTest();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("hasexited gcTest!");
System.in.read();
System.in.read();
System.out.println("out begingc!");
for(int i=0;i<100;i++)
{
System.gc();
System.in.read();
System.in.read();
}
}
private static voidgcTest()throws IOException {
System.in.read();
System.in.read();
Person p1 = new Person();
System.in.read();
System.in.read();
Person p2 = new Person();
p1.setMate(p2);
p2.setMate(p1);
System.out.println("beforeexit gctest!");
System.in.read();
System.in.read();
System.gc();
System.out.println("exitgctest!");
}
private static classPerson
{
byte[] data =new byte[20000000];
Person mate = null;
public void setMate(Personother)
{
mate = other;
}
}
}
java中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就非常可能发生内存泄露,虽然短生命周期对象已经不再须要,可是由于长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景,通俗地说,就是程序猿可能创建了一个对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用可是却无法被垃圾回收器回收的,这就是java中可能出现内存泄露的情况,比如,缓存系统,我们载入了一个对象放在缓存中(比如放在一个全局map对象中),然后一直不再使用它,这个对象一直被缓存引用,但却不再被使用。
检查java中的内存泄露,一定要让程序将各种分支情况都完整运行到程序结束,然后看某个对象是否被使用过,假设没有,则才干判定这个对象属于内存泄露。
假设一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但因为内部类持久外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄露。
以下内容来自于网上(主要特点就是清空堆栈中的某个元素,并非彻底把它从数组中拿掉,而是把存储的总数降低,本人写得能够比这个好,在拿掉某个元素时,顺便也让它从数组中消失,将那个元素所在的位置的值设置为null就可以):
我实在想不到比那个堆栈更经典的样例了,以致于我还要引用别人的样例,以下的样例不是我想到的,是书上看到的,当然假设没有在书上看到,可能过一段时间我自己也想的到,但是那时我说是我自己想到的也没有人相信的。
public class Stack {
private Object[] elements=new Object[10];
private int size = 0;
public void push(Object e){
ensureCapacity();
elements[size++] = e;
}
public Object pop(){
if( size == 0)
throw new EmptyStackException();
return elements[--size];
}
private void ensureCapacity(){
if(elements.length == size){
Object[] oldElements = elements;
elements = new Object[2 * elements.length+1];
System.arraycopy(oldElements,0, elements, 0, size);
}
}
}
上面的原理应该非常easy,假如堆栈加了10个元素,然后所有弹出来,尽管堆栈是空的,没有我们要的东西,可是这是个对象是无法回收的,这个才符合了内存泄露的两个条件:无用,无法回收。
可是就是存在这种东西也不一定会导致什么样的后果,假设这个堆栈用的比較少,也就浪费了几个K内存而已,反正我们的内存都上G了,哪里会有什么影响,再说这个东西非常快就会被回收的,有什么关系。以下看两个样例。
样例1
public class Bad{
public static Stack s=Stack();
static{
s.push(new Object());
s.pop(); //这里有一个对象发生内存泄露
s.push(new Object()); //上面的对象能够被回收了,等于是自愈了
}
}
由于是static,就一直存在到程序退出,可是我们也能够看到它有自愈功能,就是说假设你的Stack最多有100个对象,那么最多也就仅仅有100个对象无法被回收事实上这个应该非常easy理解,Stack内部持有100个引用,最坏的情况就是他们都是没用的,由于我们一旦放新的进取,曾经的引用自然消失!
内存泄露的第二种情况:当一个对象被存储进HashSet集合中以后,就不能改动这个对象中的那些參与计算哈希值的字段了,否则,对象改动后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这样的情况下,即使在contains方法使用该对象的当前引用作为的參数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄露。
82、能不能自己写个类,也叫java.lang.String?
能够,但在应用的时候,须要用自己的类载入器去载入,否则,系统的类载入器永远仅仅是去载入jre.jar包中的那个java.lang.String。因为在tomcat的web应用程序中,都是由webapp自己的类载入器先自己载入WEB-INF/classess文件夹中的类,然后才托付上级的类载入器载入,假设我们在tomcat的web应用程序中写一个java.lang.String,这时候Servlet程序载入的就是我们自己写的java.lang.String,可是这么干就会出非常多潜在的问题,原来全部用了java.lang.String类的都将出现故障。
尽管java提供了endorsed技术,可以覆盖jdk中的某些类,详细做法是….。可是,可以被覆盖的类是有限制范围,反正不包含java.lang这种包中的类。
(以下的比如主要是便于大家学习理解仅仅用,不要作为答案的一部分,否则,人家怀疑是题目泄露了)比如,执行以下的程序:
package java.lang;
publicclass String {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
System.out.println("string");
}
}
报告的错误例如以下:
java.lang.NoSuchMethodError:main
Exception inthread "main"
这是由于载入了jre自带的java.lang.String,而该类中没有main方法。
83. Java代码查错
1.
abstract class Name {
private String name;
public abstract boolean isStupidName(String name) {}
}
大侠们,这有何错误?
答案: 错。abstract method必须以分号结尾,且不带花括号。
2.
public class Something {
void doSomething () {
private String s = "";
int l = s.length();
}
}
有错吗?
答案: 错。局部变量前不能放置不论什么訪问修饰符 (private,public,和protected)。final能够用来修饰局部变量
(final如同abstract和strictfp,都是非訪问修饰符,strictfp仅仅能修饰class和method而非variable)。
3.
abstract class Something {
private abstract String doSomething ();
}
这好像没什么错吧?
答案: 错。abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)详细细节的,怎么能够用private把abstract
method封锁起来呢? (同理,abstract method前不能加final)。
4.
public class Something {
public int addOne(final int x) {
return ++x;
}
}
这个比較明显。
答案: 错。int x被修饰成final,意味着x不能在addOne method中被改动。
5.
public class Something {
public static void main(String[] args) {
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o) {
o.i++;
}
}
class Other {
public int i;
}
和上面的非常相似,都是关于final的问题,这有错吗?
答案: 正确。在addOne method中,參数o被修饰成final。假设在addOne method里我们改动了o的reference
(比方: o = new Other();),那么如同上例这题也是错的。但这里改动的是o的member vairable
(成员变量),而o的reference并没有改变。
6.
class Something {
int i;
public void doSomething() {
System.out.println("i = "+ i);
}
}
有什么错呢? 看不出来啊。
答案: 正确。输出的是"i = 0"。int i属於instant variable (实例变量,或叫成员变量)。instant variable有default value。int的default value是0。
7.
class Something {
final int i;
public void doSomething() {
System.out.println("i = "+ i);
}
}
和上面一题仅仅有一个地方不同,就是多了一个final。这难道就错了吗?
答案: 错。final int i是个final的instant variable (实例变量,或叫成员变量)。final的instant variable没有default value,必须在constructor (构造器)结束之前被赋予一个明白的值。能够改动为"final int i =0;"。
8.
public class Something {
public static void main(String[] args) {
Something s = new Something();
System.out.println("s.doSomething() returns " + doSomething());
}
public String doSomething() {
return "Do something ...";
}
}
看上去非常完美。
答案: 错。看上去在main里call doSomething没有什么问题,毕竟两个methods都在同一个class里。但细致看,main是static的。static method不能直接call non-staticmethods。可改成"System.out.println("s.doSomething()returns " + s.doSomething());"。同理,static method不能訪问non-static instant variable。
9.
此处,Something类的文件名称叫OtherThing.java
class Something {
private static void main(String[] something_to_do){
System.out.println("Dosomething ...");
}
}
这个好像非常明显。
答案: 正确。从来没有人说过Java的Class名字必须和其文件名称同样。但public class的名字必须和文件名称同样。
10.
interface A{
int x = 0;
}
class B{
int x =1;
}
class C extends B implements A {
public void pX(){
System.out.println(x);
}
public static void main(String[] args) {
new C().pX();
}
}
答案:错误。在编译时会错误发生(错误描写叙述不同的JVM有不同的信息,意思就是未明白的x调用,两个x都匹配(就象在同一时候import java.util和java.sql两个包时直接声明Date一样)。对于父类的变量,能够用super.x来明白,而接口的属性默认隐含为 public staticfinal.所以能够通过A.x来明白。
11.
interface Playable {
void play();
}
interface Bounceable {
void play();
}
interface Rollable extends Playable, Bounceable {
Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
private String name;
public String getName() {
return name;
}
public Ball(String name) {
this.name =name;
}
public void play() {
ball = newBall("Football");
System.out.println(ball.getName());
}
}
这个错误不easy发现。
答案: 错。"interfaceRollable extends Playable, Bounceable"没有问题。interface可继承多个interfaces,所以这里没错。问题出在interface Rollable里的"Ball ball =new Ball("PingPang");"。不论什么在interface里声明的interface variable (接口变量,也可称成员变量),默觉得public static final。也就是说"Ball ball = new Ball("PingPang");"实际上是"public staticfinal Ball ball = new Ball("PingPang");"。在Ball类的Play()方法中,"ball = newBall("Football");"改变了ball的reference,而这里的ball来自Rollable interface,Rollable interface里的ball是public static final的,final的object是不能被改变reference的。因此编译器将在"ball = newBall("Football");"这里显示有错。
二.算法与编程
1、编写一个程序,将a.txt文件里的单词与b.txt文件里的单词交替合并到c.txt文件里,a.txt文件里的单词用回车符分隔,b.txt文件里用回车或空格进行分隔。
答:
packagecn.itcast;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
public class MainClass{
public static voidmain(String[] args) throws Exception{
FileManager a= new FileManager("a.txt",new char[]{‘\n‘});
FileManager b= new FileManager("b.txt",new char[]{‘\n‘,‘ ‘});
FileWriter c= new FileWriter("c.txt");
String aWord= null;
String bWord= null;
while((aWord= a.nextWord()) !=null ){
c.write(aWord+ "\n");
bWord= b.nextWord();
if(bWord!= null)
c.write(bWord+ "\n");
}
while((bWord= b.nextWord()) != null){
c.write(bWord+ "\n");
}
c.close();
}
}
class FileManager{
String[] words =null;
int pos = 0;
publicFileManager(String filename,char[] seperators) throws Exception{
File f = newFile(filename);
FileReaderreader = new FileReader(f);
char[] buf =new char[(int)f.length()];
int len =reader.read(buf);
Stringresults = new String(buf,0,len);
String regex= null;
if(seperators.length>1 ){
regex= "" + seperators[0] + "|" + seperators[1];
}else{
regex= "" + seperators[0];
}
words =results.split(regex);
}
public StringnextWord(){
if(pos ==words.length)
returnnull;
returnwords[pos++];
}
}
2、编写一个程序,将d:\java文件夹下的全部.java文件拷贝到d:\jad文件夹下,并将原来文件的扩展名从.java改为.jad。
(大家正在做上面这道题,网上迟到的朋友也请做做这道题,找工作必须能编写这些简单问题的代码!)
答:listFiles方法接受一个FileFilter对象,这个FileFilter对象就是过虑的策略对象,不同的人提供不同的FileFilter实现,即提供了不同的过滤策略。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Jad2Java {
public static voidmain(String[] args) throws Exception {
File srcDir =new File("java");
if(!(srcDir.exists()&& srcDir.isDirectory()))
thrownew Exception("文件夹不存在");
File[] files= srcDir.listFiles(
newFilenameFilter(){
publicboolean accept(File dir, String name) {
returnname.endsWith(".java");
}
}
);
System.out.println(files.length);
File destDir= new File("jad");
if(!destDir.exists())destDir.mkdir();
for(File f:files){
FileInputStream fis = new FileInputStream(f);
StringdestFileName = f.getName().replaceAll("\\.java$", ".jad");
FileOutputStreamfos = new FileOutputStream(new File(destDir,destFileName));
copy(fis,fos);
fis.close();
fos.close();
}
}
private static voidcopy(InputStream ips,OutputStream ops) throws Exception{
int len = 0;
byte[] buf =new byte[1024];
while((len =ips.read(buf)) != -1){
ops.write(buf,0,len);
}
}
}
由本题总结的思想及策略模式的解析:
1.
class jad2java{
1. 得到某个文件夹下的全部的java文件集合
1.1 得到文件夹 File srcDir = newFile("d:\\java");
1.2 得到文件夹下的全部java文件:File[] files =srcDir.listFiles(new MyFileFilter());
1.3 仅仅想得到.java的文件: class MyFileFilterimplememyts FileFilter{
publicboolean accept(File pathname){
returnpathname.getName().endsWith(".java")
}
}
2.将每一个文件拷贝到另外一个文件夹,并改扩展名
2.1 得到目标文件夹,假设目标文件夹不存在,则创建之
2.2 依据源文件名称得到目标文件名称,注意要用正則表達式,注意.的转义。
2.3 依据表示文件夹的File和目标文件名称的字符串,得到表示目标文件的File。
//要在硬盘中准确地创建出一个文件,须要知道文件名称和文件的文件夹。
2.4 将源文件的流拷贝成目标文件流,拷贝方法独立成为一个方法,方法的參数採用抽象流的形式。
//方法接受的參数类型尽量面向父类,越抽象越好,这样适应面更宽广。
}
分析listFiles方法内部的策略模式实现原理
File[] listFiles(FileFilter filter){
File[] files =listFiles();
//ArraylistacceptedFilesList = new ArrayList();
File[] acceptedFiles= new File[files.length];
int pos = 0;
for(File file:files){
booleanaccepted = filter.accept(file);
if(accepted){
//acceptedFilesList.add(file);
acceptedFiles[pos++]= file;
}
}
Arrays.copyOf(acceptedFiles,pos);
//return(File[])accpetedFilesList.toArray();
}
3、编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串,但要保证汉字不被截取半个,如“我ABC”,4,应该截取“我AB”,输入“我ABC汉DEF”,6,应该输出“我ABC”,而不是“我ABC+汉的半个”。
答:
首先要了解中文字符有多种编码及各种编码的特征。
如果n为要截取的字节数。
public static voidmain(String[] args) throws Exception{
String str ="我a爱中华abc我爱传智def‘;
String str ="我ABC汉";
int num =trimGBK(str.getBytes("GBK"),5);
System.out.println(str.substring(0,num));
}
public staticint trimGBK(byte[] buf,int n){
int num = 0;
booleanbChineseFirstHalf = false;
for(inti=0;i<n;i++)
{
if(buf[i]<0&& !bChineseFirstHalf){
bChineseFirstHalf= true;
}else{
num++;
bChineseFirstHalf= false;
}
}
return num;
}
4、有一个字符串,当中包括中文字符、英文字符和数字字符,请统计和打印出各个字符的个数。
答:哈哈,事实上包括中文字符、英文字符、数字字符原来是出题者放的烟雾弹。
String content = “中国aadf的111萨bbb菲的zz萨菲”;
HashMap map = new HashMap();
for(int i=0;i<content.length;i++)
{
char c =content.charAt(i);
Integer num =map.get(c);
if(num == null)
num = 1;
else
num = num +1;
map.put(c,num);
}
for(Map.EntrySet entry : map)
{
system.out.println(entry.getkey()+ “:” + entry.getValue());
}
预计是当初面试的那个学员表述不清楚,问题非常可能是:
如果一串字符如"aaaabbc中国1512"要分别统计英文字符的数量,中文字符的数量,和数字字符的数量,如果字符中没有中文字符、英文字符、数字字符之外的其它特殊字符。
int engishCount;
int chineseCount;
int digitCount;
for(int i=0;i<str.length;i++)
{
charch = str.charAt(i);
if(ch>=’0’&& ch<=’9’)
{
digitCount++
}
elseif((ch>=’a’&& ch<=’z’) || (ch>=’A’ && ch<=’Z’))
{
engishCount++;
}
else
{
chineseCount++;
}
}
System.out.println(……………);
5、说明生活中遇到的二叉树,用java实现二叉树
这是组合设计模式。
我有非常多个(如果10万个)数据要保存起来,以后还须要从保存的这些数据中检索是否存在某个数据,(我想说出二叉树的优点,该怎么说呢?那就是说别人的缺点),假如存在数组中,那么,碰巧要找的数字位于99999那个地方,那查找的速度将非常慢,由于要从第1个依次往后取,取出来后进行比較。平衡二叉树(构建平衡二叉树须要先排序,我们这里就不作考虑了)能够非常好地解决问题,但二叉树的遍历(前序,中序,后序)效率要比数组低非常多,原理例如以下图:
代码例如以下:
package com.huawei.interview;
publicclass Node {
public int value;
public Node left;
public Node right;
public void store(intvalue)
{
if(value<this.value)
{
if(left ==null)
{
left = new Node();
left.value=http://www.mamicode.com/value;
}
else
{
left.store(value);
}
}
else if(value>this.value)
{
if(right ==null)
{
right = new Node();
right.value=http://www.mamicode.com/value;
}
else
{
right.store(value);
}
}
}
public boolean find(intvalue)
{
System.out.println("happen" +this.value);
if(value ==this.value)
{
return true;
}
else if(value>this.value)
{
if(right ==null)returnfalse;
return right.find(value);
}else
{
if(left ==null)returnfalse;
return left.find(value);
}
}
public void preList()
{
System.out.print(this.value+ ",");
if(left!=null)left.preList();
if(right!=null) right.preList();
}
public void middleList()
{
if(left!=null)left.preList();
System.out.print(this.value+ ",");
if(right!=null)right.preList();
}
public void afterList()
{
if(left!=null)left.preList();
if(right!=null)right.preList();
System.out.print(this.value+ ",");
}
public static voidmain(String [] args)
{
int [] data =new int[20];
for(inti=0;i<data.length;i++)
{
data[i] = (int)(Math.random()*100)+ 1;
System.out.print(data[i] +",");
}
System.out.println();
Node root = new Node();
root.value = data[0];
for(inti=1;i<data.length;i++)
{
root.store(data[i]);
}
root.find(data[19]);
root.preList();
System.out.println();
root.middleList();
System.out.println();
root.afterList();
}
}
-----------------重新临场写的代码---------------------------
importjava.util.Arrays;
importjava.util.Iterator;
public class Node{
private Node left;
private Node right;
private int value;
//private int num;
public Node(int value){
this.value = value;
}
public void add(int value){
if(value > this.value)
{
if(right != null)
right.add(value);
else
{
Node node = new Node(value);
right = node;
}
}
else{
if(left != null)
left.add(value);
else
{
Node node = new Node(value);
left = node;
}
}
}
public boolean find(int value){
if(value == this.value) return true;
else if(value > this.value){
if(right == null) return false;
else return right.find(value);
}else{
if(left == null) return false;
else return left.find(value);
}
}
public void display(){
System.out.println(value);
if(left != null) left.display();
if(right != null) right.display();
}
/*public Iterator iterator(){
}*/
public static void main(String[] args){
int[] values = new int[8];
for(int i=0;i<8;i++){
int num = (int)(Math.random() * 15);
//System.out.println(num);
//if(Arrays.binarySearch(values,num)<0)
if(!contains(values,num))
values[i] = num;
else
i--;
}
System.out.println(Arrays.toString(values));
Node root = new Node(values[0]);
for(int i=1;i<values.length;i++){
root.add(values[i]);
}
System.out.println(root.find(13));
root.display();
}
public static boolean contains(int [] arr,int value){
int i = 0;
for(;i<arr.length;i++){
if(arr[i] == value) return true;
}
return false;
}
}
6、从类似例如以下的文本文件里读取出全部的姓名,并打印出反复的姓名和反复的次数,并按反复次数排序:
1,张三,28
2,李四,35
3,张三,28
4,王五,35
5,张三,28
6,李四,35
7,赵六,28
8,田七,35
程序代码例如以下(答题要博得用人单位的喜欢,包名用该公司,面试前就提前查好该公司的网址,假设查不到,现场问也是能够的。还要加上实现思路的凝视):
package com.huawei.interview;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
publicclass GetNameTest {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
//InputStream ips =GetNameTest.class.getResourceAsStream("/com/huawei/interview/info.txt");
//用上一行凝视的代码和下一行的代码都能够,由于info.txt与GetNameTest类在同一包以下,所以,能够用以下的相对路径形式
Map results = new HashMap();
InputStream ips = GetNameTest.class.getResourceAsStream("info.txt");
BufferedReader in = newBufferedReader(new InputStreamReader(ips));
String line = null;
try {
while((line=in.readLine())!=null)
{
dealLine(line,results);
}
sortResults(results);
} catch (IOException e) {
// TODO Auto-generated catchblock
e.printStackTrace();
}
}
static class User
{
public String name;
public Integer value;
public User(String name,Integervalue)
{
this.name = name;
this.value = value;
}
@Override
public booleanequals(Object obj) {
// TODO Auto-generated methodstub
//以下的代码没有运行,说明往treeset中添加数据时,不会使用到equals方法。
boolean result =super.equals(obj);
System.out.println(result);
return result;
}
}
private static voidsortResults(Map results) {
// TODO Auto-generated method stub
TreeSet sortedResults =newTreeSet(
new Comparator(){
public intcompare(Object o1, Object o2) {
// TODOAuto-generated method stub
User user1 = (User)o1;
User user2 = (User)o2;
/*假设compareTo返回结果0,则觉得两个对象相等,新的对象不会添加到集合中去
* 所以,不能直接用以下的代码,否则,那些个数同样的其它姓名就打印不出来。
* */
//returnuser1.value-user2.value;
//returnuser1.value<user2.value?-1:user1.value=http://www.mamicode.com/=user2.value?0:1;
if(user1.value<user2.value)
{
return -1;
}else if(user1.value>user2.value)
{
return 1;
}else
{
returnuser1.name.compareTo(user2.name);
}
}
}
);
Iterator iterator =results.keySet().iterator();
while(iterator.hasNext())
{
String name = (String)iterator.next();
Integer value =(Integer)results.get(name);
if(value > 1)
{
sortedResults.add(newUser(name,value));
}
}
printResults(sortedResults);
}
private static voidprintResults(TreeSet sortedResults)
{
Iterator iterator = sortedResults.iterator();
while(iterator.hasNext())
{
User user = (User)iterator.next();
System.out.println(user.name +":" + user.value);
}
}
public static voiddealLine(String line,Map map)
{
if(!"".equals(line.trim()))
{
String [] results =line.split(",");
if(results.length == 3)
{
String name = results[1];
Integer value =(Integer)map.get(name);
if(value ==null)value = 0;
map.put(name,value + 1);
}
}
}
}
7、写一个Singleton出来。
第一种:饱汉模式
public classSingleTon {
private SingleTon(){
}
//实例化放在静态代码块里可提高程序的运行效率,但也可能更占用空间
private final static SingleTon instance =new SingleTon();
public static SingleTon getInstance(){
return instance;
}
}
另外一种:饥汉模式
public classSingleTon {
private SingleTon(){}
private static instance = null;//newSingleTon();
public static synchronized SingleTongetInstance(){
if(instance == null)
instance = new SingleTon();
return instance;
}
}
第三种:用枚举
public enum SingleTon{
ONE;
}
第三:更实际的应用(在什么情况用单例)
public classSequenceGenerator{
//以下是该类自身的业务功能代码
private int count = 0;
public synchronized int getSequence(){
++count;
}
//以下是把该类变成单例的代码
private SequenceGenerator(){}
private final static instance = newSequenceGenerator();
public static SingleTon getInstance(){
return instance;
}
}
第四:
public class MemoryDao
{
private HashMap map = new HashMap();
publicvoid add(Student stu1){
map.put(SequenceGenerator.getInstance().getSequence(),stu1);
}
//把MemoryDao变成单例
}
Singleton模式主要作用是保证在Java应用程序中,一个类Class仅仅有一个实例存在。
一般Singleton模式通常有几种种形式:
第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用当中的方法。
public class Singleton {
private Singleton(){}
//在自己内部定义自己一个实例,是不是非常奇怪?
//注意这是private仅仅供内部调用
private staticSingleton instance = new Singleton();
//这里提供了一个供外部訪问本class的静态方法,能够直接訪问
public staticSingleton getInstance() {
return instance;
}
}
另外一种形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//这种方法比上面有所改进,不用每次都进行生成对象,仅仅是第一次
//使用时生成实例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance;
}
}
其它形式:
定义一个类,它的构造函数为private的,全部方法为static的。
一般觉得第一种形式要更加安全些
8、递归算法题1
一个整数,大于0,不用循环和本地变量,依照n,2n,4n,8n的顺序递增,当值大于5000时,把值依照指定顺序输出来。
例:n=1237
则输出为:
1237,
2474,
4948,
9896,
9896,
4948,
2474,
1237,
提示:敲代码时,先致谢按递增方式的代码,写好递增的以后,再添加考虑递减部分。
public static void doubleNum(int n)
{
System.out.println(n);
if(n<=5000)
doubleNum(n*2);
System.out.println(n);
}
|
9、递归算法题2
第1个人10,第2个比第1个人大2岁,依次递推,请用递归方式计算出第8个人多大?
package cn.itcast;
import java.util.Date;
publicclass A1 {
public static voidmain(String [] args)
{
System.out.println(computeAge(8));
}
public static int computeAge(intn)
{
if(n==1)return 10;
returncomputeAge(n-1) + 2;
}
}
public static voidtoBinary(int n,StringBuffer result)
{
if(n/2 != 0)
toBinary(n/2,result);
result.append(n%2);
}
10、排序都有哪几种方法?请列举。用JAVA实现一个高速排序。
本人仅仅研究过冒泡排序、选择排序和高速排序,以下是高速排序的代码:
public class QuickSort {
/**
* 高速排序
* @param strDate
* @param left
* @param right
*/
public void quickSort(String[] strDate,int left,int right){
String middle,tempDate;
int i,j;
i=left;
j=right;
middle=strDate[(i+j)/2];
do{
while(strDate[i].compareTo(middle)<0&& i<right)
i++; //找出左边比中间值大的数
while(strDate[j].compareTo(middle)>0&& j>left)
j--; //找出右边比中间值小的数
if(i<=j){ //将左边大的数和右边小的数进行替换
tempDate=strDate[i];
strDate[i]=strDate[j];
strDate[j]=tempDate;
i++;
j--;
}
}while(i<=j); //当两者交错时停止
if(i<right){
quickSort(strDate,i,right);//从
}
if(j>left){
quickSort(strDate,left,j);
}
}
/**
* @param args
*/
public static void main(String[] args){
String[] strVoid=newString[]{"11","66","22","0","55","22","0","32"};
QuickSort sort=new QuickSort();
sort.quickSort(strVoid,0,strVoid.length-1);
for(int i=0;i<strVoid.length;i++){
System.out.println(strVoid[i]+" ");
}
}
}
11、有数组a[n],用java代码将数组元素顺序颠倒
//用以下的也能够
//for(inti=0,int j=a.length-1;i<j;i++,j--)是否等效于for(int i=0;i<a.length/2;i++)呢?
importjava.util.Arrays;
public classSwapDemo{
public static void main(String[] args){
int [] a = new int[]{
(int)(Math.random() *1000),
(int)(Math.random() * 1000),
(int)(Math.random() *1000),
(int)(Math.random() *1000),
(int)(Math.random() * 1000)
};
System.out.println(a);
System.out.println(Arrays.toString(a));
swap(a);
System.out.println(Arrays.toString(a));
}
public static void swap(int a[]){
int len = a.length;
for(int i=0;i<len/2;i++){
int tmp = a[i];
a[i] = a[len-1-i];
a[len-1-i] = tmp;
}
}
}
12.金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出。
去零的代码:
returnsb.reverse().toString().replaceAll("零[拾佰仟]","零").replaceAll("零+万","万").replaceAll("零+元","元").replaceAll("零+","零");
public class RenMingBi {
/**
* @param args add by zxx ,Nov 29, 2008
*/
private static finalchar[] data = new char[]{
‘零‘,‘壹‘,‘贰‘,‘叁‘,‘肆‘,‘伍‘,‘陆‘,‘柒‘,‘捌‘,‘玖‘
};
private static finalchar[] units = new char[]{
‘元‘,‘拾‘,‘佰‘,‘仟‘,‘万‘,‘拾‘,‘佰‘,‘仟‘,‘亿‘
};
public static voidmain(String[] args) {
// TODOAuto-generated method stub
System.out.println(
convert(135689123));
}
public static Stringconvert(int money)
{
StringBuffersbf = new StringBuffer();
int unit = 0;
while(money!=0)
{
sbf.insert(0,units[unit++]);
intnumber = money%10;
sbf.insert(0,data[number]);
money/= 10;
}
returnsbf.toString();
}
}
三. html&JavaScript&ajax部分
1. 推断第二个日期比第一个日期大
怎样用脚本推断用户输入的的字符串是以下的时间格式2004-11-21必需要保证用户的输入是此格式,而且是时间,比方说月份不大于12等等,另外我需要用户输入两个,而且后一个要比前一个晚,仅仅同意用JAVASCRIPT,请具体帮助作答,,
//这里可用正則表達式推断提前推断一下格式,然后按下提取各时间字段内容
<script type="text/javascript">
window.onload =function()
{
//这么写是为了实现js代码与html代码的分离,当我改动js时,不能影响html代码。
document.getElementById("frm1").onsubmit=
function(){
vard1 = this.d1.value;
vard2 = this.d2.value;
if(!verifyDate(d1)) {alert("第一个日期格式不正确");return false;}
if(!verifyDate(d2)) {alert("第二个日期格式不正确");return false;}
if(!compareDate(d1,d2)){alert("第二个日期比第一日期小");return false;}
};
}
functioncompareDate(d1,d2)
{
var arrayD1= d1.split("-");
var date1 =new Date(arrayD1[0],arrayD1[1],arrayD1[2]);
var arrayD2= d2.split("-");
var date2 =new Date(arrayD2[0],arrayD2[1],arrayD2[2]);
if(date1> date2) return false;
return true;
}
functionverifyDate(d)
{
vardatePattern = /^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\d|3[0-1])$/;
returndatePattern.test(d);
}
</script>
<form id="frm1" action="xxx.html">
<input type="text" name="d1" />
<input type="text" name="d2" />
<input type="submit"/>
</form>
2. 用table显示n条记录,每3行换一次颜色,即1,2,3用红色字体,4,5,6用绿色字体,7,8,9用红颜色字体。
<body>
<table id="tbl">
<tr><td>1</td></tr>
<tr><td>2</td></tr>
<tr><td>3</td></tr>
<tr><td>4</td></tr>
<tr><td>5</td></tr>
<tr><td>6</td></tr>
<tr><td>7</td></tr>
<tr><td>8</td></tr>
<tr><td>9</td></tr>
<tr><td>10</td></tr>
</table>
</body>
<script type="text/javascript">
window.onload=function()
{
var tbl =document.getElementById("tbl");
rows =tbl.getElementsByTagName("tr");
for(i=0;i<rows.length;i++)
{
var j= parseInt(i/3);
if(j%2==0)rows[i].style.backgroundColor="#f00";
else rows[i].style.backgroundColor="#0f0";
}
}
</script>
3、HTML的 form提交之前怎样验证数值文本框的内容所有为数字?否则的话提示用户并终止提交?
<form onsubmit=’return chkForm(this)’>
<input type="text" name="d1"/>
<input type="submit"/>
</form>
<script type=”text/javascript” />
function chkForm(this)
{
var value = thist.d1.value;
var len =value.length;
for(vari=0;i<len;i++)
{
if(value.charAt(i)>"9"|| value.charAt(i)<"0")
{
alert("含有非数字字符");
returnfalse;
}
}
return true;
}
</script>
4、请写出用于校验HTML文本框中输入的内容所有为数字的javascript代码
<input type="text" id="d1" onblur=" chkNumber(this)"/>
<script type=”text/javascript” />
function chkNumber(eleText)
{
var value =eleText.value;
var len =value.length;
for(vari=0;i<len;i++)
{
if(value.charAt(i)>"9"|| value.charAt(i)<"0")
{
alert("含有非数字字符");
eleText.focus();
break;
}
}
}
</script>
除了写完代码,还应该在网页上写出实验步骤和在代码中增加实现思路,让面试官一看就明确你的意图和检查你的结果。
5、说说你用过那些ajax技术和框架,说说它们的差别
四. Java web部分
1、Tomcat的优化经验
答:去掉对web.xml的监视,把jsp提前编辑成Servlet。
有富余物理内存的情况,加大tomcat使用的jvm的内存
2、HTTP请求的GET与POST方式的差别
答:servlet有良好的生存期的定义,包含载入和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。
3、解释一下什么是servlet;
答:servlet有良好的生存期的定义,包含载入和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。
4、说一说Servlet的生命周期?
答:servlet有良好的生存期的定义,包含载入和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。
Servlet被server实例化后,容器执行其init方法,请求到达时执行其service方法,service方法自己主动派遣执行与请求相应的doXXX方法(doGet,doPost)等,当server决定将实例销毁的时候调用其destroy方法。
web容器载入servlet,生命周期開始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现,依据请求的不同调用不同的do***()方法。结束服务,web容器调用servlet的destroy()方法。
5、Servlet的基本架构
public class ServletName extends HttpServlet {
public void doPost(HttpServletRequest request,HttpServletResponse response) throws
ServletException, IOException {
}
public void doGet(HttpServletRequest request,HttpServletResponse response) throws
ServletException, IOException {
}
}
6、SERVLET API中forward()与redirect()的差别?
答:前者仅是容器中控制权的转向,在client浏览器地址栏中不会显示出转向后的地址;后者则是全然的跳转,浏览器将会得到跳转的地址,并又一次发送请求链接。这样,从浏览器的地址栏中能够看到跳转后的链接地址。所以,前者更加高效,在前者能够满足须要时,尽量使用forward()方法,而且,这样也有助于隐藏实际的链接。在有些情况下,比方,须要跳转到一个其他server上的资源,则必须使用
sendRedirect()方法。
7、什么情况下调用doGet()和doPost()?
Jsp页面中的FORM标签里的method属性为get时调用doGet(),为post时调用doPost()。
8、Request对象的主要方法:
setAttribute(String name,Object):设置名字为name的request的參数值
getAttribute(String name):返回由name指定的属性值
getAttributeNames():返回request对象全部属性的名字集合,结果是一个枚举的实例
getCookies():返回client的全部Cookie对象,结果是一个Cookie数组
getCharacterEncoding():返回请求中的字符编码方式
getContentLength():返回请求的Body的长度
getHeader(String name):获得HTTP协议定义的文件头信息
getHeaders(String name):返回指定名字的request Header的全部值,结果是一个枚举的实例
getHeaderNames():返回所以request Header的名字,结果是一个枚举的实例
getInputStream():返回请求的输入流,用于获得请求中的数据
getMethod():获得client向server端传送数据的方法
getParameter(String name):获得client传送给server端的有name指定的參数值
getParameterNames():获得client传送给server端的全部參数的名字,结果是一个枚举的实例
getParametervalues(String name):获得有name指定的參数的全部值
getProtocol():获取client向server端传送数据所根据的协议名称
getQueryString():获得查询字符串
getRequestURI():获取发出请求字符串的client地址
getRemoteAddr():获取client的IP地址
getRemoteHost():获取client的名字
getSession([Boolean create]):返回和请求相关Session
getServerName():获取server的名字
getServletPath():获取client所请求的脚本文件的路径
getServerPort():获取server的port号
removeAttribute(String name):删除请求中的一个属性
9、forward和redirect的差别
forward是server请求资源,server直接訪问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道server发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
redirect就是服务端依据逻辑,发送一个状态码,告诉浏览器又一次去请求那个地址,一般来说浏览器会用刚才请求的全部參数又一次请求,所以session,request參数都能够获取。
10、request.getAttribute()和 request.getParameter()有何差别?
11. jsp有哪些内置对象?作用各自是什么?分别有什么方法?
答:JSP共同拥有下面9个内置的对象:
request 用户端请求,此请求会包括来自GET/POST请求的參数
response 网页传回用户端的回应
pageContext 网页的属性是在这里管理
session 与请求有关的会话期
application servlet 正在运行的内容
out 用来传送回应的输出
config servlet的构架部件
page JSP网页本身
exception 针对错误网页,未捕捉的例外
request表示HttpServletRequest对象。它包括了有关浏览器请求的信息,而且提供了几个用于获取cookie, header,和session数据的实用的方法。
response表示HttpServletResponse对象,并提供了几个用于设置送回浏览器的响应的方法(如cookies,头信息等)
out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。
pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,而且包装了通用的servlet相关功能的方法。
session表示一个请求的javax.servlet.http.HttpSession对象。Session能够存贮用户的状态信息
applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息
config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化參数。
page表示从该页面产生的一个servlet实例
12. jsp有哪些动作?作用各自是什么?
(这个问题似乎不重要,不明确为何有此题)
答:JSP共同拥有下面6种基本动作
jsp:include:在页面被请求的时候引入一个文件。
jsp:useBean:寻找或者实例化一个JavaBean。
jsp:setProperty:设置JavaBean的属性。
jsp:getProperty:输出某个JavaBean的属性。
jsp:forward:把请求转到一个新的页面。
jsp:plugin:依据浏览器类型为Java插件生成OBJECT或EMBED标记
13、JSP的经常使用指令
isErrorPage(能否使用Exception对象),isELIgnored(是否忽略表达式)
14. JSP中动态INCLUDE与静态INCLUDE的差别?
答:动态INCLUDE用jsp:include动作实现
<jsp:include page=included.jsp flush=true />它总是会检查所含文件里的变化,适合用于包括动态页面,而且能够带參数静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包括静态页面 <%@include file=included.htm %>
15、两种跳转方式各自是什么?有什么差别?
(以下的回答严重错误,应该是想问forward和sendRedirect的差别,毕竟出题的人不是专业搞文字艺术的人,可能表达能力并不见得非常强,用词不一定精准,加之其自身的技术面也可能存在一些问题,不一定真正将他的意思表达清楚了,严格意思上来讲,一些题目可能根本就无人能答,所以,答题时要掌握主动,仅仅要把自己知道的表达清楚就够了,而不要去推敲原始题目的详细含义是什么,不要一味想着是在答题)
答:有两种,分别为:
<jsp:include page=included.jsp flush=true>
<jsp:forward page= nextpage.jsp/>
前者页面不会转向include所指的页面,仅仅是显示该页的结果,主页面还是原来的页面。运行完后还会回来,相当于函数调用。而且能够带參数.后者全然转向新页面,不会再回来。相当于go to 语句。
16、页面间对象传递的方法
request,session,application,cookie等
17、JSP和Servlet有哪些同样点和不同点,他们之间的联系是什么?
JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"类servlet"。Servlet和JSP最基本的不同点在于,Servlet的应用逻辑是在Java文件里,而且全然从表示层中的HTML里分离开来。而JSP的情况是Java和HTML能够组合成一个扩展名为.jsp的文件。JSP側重于视图,Servlet主要用于控制逻辑。
18、MVC的各个部分都有那些技术来实现?怎样实现?
答:MVC是Model-View-Controller的简写。Model代表的是应用的业务逻辑(通过JavaBean,EJB组件实现),View是应用的表示面(由JSP页面产生),Controller是提供应用的处理过程控制(通常是一个Servlet),通过这样的设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件能够进行交互和重用。
19、我们在web应用开发过程中常常遇到输出某种编码的字符,如iso8859-1等,怎样输出一个某种编码的字符串?
Public String translate(String str) {
String tempStr ="";
try {
tempStr = newString(str.getBytes("ISO-8859-1"), "GBK");
tempStr =tempStr.trim();
}
catch (Exception e) {
System.err.println(e.getMessage());
}
return tempStr;
}
20.如今输入n个数字,以逗号,分开;然后可选择升或者降序排序;按提交键就在还有一页面显示按什么排序,结果为,提供reset
五.数据库部分
1、用两种方式依据部门号从高到低,工资从低到高列出每一个员工的信息。
employee:
eid,ename,salary,deptid;
select * from employeeorder by deptid desc,salary
2、列出各个部门中工资高于本部门的平均工资的员工数和部门号,并按部门号排序
创建表:
mysql> createtable employee921(id int primary key auto_increment,name varchar(5
0),salary bigint,deptid int);
插入实验数据:
mysql> insert into employee921values(null,‘zs‘,1000,1),(null,‘ls‘,1100,1),(null
,‘ww‘,1100,1),(null,‘zl‘,900,1) ,(null,‘zl‘,1000,2), (null,‘zl‘,900,2),(null,‘z
l‘,1000,2) , (null,‘zl‘,1100,2);
编写sql语句:
()select avg(salary) from employee921 group by deptid;
()mysql> selectemployee921.id,employee921.name,employee921.salary,employee921.dep
tid tid from employee921where salary > (select avg(salary) from employee921 where deptid = tid);
效率低的一个语句,仅供学习參考使用(在group by之后不能使用where,仅仅能使用having,在group by之前能够使用where,即表示对过滤后的结果分组):
mysql> selectemployee921.id,employee921.name,employee921.salary,employee921.dep
tid tid from employee921where salary > (select avg(salary) from employee921 group by deptid havingdeptid = tid);
()select count(*) ,tid
from (
selectemployee921.id,employee921.name,employee921.salary,employee921.deptid tid
from employee921
where salary>
(selectavg(salary) from employee921 where deptid = tid)
) as t
group by tid ;
第二种方式:关联查询
select a.ename,a.salary,a.deptid
from emp a,
(selectdeptd,avg(salary) avgsal from emp group by deptid ) b
where a.deptid=b.deptidand a.salary>b.avgsal;
3、存储过程与触发器必须讲,常常被面试到?
create procedure insert_Student (_name varchar(50),_age int ,out_id int)
begin
insert into studentvalue(null,_name,_age);
select max(stuId)into _id from student;
end;
call insert_Student(‘wfz‘,23,@id);
select @id;
mysql> create trigger update_Student BEFORE update on studentFOR EACH ROW
-> select * from student;
触发器不同意返回结果
create trigger update_StudentBEFORE update on student FOR EACH ROW
insert into student value(null,‘zxx‘,28);
mysql的触发器眼下不能对当前表进行操作
create trigger update_StudentBEFORE update on student FOR EACH ROW
delete from articles where id=8;
这个样例不是非常好,最好是用删除一个用户时,顺带删除该用户的全部帖子
这里要注意使用OLD.id
触发器用处还是非常多的,比方校内网、开心网、Facebook,你发一个日志,自己主动通知好友,事实上就是在添加日志时做一个后触发,再向通知表中写入条目。由于触发器效率高。而UCH没实用触发器,效率和数据处理能力都非常低。
存储过程的实验步骤:
mysql> delimiter |
mysql> create procedureinsertArticle_Procedure (pTitle varchar(50),pBid int,out
pId int)
-> begin
-> insert into article1value(null,pTitle,pBid);
-> select max(id) into pId fromarticle1;
-> end;
-> |
Query OK, 0 rows affected (0.05sec)
mysql> callinsertArticle_Procedure(‘传智播客‘,1,@pid);
-> |
Query OK, 0 rows affected (0.00sec)
mysql> delimiter ;
mysql> select @pid;
+------+
| @pid |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
mysql> select * fromarticle1;
+----+--------------+------+
| id | title | bid |
+----+--------------+------+
| 1 | test | 1 |
| 2 | chuanzhiboke | 1 |
| 3 | 传智播客 | 1 |
+----+--------------+------+
3 rows in set (0.00 sec)
触发器的实验步骤:
create table board1(id intprimary key auto_increment,name varchar(50),ar
ticleCount int);
create table article1(id intprimary key auto_increment,title varchar(50)
,bid int referencesboard1(id));
delimiter |
create triggerinsertArticle_Trigger after insert on article1 for each ro
w begin
-> update board1 setarticleCount=articleCount+1 where id= NEW.bid;
-> end;
-> |
delimiter ;
insert into board1 value(null,‘test‘,0);
insert into article1value(null,‘test‘,1);
还有,每插入一个帖子,都希望将版面表中的最后发帖时间,帖子总数字段进行同步更新,用触发器做效率就非常高。下次课设计这样一个案例,写触发器时,对于最后发帖时间可能须要用declare方式声明一个变量,或者是用NEW.posttime来生成。
4、数据库三范式是什么?
第一范式(1NF):字段具有原子性,不可再分。全部关系型数据库系统都满足第一范式)
数据库表中的字段都是单一属性的,不可再分。比如,姓名字段,当中的姓和名必须作为一个总体,无法区分哪部分是姓,哪部分是名,假设要区分出姓和名,必须设计成两个独立的字段。
第二范式(2NF):
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。
要求数据库表中的每一个实例或行必须能够被惟一地区分。通常须要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称为主keyword或主键。
第二范式(2NF)要求实体的属性全然依赖于主keyword。所谓全然依赖是指不能存在仅依赖主keyword一部分的属性,假设存在,那么这个属性和主keyword的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常须要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主keyword。
第三范式的要求例如以下:
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包括已在其他表中已包括的非主keyword信息。
所以第三范式具有例如以下特征:
1,每一列仅仅有一个值
2,每一行都能区分。
3,每个表都不包括其它表已经包括的非主keyword信息。
比如,帖子表中仅仅能出现发帖人的id,而不能出现发帖人的id,还同一时候出现发帖人姓名,否则,仅仅要出现同一发帖人id的全部记录,它们中的姓名部分都必须严格保持一致,这就是数据冗余。
5、说出一些数据库优化方面的经验?
用PreparedStatement一般来说比Statement性能高:一个sql发给server去运行,涉及步骤:语法检查、语义分析,编译,缓存
“inert into user values(1,1,1)”-à二进制
“inert into user values(2,2,2)”-à二进制
“inert into user values(?,?,?)”-à二进制
有外键约束会影响插入和删除性能,假设程序可以保证数据的完整性,那在设计数据库时就去掉外键。(比喻:就好比免检产品,就是为了提高效率,充分相信产品的制造商)
(对于hibernate来说,就应该有一个变化:empleyee->Deptment对象,如今设计时就成了employeeàdeptid)
看mysql帮助文档子查询章节的最后部分,比如,依据扫描的原理,以下的子查询语句要比第二条关联查询的效率高:
1. select e.name,e.salarywhere e.managerid=(select id from employee where name=‘zxx‘);
2. select e.name,e.salary,m.name,m.salary fromemployees e,employees m where
e.managerid = m.id andm.name=‘zxx‘;
表中同意适当冗余,譬如,主题帖的回复数量和最后回复时间等
将姓名和password单独从用户表中独立出来。这能够是很好的一对一的案例哟!
sql语句所有大写,特别是列名和表名都大写。特别是sql命令的缓存功能,更加须要统一大写和小写,sql语句à发给oracleserverà语法检查和编译成为内部指令à缓存和运行指令。依据缓存的特点,不要拼凑条件,而是用?和PreparedStatment
还有索引对查询性能的改进也是值得关注的。
备注:以下是关于性能的讨论举例
4航班 3个城市
m*n
select * from flight,city where flight.startcityid=city.cityidand city.name=‘beijing‘;
m + n
select * from flight where startcityid = (select cityid fromcity where cityname=‘beijing‘);
select flight.id,‘beijing‘,flight.flightTime from flight wherestartcityid = (select cityid from city where cityname=‘beijing‘)
6、union和union all有什么不同?
如果我们有一个表Student,包含下面字段与数据:
drop table student;
create table student
(
id int primary key,
name nvarchar2(50) not null,
score number not null
);
insert into student values(1,‘Aaron‘,78);
insert into student values(2,‘Bill‘,76);
insert into student values(3,‘Cindy‘,89);
insert into student values(4,‘Damon‘,90);
insert into student values(5,‘Ella‘,73);
insert into student values(6,‘Frado‘,61);
insert into student values(7,‘Gill‘,99);
insert into student values(8,‘Hellen‘,56);
insert into student values(9,‘Ivan‘,93);
insert into student values(10,‘Jay‘,90);
commit;
Union和Union All的差别。
select *
from student
where id < 4
union
select *
from student
where id > 2 and id < 6
结果将是
1 Aaron 78
2 Bill 76
3 Cindy 89
4 Damon 90
5 Ella 73
假设换成Union All连接两个结果集,则返回结果是:
1 Aaron 78
2 Bill 76
3 Cindy 89
3 Cindy 89
4 Damon 90
5 Ella 73
能够看到,Union和Union All的差别之中的一个在于对反复结果的处理。
UNION在进行表链接后会筛选掉反复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除反复的记录再返回结果。实际大部分应用中是不会产生反复的记录,最常见的是过程表与历史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
这个SQL在执行时先取出两个表的结果,再用排序空间进行排序删除反复的记录,最后返回结果集,假设表数据量大的话可能会导致用磁盘进行排序。
而UNION ALL仅仅是简单的将两个结果合并后就返回。这样,假设返回的两个结果集中有反复的数据,那么返回的结果集就会包括反复的数据了。
从效率上说,UNION ALL要比UNION快非常多,所以,假设能够确认合并的两个结果集中不包括反复的数据的话,那么就使用UNION ALL,
7.分页语句
取出sql表中第31到40的记录(以自己主动增长ID为主键)
sql server方案1:
selecttop 10 * from t where id not in (select top 30 id from t order by id ) orde byid
sql server方案2:
selecttop 10 * from t where id in (select top 40 id from t order by id) order by iddesc
mysql方案:select * from t order by idlimit 30,10
oracle方案:select * from (select rownum r,* from t where r<=40) wherer>30
--------------------待整理进去的内容-------------------------------------
pageSize=20;
pageNo = 5;
1.分页技术1(直接利用sql语句进行分页,效率最高和最推荐的)
mysql:sql = "select * from articles limit " +(pageNo-1)*pageSize + "," + pageSize;
oracle: sql = "select * from " +
"(selectrownum r,* from " +
"(select* from articles order by postime desc)" +
"whererownum<= " + pageNo*pageSize +") tmp " +
"wherer>" + (pageNo-1)*pageSize;
凝视:第7行保证rownum的顺序是确定的,由于oracle的索引会造成rownum返回不同的值
简洋提示:没有order by时,rownum按顺序输出,一旦有了order by,rownum不按顺序输出了,这说明rownum是排序前的编号。假设对order by从句中的字段建立了索引,那么,rownum也是按顺序输出的,由于这时候生成原始的查询结果集时会參照索引表的顺序来构建。
sqlserver:sql = "select top 10 * from id not id(select top" + (pageNo-1)*pageSize + "id from articles)"
DataSource ds = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?" --->binary directive
PreparedStatement pstmt = cn.prepareSatement(sql);
ResultSet rs = pstmt.executeQuery()
while(rs.next())
{
out.println(rs.getString(1));
}
2.不可滚动的游标
pageSize=20;
pageNo = 5;
cn = null
stmt = null;
rs = null;
try
{
sqlserver:sql = "select * from articles";
DataSource ds = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?" --->binary directive
PreparedStatement pstmt = cn.prepareSatement(sql);
ResultSet rs = pstmt.executeQuery()
for(int j=0;j<(pageNo-1)*pageSize;j++)
{
rs.next();
}
int i=0;
while(rs.next() && i<10)
{
i++;
out.println(rs.getString(1));
}
}
cacth(){}
finnaly
{
if(rs!=null)try{rs.close();}catch(Exceptione){}
if(stm.........
if(cn............
}
3.可滚动的游标
pageSize=20;
pageNo = 5;
cn = null
stmt = null;
rs = null;
try
{
sqlserver:sql = "select * from articles";
DataSource ds = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?" --->binary directive
PreparedStatement pstmt = cn.prepareSatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,...);
//依据上面这行代码的异常SQLFeatureNotSupportedException,就可推断驱动是否支持可滚动游标
ResultSet rs = pstmt.executeQuery()
rs.absolute((pageNo-1)*pageSize)
int i=0;
while(rs.next() && i<10)
{
i++;
out.println(rs.getString(1));
}
}
cacth(){}
finnaly
{
if(rs!=null)try{rs.close();}catch(Exceptione){}
if(stm.........
if(cn............
}
8.用一条SQL语句查询出每门课都大于80分的学生姓名
name kecheng fenshu
张三 语文 81
张三 数学 75
李四 语文 76
李四 数学 90
王五 语文 81
王五 数学 100
王五 英语 90
准备数据的sql代码:
create table score(id int primary key auto_increment,namevarchar(20),subject varchar(20),score int);
insert into score values
(null,‘张三‘,‘语文‘,81),
(null,‘张三‘,‘数学‘,75),
(null,‘李四‘,‘语文‘,76),
(null,‘李四‘,‘数学‘,90),
(null,‘王五‘,‘语文‘,81),
(null,‘王五‘,‘数学‘,100),
(null,‘王五 ‘,‘英语‘,90);
提示:当百思不得其解时,请理想思维,把小变成大做,把大变成小做,
答案:
A: select distinct name from score where name not in (selectdistinct name from score where score<=80)
B:select distince name t1 from score where 80< all (selectscore from score where name=t1);
9.全部部门之间的比赛组合
一个叫department的表,里面仅仅有一个字段name,一共同拥有4条纪录,各自是a,b,c,d,相应四个球对,如今四个球对进行比赛,用一条sql语句显示全部可能的比赛组合.
答:select a.name,b.name
from team a, team b
where a.name < b.name
10.每一个月份的发生额都比101科目多的科目
请用SQL语句实现:从TestDB数据表中查询出全部月份的发生额都比101科目对应月份的发生额高的科目。请注意:TestDB中有非常多科目,都有1-12月份的发生额。
AccID:科目代码,Occmonth:发生额月份,DebitOccur:发生额。
数据库名:JcyAudit,数据集:Select * from TestDB
准备数据的sql代码:
drop table if exists TestDB;
create table TestDB(id int primary key auto_increment,AccIDvarchar(20), Occmonth date, DebitOccur bigint);
insert into TestDB values
(null,‘101‘,‘1988-1-1‘,100),
(null,‘101‘,‘1988-2-1‘,110),
(null,‘101‘,‘1988-3-1‘,120),
(null,‘101‘,‘1988-4-1‘,100),
(null,‘101‘,‘1988-5-1‘,100),
(null,‘101‘,‘1988-6-1‘,100),
(null,‘101‘,‘1988-7-1‘,100),
(null,‘101‘,‘1988-8-1‘,100);
--复制上面的数据,有益把第一个月份的发生额数字改小一点
insert into TestDB values
(null,‘102‘,‘1988-1-1‘,90),
(null,‘102‘,‘1988-2-1‘,110),
(null,‘102‘,‘1988-3-1‘,120),
(null,‘102‘,‘1988-4-1‘,100),
(null,‘102‘,‘1988-5-1‘,100),
(null,‘102‘,‘1988-6-1‘,100),
(null,‘102‘,‘1988-7-1‘,100),
(null,‘102‘,‘1988-8-1‘,100);
--复制最上面的数据,有益把全部发生额数字改大一点
insert into TestDB values
(null,‘103‘,‘1988-1-1‘,150),
(null,‘103‘,‘1988-2-1‘,160),
(null,‘103‘,‘1988-3-1‘,180),
(null,‘103‘,‘1988-4-1‘,120),
(null,‘103‘,‘1988-5-1‘,120),
(null,‘103‘,‘1988-6-1‘,120),
(null,‘103‘,‘1988-7-1‘,120),
(null,‘103‘,‘1988-8-1‘,120);
--复制最上面的数据,有益把全部发生额数字改大一点
insert into TestDB values
(null,‘104‘,‘1988-1-1‘,130),
(null,‘104‘,‘1988-2-1‘,130),
(null,‘104‘,‘1988-3-1‘,140),
(null,‘104‘,‘1988-4-1‘,150),
(null,‘104‘,‘1988-5-1‘,160),
(null,‘104‘,‘1988-6-1‘,170),
(null,‘104‘,‘1988-7-1‘,180),
(null,‘104‘,‘1988-8-1‘,140);
--复制最上面的数据,有益把第二个月份的发生额数字改小一点
insert into TestDB values
(null,‘105‘,‘1988-1-1‘,100),
(null,‘105‘,‘1988-2-1‘,80),
(null,‘105‘,‘1988-3-1‘,120),
(null,‘105‘,‘1988-4-1‘,100),
(null,‘105‘,‘1988-5-1‘,100),
(null,‘105‘,‘1988-6-1‘,100),
(null,‘105‘,‘1988-7-1‘,100),
(null,‘105‘,‘1988-8-1‘,100);
答案:
select distinct AccID from TestDB
where AccID not in
(selectTestDB.AccIDfrom TestDB,
(select * from TestDB where AccID=‘101‘) asdb101
whereTestDB.Occmonth=db101.Occmonth and TestDB.DebitOccur<=db101.DebitOccur
);
11.统计每年每月的信息
year monthamount
1991 1 1.1
1991 2 1.2
1991 3 1.3
1991 4 1.4
1992 1 2.1
1992 2 2.2
1992 3 2.3
1992 4 2.4
查成这样一个结果
year m1 m2 m3 m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4
提示:这个与工资条非常类似,与学生的科目成绩也非常相似。
准备sql语句:
drop table if existssales;
create table sales(idint auto_increment primary key,year varchar(10), month varchar(10), amountfloat(2,1));
insert into salesvalues
(null,‘1991‘,‘1‘,1.1),
(null,‘1991‘,‘2‘,1.2),
(null,‘1991‘,‘3‘,1.3),
(null,‘1991‘,‘4‘,1.4),
(null,‘1992‘,‘1‘,2.1),
(null,‘1992‘,‘2‘,2.2),
(null,‘1992‘,‘3‘,2.3),
(null,‘1992‘,‘4‘,2.4);
答案一、
select sales.year ,
(select t.amount fromsales t where t.month=‘1‘ and t.year= sales.year) ‘1‘,
(select t.amount fromsales t where t.month=‘1‘ and t.year= sales.year) ‘2‘,
(select t.amount fromsales t where t.month=‘1‘ and t.year= sales.year) ‘3‘,
(select t.amount fromsales t where t.month=‘1‘ and t.year= sales.year) as ‘4‘
from sales group by year;
12.显示文章标题,发帖人、最后回复时间
表:id,title,postuser,postdate,parentid
准备sql语句:
drop table if exists articles;
create table articles(id int auto_increment primary key,titlevarchar(50), postuser varchar(10), postdate datetime,parentid int referencesarticles(id));
insert into articles values
(null,‘第一条‘,‘张三‘,‘1998-10-10 12:32:32‘,null),
(null,‘第二条‘,‘张三‘,‘1998-10-10 12:34:32‘,null),
(null,‘第一条回复1‘,‘李四‘,‘1998-10-10 12:35:32‘,1),
(null,‘第二条回复1‘,‘李四‘,‘1998-10-10 12:36:32‘,2),
(null,‘第一条回复2‘,‘王五‘,‘1998-10-10 12:37:32‘,1),
(null,‘第一条回复3‘,‘李四‘,‘1998-10-10 12:38:32‘,1),
(null,‘第二条回复2‘,‘李四‘,‘1998-10-10 12:39:32‘,2),
(null,‘第一条回复4‘,‘王五‘,‘1998-10-10 12:39:40‘,1);
答案:
select a.title,a.postuser,
(selectmax(postdate) from articles where parentid=a.id) reply
from articles a where a.parentid is null;
凝视:子查询能够用在选择列中,也可用于where的比較条件中,还能够用于from从句中。
13.删除除了id号不同,其它都同样的学生冗余信息
2.学生表例如以下:
id号 学号 姓名课程编号课程名称分数
1 2005001 张三 0001 数学 69
2 2005002 李四 0001 数学 89
3 2005001 张三 0001 数学 69
A: delete from tablename where id号 not in(select min(id号) from tablename group by学号,姓名,课程编号,课程名称,分数)
实验:
create table student2(id int auto_increment primary key,codevarchar(20),name varchar(20));
insert into student2 values(null,‘2005001‘,‘张三‘),(null,‘2005002‘,‘李四‘),(null,‘2005001‘,‘张三‘);
//例如以下语句,mysql报告错误,可能删除依赖后面统计语句,而删除又导致统计语句结果不一致。
delete from student2 where id not in(select min(id) fromstudent2 group by name);
//可是,例如以下语句没有问题:
select * from student2where id not in(select min(id) from student2 group by name);
//于是,我想先把分组的结果做成虚表,然后从虚表中选出结果,最后再将结果作为删除的条件数据。
delete from student2 where id not in(select mid from (selectmin(id) mid
from student2 group by name) as t);
或者:
delete from student2 where id not in(select min(id) from (select* from s
tudent2) as t group by t.name);
14.航空网的几个航班查询题:
表结构例如以下:
flight{flightID,StartCityID ,endCityID,StartTime}
city{cityID, CityName)
实验环境:
create table city(cityID int auto_increment primary key,cityNamevarchar(20));
create table flight (flightID int auto_increment primary key,
StartCityID intreferences city(cityID),
endCityID int references city(cityID),
StartTimetimestamp);
//航班本来应该没有日期部分才好,可是以下的题目其中涉及到了日期
insert into city values(null,‘北京‘),(null,‘上海‘),(null,‘