﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-我思故我强-文章分类-面试笔试相关的</title><link>http://www.blogjava.net/balajinima/category/42118.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Oct 2009 11:12:45 GMT</lastBuildDate><pubDate>Tue, 27 Oct 2009 11:12:45 GMT</pubDate><ttl>60</ttl><item><title>Java认证之精屁总结</title><link>http://www.blogjava.net/balajinima/articles/298543.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:50:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298543.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298543.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298543.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298543.html</trackback:ping><description><![CDATA[<p>3.switch里面只能是short,int,char,byte的.<br />
4.if (a="a") 编译错, if(a=false)编译ok,原因是a=false的a代表了个boolean值<br />
6.这种写法Outer.Inner i = new Outer().new Inner(); OK!<br />
7.文件里, 8 默认是int, 8.0默认是double<br />
8.八进制是 0开头,不是O(英文o)<br />
9.byte -128~127 ,-128是二进制的多少<br />
11. -1&gt;&gt;32还是-1, -1&gt;&gt;&gt;32为什么还是-1<br />
12. char c='c'; String s ="s"; s+=c;结果是 sc!!!<br />
13. boolean b1=true; boolean b2=true; System.out.println(b1|b2); 结果是true.编译没错!<br />
java的默认import包有哪些<br />
AWT&nbsp;<wbr><br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1. 所有组件flowLayout会被压缩为它们的最小尺寸<br />
2. BorderLayout的North,South,West,East,Center就是这个样子,四个单词大小写区分,必须这么写,否则错<br />
2.1如果只是add,而不写东南西北中,默认是中<br />
2.2如果不加component到中,那中就空着<br />
2.3如果某个方位有个component,如果你还往上面加component,后来的会覆盖原来的<br />
3. applet,panel默认布局是flowlayout<br />
4. frame,dialog默认布局是borderlayout<br />
5. 各种awe类的继承关系,frame,window,component,...<br />
6. window,frame,dialog不能被嵌入到容器里.注意:window!<br />
7. action event作用于button和textfeild的回车时刻<br />
8. item event作用于list,choice,checkbox的选择改变时刻<br />
9. 如果容器不可见,新layout管理器后前的component将跟随这个新的layout变化,如果容器可见,这些component将不受后来的layout影响<br />
10.gridLayout里的component尺寸一样<br />
11.gridBagLayout里,component可以占用多个grid<br />
12.System.exit();在Applet里面不允许调用.<br />
AWT事件<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1.事件类有<br />
(symantic)语义事件:ActionEvent,AdjustEvent,ItemEvent,TextEvent<br />
低级事件:ComponentEvent,ContainerEvent,FocusEvent,InputEvent,KeyEvent,MouseEvent,PaintEvent,WindowEvent<br />
2.监听器:<br />
ActionListener,AdjustListener,CompentListener,ContainerListener,FocusListener,ItemListener,<br />
KeyListener,MouseListener,MouseMotionListener,TextListener,WindwosListener, 共11个Listener,<br />
七个adpter,少的4个是ActionLisenter,AdjustListener,ItemListener,TextListener,它们只有一个方法.<br />
3,鼠标MouseListener有5个方法:clicked,pressed,released,entered,exited<br />
4.鼠标MouseMotionListener有2个方法:mouseDragged,mouseMoved<br />
类和对象(Class and Object)<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
0.最外层的类可以声明成final: "$file a":&lt; final class a{}&gt; ok!,但是不能是private和static的.<br />
1.overload是同类里同样的方法名,override是父子的继承<br />
2.override的返回结果必须一样,否则编译错哦<br />
The return type of an overriding method is identical to the return type of the method it overrides.<br />
2.1 override的modifier可以扩大,但是不能缩小.比如父类private void test(){} 子类:public void test(){} ,没问题;如果反了,就死翘翘了!<br />
3.super.super(),靠,错的,没这么写的<br />
4.static和非static之间永远无法override!<br />
5. 看程序<br />
public class A{<br />
void test1() throws BaseEx{hi();}<br />
void hi(){System.out.println("say hi,a");}<br />
}<br />
class AA extends A{<br />
void hi(){System.out.println("say hi,aa");}<br />
}<br />
class test{<br />
static void main(String b[]) throws Exception{<br />
A a = new AA();<br />
a.test1();<br />
}<br />
}<br />
结果是,"say hi,aa",这说明什么说明,方法永远跟着类的原来面目走;而,变量恰恰相反!<br />
6.一个非抽象方法死活也别想override成一个抽象方法<br />
7.override的子类的方法抛出的的异常只能是父类方法抛出异常的子异常类,或者无!<br />
8.构造器不能是native,final,static,synchronized的,可以是public,private,什么都没有的,呵呵<br />
9.构造器函数里还可以写return呢,但后面什么都不许有,甚至null(这不是废话吗,哈哈)<br />
10.构造器不能返回值.这大家都知道,但如果有个"构造器"反值了,别紧张,它就不是构造器喽,只是个普通函数<br />
11.super();this();这两个函数只能在构造函数里调用.<br />
12,成员变量声明时候赋值,比构造函数还早.int i=1; ealier than Test(){}<br />
13.方法的参数变量可以是final.<br />
14. hashCode返回一个int<br />
15. void wait() throws InterruptException wait扔InterruptException异常<br />
16. java.lang.Void 是void的包装类<br />
17. Byte,Interger,Double...所有的跟数有关的包装类都是继承于Number</p>
<p>接口Interface)<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1.接口的所有方法默认都是public,abstract和non-static的<br />
2.接口的所有变量默认都是public,static,final的.所以,接口的变量不能改值,在它的实现类里.<br />
3.接口的实现类实现的方法必须和接口的方法抛出同样的异常,不许是子类,这和override不一样!同样,如果接口方法没有抛,实现方法也不能抛.<br />
4.实现类实现的方法必须显式的声明成public,什么都不写都不行,啊!!!<br />
5.接口不能声明成final,要不它怎么被实现呢(这好像又是废话啊<br />
6.一个类实现两个接口,如果两个接口有相同的方法,实现类就实现这个方法,没问题的.</p>
<p>内嵌类Inner Class)<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1.内嵌类可以访问outer类的任何变量,包括私有的.<br />
2.静态inner类,只能访问outer类的任何static变量<br />
2.1内嵌类可以是final,abstract的<br />
3.我靠,方法内的内嵌类不能为static: void test(){ static class A{}} XXXXX!!!!<br />
4.我靠,方法内的内嵌类也不能带任何modifier,void test(){ public class A{}} XXXXX!!!!<br />
5.我靠,方法内的内嵌类只能访问方法内的final变量,但是,可以访问outer类的任何变量.<br />
6.匿名类不能有构造器,但声明时候带参数,相当于构造器的参数传递.<br />
class ABC{}<br />
class ABCD{private ABCD(int i){}}<br />
ABC test3(){return new ABC(){};}<br />
ABCD test4(){return new ABCD(3){};}<br />
interface iii{}<br />
iii test5(){return new iii(){};}<br />
//class BCD extends ABCD{} compile error,因为,<br />
看上面就知道,new iii(){};实际上匿名类实现了iii接口;new ABC(){};实际上是匿名类继承了ABC.<br />
8.<br />
class A {private A(){System.out.println("a!");}}<br />
class B extends A{}<br />
我靠,没错!B实例的时候会主动调用父类A的构造,即使是private的,看来也没问题!!!<br />
9.内部类可以有synchronized方法,那么锁是这个内部类,跟外部类没一点关系,内外分别的,在锁的问题上.<br />
10.外部类不能通过this被访问,this这时候应该指的是内部类,享用外部类的成员就直接用,不用加任何限定词<br />
11.如何用this呢请看:<br />
class Outer{ int i;<br />
class Inner{<br />
class InnerInner{<br />
void Test(){<br />
Outer.this.i=1;<br />
}<br />
}<br />
}<br />
}<br />
看见了吧,类名.this.变量名,可以引用到i,第一次看到吧,嘿嘿,孤陋寡闻.<br />
12.注意这两种写法都可以<br />
Class Outer.Inner i = new Outer().new Inner();<br />
或者, Class o= new Outer(); Class Outer.Inner i=o.new Inner();</p>
<p>线程Thread)<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
去看Thread的API!!!!<br />
1.线程启动必须通过start函数.<br />
2.run函数不许也只能是public的.<br />
3.线程有优先级从1到10,通过Thread.setPriority(int);来改变,不能超过10,否则会出现运行异常<br />
4.线程优先级默认是5,即NORM_PRIORITY.NORM_PRIORITY是Thread的静态变量吗<br />
5.Thread.yeild();是静态方法,所以,使用格式是Thread.yield();她强迫当前的进程放弃CUP.<br />
6.sleep(1000),是说线程睡觉1秒,然后,进入Ready状态,注意,不是运行状态,它还要等OS来调度来获得CUP.</p>
<p>java.lang.*;<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1.数组的科隆: int ia[][]={{1,2},null}; int ib[][]=(int[][])ia.clone();<br />
2.什么是NaN然后看ceil(NaN),floor(NaN),...<br />
3.Math.floor(-1.1f);//-2.0<br />
Math.ceil(-1.1f);//-1.0<br />
Math.round(-1.6d)//-2<br />
4.0=&lt;1<br />
5.Math,Interger,Boolean...等类型包装类都是final的,不可继承<br />
6.int round(float); long round(double);唉,round永远返回不了小数点<br />
7.static double ceil(double)<br />
8.static double floor(double)注意，ceil,floor的只有这个double版本,什么都转成double!<br />
9.static double sin(double 弧度); 还有cos,tan<br />
10. new String; 可以是byte[];char[];String;StringBuffer<br />
11. String的一些函数: int length(); char charAt(int); String toUpperCase(); String toLowerCase();<br />
12. String("Abc").equals(String("abc"))不相等的,不然就不会有boolean equalsIgnoreCase(String)函数<br />
13."012345678"是一个串的顺序号码,indexOf('1'),indexOf("1")都返回1,subString(1,5)是2345,嘿嘿:是"[)"的感觉<br />
14, trim()连tab都退毛,"\t\n java ",trim()一下就只剩下"java"了<br />
15. 关于对象的科隆,去喳喳API<br />
16. "abcd".trim(),"abcd" + new String("ef")都是合理的写法<br />
17. StringBuffer的3个构造器: ()初始化容量为16,(int 初始化容量),(String),初始化容量为串长加上16<br />
18. StringBuffer的一些函数: String toString(); append();reverse();insert();delete(int start,int end);deleteCharAt(int);setLength(int newLength);<br />
19. String s=""; StringBuffer sb=new StringBuffer(); if (s==sb){}编译错!因为,s,sb类型不一样,不能比较<br />
集合:<br />
1.各接口和类的关系,只有最后一个是类<br />
Collection:List:vector,ArrayList,LinkedList<br />
Map:SortedMap:TreeMap<br />
Collection:Set:SortedSet:TreeSet<br />
Map:HashTable<br />
Collection:Set:HashSet</p>
<p>基础Base)<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1.java application的main可以不是public的.但必须是static的<br />
2.一个文件只能有一个public类,而且还得跟文件名一样,包括大小写<br />
3.变量只能是字母,$,_开头,接下来的第二个可以是,数字<br />
4.ch\u0061r='a'; char \u0063='b'; char c='\u0063';都是合法的<br />
5.1e-5d,合法.e-5d不合法,必须有前面的系数<br />
6.int[] i[]={null{1,2}}正确! int i[]={1,2,3,} 正确!","和没有的效果一样<br />
7.局部array,跟变量一样,使用前要初始化<br />
8.main方法可以为final</p>
<p>操作符和分配符(Operator and Assignment)<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1.System.out.printl(1+2+"3");//33 System.out.printl("1"+2+3);//123<br />
2.int i=0; i=i++;i=i++;i=i++; 结果,i=0!<br />
3.int i[]; index=0; i[index]=index=5; 结果是,i[0]=5;!!!<br />
4.byte b=10;可以,因为,10可以被自动从int转成byte<br />
5.接下来,byte b=b+10;不可以!!因为,10+b后的int无法被自动从int转成byte,问我,我也不知道为什么!靠!<br />
6.byte b1 = 4; byte b2 = 6; b1 = b1 + b2;错!编译错!b1 + b2后,必须强制转成byte,b1x1+b2);<br />
7.XOR 一样的为0，不一样为1 1,1=0;0,0=0;1,0/0,1=1<br />
8. x == Float.NaN编译错，应该是Float.IsNaN<br />
9. x == Double.POSITIVE_INFINITY编译可以<br />
10.-1是1111.... 1111,&lt;&lt;永远右补零，&gt;&gt;正补零，负补一，&gt;&gt;&gt;恒补零<br />
10.1 -1&gt;&gt;多少位都是-1 ; 1&lt;&lt;31变成了最小负数,1000....0000<br />
11.最大正数是01111....1111<br />
12.最小负数是1000....0000(-2147483648)<br />
13. a instanceof b,b必须是类/接口，不能是实例<br />
--------补充------------------------------<br />
1. byte,short,char 都存在 var = -var;编译错误,因为,这时候的-var已经自动转成个int类型了<br />
2. int/0会扔出ArithmeticException<br />
double,float/0得INF或者-INF<br />
0/0得NaN<br />
3. int a-b-c;是不符合命名规则的变量名编译会出错.<br />
4. char a='\u0001';对! char b=\u0001;编译错!<br />
5. boolean b1,b2,b3,b4,b5;<br />
b1 = b2==b3;<br />
b1 = b2&lt;=b3 &amp;&amp; b4==b5;<br />
b1 = b2==b3==true<br />
都是对的!靠!变态!<br />
b1 = b2==b3==b4 XXXXXXX编译错!<br />
6. 1&gt;&gt;1 是0<br />
7. %= &lt;&lt;= =&gt;&gt; =&gt;&gt;&gt;都是合法符号<br />
8. --1-10*4 这种写法没错,就是 (--1)-10*4<br />
9. k=1;++k + k++ + +k ;结果是7,相当于 (++2)+(2++)+(+3)<br />
10.标号不能标示声明.<br />
hi:<br />
if {<br />
break hi;<br />
//break hi1;不行,不能向后调转<br />
}<br />
//hi1:不行,不能放在声明前<br />
int i;<br />
hi1:<br />
i=1;<br />
11.public static void main(String s[]) throws Exception{}可以噢,main可以扔出异常<br />
12. hi:<br />
if(b==true){break hi;}<br />
break 标号，可以用在if里面.别的任何都不行,包括break,continue 标号.<br />
13.int x = i*-j; 我靠,没问题的!!!编译没错! int x = i*j++ + +i++; 这个也没问题,</p>
<p>变量修饰符(Modifier)<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1.最外面一层的类不能声明成protect和pravite的<br />
2.同一个类的两个实例之间可以访问彼此的私有方法和私有变量,酷<br />
3.protect和无修饰符的具体区别关于外包可以访问被子类访问的是哪个<br />
4.成员变量被修饰成final后,必须声明时候就赋初值或者在构造器里面赋初值,别指望她可以得到default值.<br />
5.抽象方法不能是static的!!!<br />
6.静态方法将随着类的变化而变化,看例子:<br />
class Parent{<br />
static void test(){System.out.println("hi,parent")};<br />
}<br />
class Child extends Parent{<br />
static void test(){System.out.println("hi,child")};<br />
}<br />
Parent p = new Child();<br />
p.test(); //打出来的是hi,parent!<br />
7.静态方法可以通过类的实例调用.<br />
new Child().test(); 和 Child.test(); 都OK!<br />
8.transient只能用在类的成员变量上,不能用在方法里.<br />
9.transient变量不能是final和static的<br />
10.native方法可以是private,abstractd的</p>
<p>流程控制<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1。不可到达的语句声明为错：while(false){} ;for(;false{};if(false){}都无法编译<br />
2。for(第一部分;的第一部分可以用来声明或者赋值，但不能两者都<br />
3。byte b; switch&nbsp;<wbr> { case 200: // 200 not in range of byte，因为200超过b的范围，将编译错误<br />
4。带标签的continue回达到标签的位置，从新进入紧接在标签后面的循环<br />
5。带标签的break会中断当前循环，并转移到标签标示的的循环的末尾</p>
<p>转型和上溯(Converting and Casting)<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
Binary operators convert the smaller(less precise) operand to the type of the larger(more precise) operand.<br />
All operators will convert things smaller than ints to ints or larger. This includes char 's!<br />
1.byte,char,short默认转成int<br />
2.byte-&gt;short-&gt;int-&gt;long-&gt;float-&gt;double<br />
char^<br />
这是默认可以转型的方向,反了必须要显式cast! 特别注意:long-&gt;float是默认的,别看long64,float32,嘿嘿<br />
还有就是看得出来,char和 byte,short之间无法互相默认转换<br />
3.float f=1/3; OK!float f=1.0/3.0;编译出错,因为1.0/3.0结果是double的,噢噢~,错喽!!<br />
4.int i=1; byte b=i;错!需要显式cast.<br />
final i=1; byte b=i;就ok! 我也不知道为什么,final就可以.而且,据我实验只有int和byte的关系这样,其他不行.<br />
5.int i[]; Object[] obj=i;错! Object obj=i;对! 数组只能转成Object,而不能是Object[]<br />
6.int i[]; Object[] obj;i=(int[])obj; 对! 对象可以通过显式来转成一个数组.</p>
<p>I/O<br />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
1.File类的一些重要方法:isFile();isDirectory();String[] list();exists();getAbsolutePath();getParent();<br />
2.通过delete();mkdir();rename(File newname);可以操纵文件,但是却改变不了文件的内容<br />
2.1 File类无法改变当前目录,除非重新创建一个File对象.<br />
3.InputStreamReader(InputStream in,String encodingName);<br />
OutputStreamReader(OutputStream in,String encodingName);<br />
Encoding: 8859_1是Latin-1,包含ASCII<br />
4.关闭close一个流,就自动调用了flush.<br />
5.System.in,System.out,System.err,由JVM自动创建<br />
6.RandomAccessFile(File file,String mode);mode有,r,rw</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:50 <a href="http://www.blogjava.net/balajinima/articles/298543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA概念总结</title><link>http://www.blogjava.net/balajinima/articles/298542.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:49:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298542.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298542.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298542.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298542.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298542.html</trackback:ping><description><![CDATA[<p>◆<strong>传值与传引</strong></p>
<p>严格来说，Java中所有方法参数都是传值。因为即使是传递的参数是对象的引数时，引数本身也是传值的。所有基本类型都是传值的。</p>
<p><strong>传值：</strong>被传入的参数被视为内部的局域变量，其变化不影响外部变量的原始值。</p>
<p><strong>传引</strong><strong>：</strong>对于引数本身来讲也是传值的，但是在方法内部若对引数所指向的对象属性有改变，则会直接实时地影响所指向的对象属性。</p>
<p>理解传引这一概念的最佳方式就是画出指向图。eg. A&#224;(Object)O 对于A本身而言它是传值的，也就是说当A作为参数传递的时候，假若在方法内部把其它的引数赋给了A，但是当方法返回时，A仍旧是指向原来的对象，而不会改变。其次，对于传引来说，假若在方法内部对A所指向的对象属性有改变，那么对象属性的改变会是直接实时的。</p>
<p>再次强调，Java中所有的参数传递都是传值的。</p>
<p>传值这种题型的考试很多，基本类型传值问题考的较多的是对某一变量，故意用某一方法试图改变它，然后方法返回时再打印它。按传值的说法，实际上该变量并没有改变。</p>
<p>◆<strong>构造函数</strong></p>
<p>a．构造器没有任何返回类型，哪怕是void也不行。<strong>假如指定了返回值，那么</strong><strong>Java</strong><strong>会视为一个普通的方法。</strong></p>
<p>b．如果没有显示地调用父类的构造器，Java总是自动地调用父类的默认构造器。（也就是第一行会默认为super( )）</p>
<p>c．只要类中显式地定义一个或多个构造器，那么Java不会再为你定义一个默认的构造器</p>
<p>d．构造函数可以被重载，并且在其体内可以用this()和super()来调用其它的构造器。但是this()和super()只能放在构造函数体的第一行进行调用。</p>
<p>e．构造器的修饰符只可以是接入控制符public、private、protected、(default)。其它修饰符一律不可。</p>
<p>f．构造方法不可被继承。</p>
<p>◆<strong>重载与覆盖</strong></p>
<p>&nbsp;<wbr> 重载的英文为Overload，而覆盖的英文为Override。重载是出现在同一类中多个同名函数，而覆盖是出现在类继承体系中同名函数。（注意：覆盖有时被称为重写）</p>
<p>&nbsp;<wbr> <strong>重载</strong>是依据同名方法<strong>参数的个数</strong>、<strong>参数的类型</strong>和<strong>参数的顺序</strong>来确定的。方法的修饰符、返回值、抛出的异常均不能作为区分重载方法的依据。（继承体系中也有重载现象）</p>
<p><strong>&nbsp;<wbr></strong> <strong>覆盖</strong>是在继承体系中子类覆盖超类中定义的方法。子类中覆盖方法的<strong><u>返回类型</u></strong>和<strong><u>参数类型</u></strong>必须精确匹配。<strong>接入控制符</strong>只能更加公有化；<strong>抛出的异常</strong>是超类抛出的子集或不抛。</p>
<p><strong>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></strong> <strong>（static</strong>方法不能覆盖，<strong>private</strong>方法也不能覆盖。Java视它们为被隐藏<strong>）</strong></p>
<p><strong>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></strong> &#183; 参数类型一致，返回类型不同，编译错误，提示&#8220;试图用不兼容的返回类型覆盖&#8221;。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &#183; 只要参数类型不一致，返回类型同与不同，编译都能通过，此不为覆盖而是重载。</p>
<p>◆<strong>多态</strong></p>
<p>&nbsp;<wbr> 多态是出现于类的继承层次中，通过<strong>向上转型</strong>和<strong>方法重写</strong>的机制来实现的。</p>
<p>&nbsp;<wbr> 面向对象程序设计的目标是：<strong>希望所撰写的程序代码都只对基类进行操作</strong>。这么一来，当加入新的继承类时，大部分程序代码都不会受影响而改写（也即是说代码具有扩充性）。所以当调用新加入的继承类时，都会首先向上转型为基类。这就是多态的向上转型。</p>
<p>&nbsp;<wbr> 当你希望通过调用基类的方法而能让继承类产生正确的行为时，这显然需要在继承类进行重写该方法。而究竟是该调用哪个继承类，这是由Java的动态绑定决定的。</p>
<p>&nbsp;<wbr> 多态最重要的一点在于<strong><em>run-time binding</em></strong>。多态是面向对象程序设计的目标。</p>
<p>&nbsp;<wbr> 关于多态中覆盖注意如下：</p>
<p><strong>属性</strong>既可以继承，也是可以&#8220;覆盖&#8221;的。但是对属性而言没有动态绑定这一特性，所以覆盖的属性被认为是子类的特别属性。从某种意义上来讲，属性决定了类（性质）。另一方面，申明的类型就决定了对象的属性。这是因为，任何对象或变量等号右面是用来赋值给符合等号左面所申明类型的，所以左面的类型是先决条件，赋值必须要符合申明类型。对于向上转型而言，因为等号右面的对象is a申明类型，所以是成立的。一定要记住，<strong>属性永远都是跟着申明类型走</strong>。但是，对<strong>方法</strong>而言是在运行时动态绑定的，它取决于对象自身的实际类型（实际上对方法而言，也是先检查向上转型后的基类该方法，若无该方法的定义，则编译错，然后再动态绑定到继承类的覆盖方法）。</p>
<p>另外，<strong>static</strong>方法不能覆盖，<strong>private</strong>方法也不能覆盖。</p>
<p>还需特别注意，方法覆盖时，若覆盖得不对（例如参数一致，仅依靠返回类型不同），则编译会出错，而不是被Java认为方法重载（除非参数类型也不一样，这样java会认为不是override，实际上它是overload）。</p>
<p>◆<strong>类初始化</strong></p>
<p>&nbsp;<wbr> 类的初始化大致上有这么几个方面。</p>
<p>a．静态变量的初始化 b．一般实例变量的初始化 c．构造函数的初始化</p>
<p>&nbsp;<wbr> 初始化的难点在于继承体系中。当有继承体系时，初始化始终要遵循的原则就是，无论如何必先初始化基类</p>
<p>&nbsp;<wbr>&nbsp;<wbr> 0．当载入当前类时，若当前类有继承体系，则依次无条件载入基类</p>
<p>&nbsp;<wbr>&nbsp;<wbr> 0&#8217;．先从最顶的基类开始顺序初始化其静态static变量，接着初始化当前类的静态static变量（也就是说，static变量的初始化是伴随着类被装载时而初始化的，它的初始化在任何构造函数执行前）</p>
<p>&nbsp;<wbr>&nbsp;<wbr> 1．先从最顶端基类，构造基类对象。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> （假如构造函数中有this或super调用，则先执行此调用）</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 1.1．首先按出现次序初始化其实例变量</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> 1.2．再执行其构造函数体</p>
<p>&nbsp;<wbr>&nbsp;<wbr> 2．依次递归上述步骤</p>
<p>&nbsp;<wbr> &lt;此外，实例变量可以不显式初始化（系统会赋默认值），但是局部变量必须显式初始化&gt;</p>
<p>◆<strong>异常</strong></p>
<p><strong>throws</strong><strong>是异常的申明，它置于方法的定义处；throw</strong><strong>是异常的掷出，它置于方法体内。</strong></p>
<p><strong>异常可分为可检测异常和非检测异常，调用申明为可检测异常的方法时必须捕获异常。</strong></p>
<p>a．方法申明了可检测异常，则调用该方法的块一定要捕获异常，否则编译出错</p>
<p>&nbsp;<wbr>&nbsp;<wbr> b．throw后面不能跟任何语句，否则编译提示语句不可到达</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>c．多个catch语句，要求更具体的异常在前，超类异常在后，否则编译出错</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>d．finally语句会在return语句之前执行，即在跳出方法之前一定会执行finally语句</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>e．假如遇到的是System.exit(0)，则无论如何，程序马上退出，finally语句不会执行</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>f．方法申明了异常，但是在方法体内可以不显示地用throw抛出异常</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>g．没有申明可检测异常的方法调用时，不可用catch捕获，否则编译出错</p>
<p>其它注意：</p>
<p>a子类中覆盖的方法只能抛出父类方法抛出异常的子集，也可以不抛出任何异常（这本身就是子集）</p>
<p>&nbsp;<wbr>&nbsp;<wbr> b 但是对于非检测异常RuntimeException则不会受到上面的约束，它们可以被随时抛出。也不受范围限制。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> c 当继承的子类没有申明异常时，假如它的一个实例被申明为超类（向上转型），这时再调用子类没有申明异常的方法，而用了catch，程序也会编译通过。（实际运行中调用的还是子类中的方法）</p>
<p>◆<strong>equals()</strong><strong>和==</strong></p>
<p>&nbsp;<wbr> 对于上述关于equals()总结如下:</p>
<p>&nbsp;<wbr>&nbsp;<wbr> a．类型不兼容的两个对象可以用equals()，但是只要比较的对象类型不同（哪怕值相同），永远返回false</p>
<p>&nbsp;<wbr>&nbsp;<wbr> b．对于没有覆盖equals()的类，即使对象类型相同，值也相同，但返回的仍旧是false，因为它用的是object的默认equals方法（与==相同）</p>
<p>&nbsp;<wbr>&nbsp;<wbr> c然而对于覆盖equals()的类，只要值相同，便返回true。这些类是String,Wrappers,Date,Calendar,BitSet等</p>
<p>&nbsp;<wbr> 对于==总结如下：</p>
<p>&nbsp;<wbr>&nbsp;<wbr> a．类型不兼容的两个对象不可以用==，若用则编译错误</p>
<p>&nbsp;<wbr>&nbsp;<wbr> b．同种类型的对象，假如不是指引同一个对象，则返回为false（只有指向同一个内存块的对象才返回true）</p>
<p>&nbsp;<wbr>&nbsp;<wbr> c．对于String情况有些不同，因为String对象有字面量和构造函数之分。字面量对象是放在缓冲池中的，这意味着，如果两个字面量值相同，则第二个对象会指向第一个已经存在的对象，而不会新产生，所以==返回的是true。用构造器产生的对象同一般对象。对于字面量来说，多个类共享的是同一个缓冲池。这意味着在另外一个类中创建一个先前类中已有的字面量字符串，则仍旧是同一对象。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 另外，注意，toUpperCase()、toLowerCase()方法而言，如果大小写形式与原始String没什么差别，方法返回原始对象，==返回true。</p>
<p>&nbsp;<wbr>&nbsp;<wbr> d．对于基本类型而言，系统会自动先归一精度，然后再比较值，若值相同则返回true。</p>
<p>◆<strong>String</strong></p>
<p>&nbsp;<wbr> String类最重要的一点在于&#8220;不变性（immutable）&#8221;。它的意思是一旦String类产生了就不会再改变了，若试图改变它都会产生新的对象。</p>
<p>&nbsp;<wbr> String对象有字面量和构造函数之分。字面量对象是放在缓冲池中的，这意味着，如果两个字面量值相同，则第二个对象会指向第一个已经存在的对象，而不会新产生，所以==返回的是true。用构造器产生的对象同一般对象。对于字面量来说，多个类共享的是同一个缓冲池。这意味着即使在另外一个类中创建一个先前类中已有的字面量字符串，则仍旧是同一对象。</p>
<p>&nbsp;<wbr> 考试中需要注意的是：s=new String(&#8220;abc&#8221;);s+=&#8221;def&#8221;;System.out.println(s);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>s=new String(&#8220;abc&#8221;);s.concat(&#8220;def&#8221;);System.out.prinln(s);</p>
<p>&nbsp;<wbr> 前一程序打印为&#8220;abcdef&#8221;，后一程序打印为&#8220;abc&#8221;。区别是第一个程序又重新赋值给了s。而第二个程序中s.concat(&#8220;def&#8221;)只是产生了一个新的对象但没有赋给谁，但原来的s不变。</p>
<p>&nbsp;<wbr> 另外，对于StringBuffer而言是可变的，对它的任何改变都是实时的。</p>
<p>◆<strong>包装类</strong></p>
<p>&nbsp;<wbr> 包装类是为了方便对基本数据类型操纵而出现的。有了包装类就可以用很多的方法来操纵基本数据类型（没有包装类想直接对基本数据类型操作是不方便的，除非自己编写方法）。</p>
<p>&nbsp;<wbr> 要熟悉包装类应该着种理解下面几点：</p>
<p>&nbsp;<wbr> a．包装类的构造器。一般说来，包装类的构造器参数有两种：<strong>基本数据值</strong>、<strong>字符串</strong></p>
<p><strong>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></strong> <strong>注意：</strong>Boolean包装类构造器当传入字符串时，除了不分大小写的true返回true外，其它字符串一律返回false</p>
<p>&nbsp;<wbr> b．常见的操作方法。例如：转换为本基本类型或其它基本类型的方法</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> eg. byteValue(),intValue()&#8230;;parseByte(String s),parseInt(String s)&#8230;</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> c．valueOf(各基本类型或字符串)的使用。ValueOf(str)是包装类的静态方法，作用等同于构造器。它会解析传入的参数，然后构造一个相同类型的包装类，并返回该包装类。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 例子：原始类型&#224;字符串&nbsp;<wbr> (new Integer(101)).toString()；String.valueOf(&#8220;101&#8221;)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 字符串&#224;（包装类）&#224;原始类型 Integer.parseInt(&#8220;string&#8221;)；</p>
<p>(new Integer(&#8220;101&#8221;)).doubleValue()；Integer.valueOf(&#8220;101&#8221;).intValue()</p>
<p>◆<strong>Math</strong><strong>类</strong></p>
<p>&nbsp;<wbr> Math类中都是静态方法。其中最易错的是三个方法：ceil(),floor(),round()</p>
<p>另外还需注意，有许多方法随基本数据类型不同有多个重载版本。eg.abs(),max()</p>
<p>a．ceil()方法。该方法返回类型为double，往单一的正坐标方向取最近的整数</p>
<p>b．floor()方法。该方法返回类型类double，取最靠近其负向的整数。</p>
<p>c．round()方法。它有两个重载版本：double和float，返回分别为long和int</p>
<p>&nbsp;<wbr>&nbsp;<wbr> long round(double a)；int round(float)</p>
<p>&nbsp;<wbr>&nbsp;<wbr> <strong>round()</strong><strong>方法＝Math.floor(a+0.5),这意味着正数5入，负数6入</strong></p>
<p><strong>&nbsp;<wbr>&nbsp;<wbr></strong> eg.System.out.println(Math.ceil(Double.MIN_VALUE))&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> //1.0</p>
<p>System.out.println(Math.floor(-0.1))&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> //-1.0</p>
<p>System.out.println(Math.round(-9.5))&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> //-9</p>
<p>System.out.println(Math.round(-9.6))&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> //-10</p>
<p>System.out.println(Math.round(Double.MIN_VALUE))&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> //0</p>
<p>◆<strong>collection</strong><strong>类</strong></p>
<p>&nbsp;<wbr> collection类提供了持有对象的便利性，并对持有对象的操作便利性。正如其名，收集意为将各种类型的对象收在一起，且数目不限（有点像收集袋）。收集会将放入其中的所有对象均视为Object（向上转型），所以在取出元素对象时，必须显式（即强制转型）指出其类型。</p>
<p>&nbsp;<wbr> 对象收集从整体上分为Collection接口和Map接口。这种分类的标准是：某个元素位置上放置元素对象的个数。显然，Map接口放置的是一对。</p>
<p>&nbsp;<wbr> Collection接口又可扩展为两个基本接口：List接口和Set接口。</p>
<p>&nbsp;<wbr> 依上所述，对象收集可以划分为四个基本的类型：<strong><em>Collection、List、Set、Map</em></strong></p>
<p>&nbsp;<wbr> &#183; Collection 它是一个基类的接口，对元素没有任何的限制，可以重复并且无序。</p>
<p>&nbsp;<wbr> &#183; List&nbsp;<wbr> 从其名就知是有序的列表。它描述的是按顺序将对象放入其中。显然，后放入的元素有可能与先前放入的对象是相同的。所以，List是允许对象重复出现的有序列表。</p>
<p>&nbsp;<wbr> &#183; Set&nbsp;<wbr>&nbsp;<wbr> 其实就是数学上所说的集合，它不允许有重复的元素。其中可以有空集（即null对象）。Set中的元素不要求有序。</p>
<p>&nbsp;<wbr> &#183; Map&nbsp;<wbr>&nbsp;<wbr> 即映射，借助于key和value来描述对象的搜索。key域中要求唯一性（其实就是一个Set），value域可以允许有重复的元素（其实就是一个Collection）。另外注意：常见的HashMap是无序的，而TreeMap是有序的。</p>
<p>◆<strong>标识符</strong></p>
<p>&nbsp;<wbr> a．所有标识符的首字符必须是字母（大小写）、下划线_、美元符号$（或符号￥）</p>
<p>b．接下来的可以是由数字（0-9）及首字符相同类型的字符（字母、_、$），其它任何特殊字符均不可</p>
<p>c．标识符不能使用Java关键字和保留字（50个）。但是注意像java,Integer,sizeof,friendly等都不是Java的关键字</p>
<p>d．标识符大小写是敏感的，但没有长度的限制。</p>
<p>◆<strong>Switch(i)</strong></p>
<p>&nbsp;<wbr> a．switch(i)中的参数最高精度是int（或者short,byte,char），但不可是long，float,double</p>
<p>&nbsp;<wbr> b．default语句可以放置于任何地方（default意为都不匹配case中的值）</p>
<p>&nbsp;<wbr> c．当语句中未加break语句时，则程序会从匹配的地方开始执行（包括匹配default语句），接下来所有的语句都会被执行（而不管匹配否），直到遇到break语句或switch尾部。</p>
<p>◆<strong>垃圾收集</strong></p>
<p>&nbsp;<wbr> a．只要一个对象失去了<strong>所有</strong>的reference，就可以考虑收集到垃圾收集堆了。</p>
<p>&nbsp;<wbr> B．当失去对一个对象的所有引用时，JVM只是考虑垃圾收集，但并不意味着就立刻收回这个对象的内存，甚至根本不收回。JVM仅会在需要更多的内存以继续执行程序时，才会进行垃圾收集。</p>
<p>C．多数情况下，你永远不会知道垃圾收集什么时候会发生。Java将垃圾收集进程作为一个低优先级线程在运行。在Java中垃圾收集是不能被强迫<strong>立即</strong>执行的。调用System.gc()或Runtime.gc()静态方法不能保证垃圾收集器的立即执行，因为，也许存在着更高优先级的线程。</p>
<p>D．如果你想人工调用垃圾收集，并想在收集对象时执行一些你想要的任务，你就可以覆盖一个叫finalize()的方法。java会为每一个对象只调用一次finalize()方法。<strong>finalize()方法必须被申明为protected的，不返回任何值（viod），而且要申明抛出一个Throwable对象，并一定要调用超类的finalize()方法（super.finalize()）。</strong></p>
<p>&nbsp;<wbr>&nbsp;<wbr> eg.protected void finalize() throws Throwable(){</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> super.finalize();</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &#8230;&#8230;&#8230;&#8230;;}</p>
<p>◆<strong>is a &amp; has a</strong></p>
<p>&nbsp;<wbr> is a&nbsp;<wbr> 描述的是一个超类和一个子类的关系，也即是<strong>继承</strong>的关系。</p>
<p>&nbsp;<wbr> has a 描述的是一个对象的部分是另一个对象，也即是<strong>组合</strong>的关系（或称为调用）。</p>
<p>◆<strong>内类与匿名类</strong></p>
<p>&nbsp;<wbr> 内类是被包含的类中类，有三个方面需要注意：一般内类、方法内类、静态内类。</p>
<p>&nbsp;<wbr> &#183; 一般内类它可以被当做外类的一个&#8220;实例变量&#8221;来看待。因此，四个接入控制符public、protected、default、private。只是注意：要在外类的non-static函数外产生该内类对象，必须以<strong><em>OuterClassName.InnerClassName</em></strong>的形式指定该内类对象的<strong>类型申明</strong>。<strong>一般内类必须得关联至其外类的某个对象</strong>。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 一般内类不可拥有static成员。</p>
<p>&#183; 方法内类它属于<strong>范围</strong>型内类，也就是说你无法在方法外来调用内类，从这一点来讲它可视为方法的局部变量。但是，虽然有它的范畴性，毕竟内类还是类，它不会像局部变量那样随着方法的返回就消失了，它仍旧被java视为类。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> A．方法内类可以直接访问外类的任何成员</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> B．方法内类只能访问该方法中final型局部变量和final型的方法参数</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> C. 方法内类不可有任何<strong>接入控制符</strong>修饰（这一点与局部变量相同）</p>
<p>&nbsp;<wbr> &#183; 静态内类它在产生其对象时不需要存在一个外类对象。它可被视为static函数。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> static内类可以置于接口中。</p>
<p>&nbsp;<wbr> &#183; 匿 名 类它实际上是<strong>继承</strong>自new类的一个无名类。New传回的reference会被自动向上转型。匿名类不能拥有构造器，但是可以通过其基类默认或带参数的构造器来申明。</p>
<p>匿名类添加任何修饰符（遵循超类的修饰符），也不可实现接口、抛出异常。</p>
<p>◆<strong>断言</strong></p>
<p>&nbsp;<wbr> 断言是Java 1.4中新添加的功能，是Java中的一种新的错误检查机制，它提供了一种在代码中进行正确性检查的机制，但是这项功能可以根据需要关闭。断言包括：<strong>assert</strong>关键字，<strong>AssertionError</strong>类，以及在java.lang.ClassLoader中增加了几个新的有关assert方法。</p>
<p>assert最重要的特点是assert语句可以在<strong>运行时</strong>任意的开启或关闭，默认情况下是关闭的。</p>
<p>断言语句有两种合法的形式：a．<strong>assert expression_r1;</strong> b．<strong>assert expression_r1 : expression_r2;</strong></p>
<p>expression_r1是一条被判断的布尔表达式，必须保证在程序执行过程中它的值一定是真；expression_r2是可选的，用于在expression_r1为假时，传递给抛出的异常AssertionError的构造器，因此expression_r2的类型必须是合法的AssertionError构造器的参数类型。AssertionError除了一个不带参数的缺省构造器外，还有7个带单个参数的构造器，分别为：object（eg.String） &nbsp;<wbr>boolean &nbsp;<wbr>char &nbsp;<wbr>int &nbsp;<wbr>long &nbsp;<wbr>float &nbsp;<wbr>double。第一种形式如果抛出异常，则调用AssertionError的缺省构造器，对于第二种形式，则根据expression_r2值的类型，分别调用7种单参数构造器中的一种。</p>
<p>A．<strong>assert</strong><strong>程序的编译</strong>：javac -source 1.4 TestAssert.java（提示java按1.4版本编译）</p>
<p>B．<strong>assert</strong><strong>程序的运行</strong>：java &#8211;ea TestAssert 或者 java &#8211;ea:TestAssert TestAssert</p>
<p>&nbsp;<wbr>&nbsp;<wbr> 其它的运行参数：java -ea:pkg0... TestAssert；java &#8211;esa；java &#8211;dsa（系统类断言），另外，还可以同时组合用。当一个命令行使用多项 -ea -da 参数时，遵循两个基本的原则：<strong>后面的参数设定会覆盖前面参数的设定，特定具体的参数设定会覆盖一般的参数设定</strong>。</p>
<p>C．<strong>AssertinError</strong><strong>类</strong>是Error的直接子类，因此代表程序出现了严重的错误，这种异常通常是不需要程序员使用catch语句捕捉的。</p>
<p>D．<strong>使用</strong><strong>assert</strong><strong>的准则</strong>：assert语句的作用是保证程序内部的一致性，而不是用户与程序之间的一致性，所以不应用在保证命令行参数的正确性。可以用来保证传递给<strong><em>private</em></strong>方法参数的正确性。因为私有方法只是在类的内部被调用，因而是程序员可以控制的，我们可以预期它的状态是正确和一致的。公有方法则不适用。此外，assert语句可用于检查任何方法结束时状态的正确性，及在方法的开始检查相关的初始状态等等。</p>
<p>assert语句并不构成程序正常运行逻辑的一部分，时刻记住在运行时它们可能不会被执行。</p>
<p>◆<strong>线程</strong></p>
<p>&nbsp;<wbr> 线程是将程序中容易消耗大量cpu且易陷入死循环的片断代码独立出来作为一个线程来运行（也即线程是一个代码块）。</p>
<p>&nbsp;<wbr> 线程一经启动start，就会进入ready状态（实际上就是runnable状态，只是等待分配cpu）。这也说明线程并不会马上就running，其运行具有不确定性。线程启动后，只要不跳出run()方法，则一直都有机会running，它由系统自动在各线程间分配cpu时间来running。要牢记的是：<strong>线程运行与中断具有不确定性，你永远也不知道线程何时会运行，何时会中断。</strong></p>
<p>&nbsp;<wbr> 线程从对象的角度来看，它自身也可以是一个对象。它可视为其它对象中的一个代码块。</p>
<p>&nbsp;<wbr> 在线程的概念中要特别注意几个概念：<strong>单线程</strong>、<strong>多线程</strong>、<strong>多线程的运行</strong>、<strong>多线程间的同步（资源访问）</strong>、<strong>多线程间的通信</strong>。</p>
<p>&nbsp;<wbr> &#183; <strong>单线程</strong> 对于单线程而言，编写其程序是比较简单的，也比较容易理解，因为它并不涉及到synchronized和communication问题。创建单线程的方法有两种，其一、扩展Thread类，即class A extends Thread{public void run(){};&#8230;&#8230;}；其二、实现Runnable接口，class B implements Runnable{Thread t=new Thread(this);public void run(){};&#8230;&#8230;}；</p>
<p>&nbsp;<wbr> &#183; <strong>多线程</strong> 相对于单线程而言，多线程会复杂很多，原因就是它们会涉及到<strong>多线程间的资源访问</strong>和<strong>多线程间通信</strong>问题。这就涉及到下面所说的三个方面：<strong>多线程的运行</strong>、<strong>多线程间的同步（资源访问）</strong>、<strong>多线程间的通信</strong></p>
<p>&nbsp;<wbr> &#183; <strong>多线程的运行</strong> 对于多个可运行runnable的线程来说，<strong>运行与中断具有不确定性，永远也无法知道线程何时会运行，何时会中断</strong>。但是多线程运行也遵循几个原则：如果多个线程具有同样的优先级，则系统会在它们之间切换cpu时间运行；<strong>JVM</strong><strong>基于优先级来决定线程的运行，但是这并不意味着一个低优先级的线程一直不运行</strong>。</p>
<p>&nbsp;<wbr> &#183; <strong>多线程的同步</strong> 被线程可访问的每个对象都有一个仅被一个线程访问控制的锁，锁控制着对对象的同步码的存取。这个可被多个线程访问的对象就是所说的资源共享问题。</p>
<p>A．在程序中，可以通过定义一个synchronized代码块或多个synchronized方法来使得调用的线程获得该对象的控制锁。通过获得对象的锁，该线程就会阻止其它线程对该对象所定义的<strong>同步块</strong>或<strong>同步方法</strong>进行操作（特别注意的是，此时并不能保证其它线程对该对象的非同步变量和非同步方法进行操作）。</p>
<p>B．线程只有在同步块或同步方法返回后才释放锁。</p>
<p>C．synchronized并不能保证程序的运行连续性，而只是保证同一性。也就是说即使在synchronized块或方法中，线程的运行仍旧会有中断的可能性。尽管如此，但它却能确保别的线程不会再访问该对象的其它同步块和方法，因为对象锁并未释放。这一事实说明了&#8220;多线程的运行&#8221;与&#8220;多线程间的同步&#8221;是两个独立的概念。</p>
<p>D．多线程的同步块或方法可以放在任何可被线程访问的对象中（包括线程本身，它实际上也可被其它的线程访问）。</p>
<p>&nbsp;<wbr> &#183; <strong>多线程间的通信</strong> 多线程间的同步消除了一个线程在改变另一个线程的稳定对象状态时发生的并发错误，但是就线程间通信而言，同步不起任何作用，也就是说&#8220;多线程间的通信&#8221;又是一个独立的概念。多线程间的通信通常是靠wait(),notify()两个方法来实现的，有关这两个方法的总结如下：</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 1.wait(),notify()属于<strong>object方法</strong>，并不是线程的方法</p>
<p>2.object.wait()&nbsp;<wbr> 意为：调用我（指该object）的当前线程你得等等，也就是使...（调用我的当前线程）...等待</p>
<p>object.notify()意为：该唤醒其它先前调用过我的且在等待的线程</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 从上述意义可知，wait(),notify()的对象是指线程所要用到的共享对象（当然共享对象也可以是线程对象），但是它的方法动作却是针对调用它的线程。（通常情况下，对象的方法是作用于自己的属性，而很少作用于其它对象。若要作用于其它对象，则用调用object.method()）</p>
<p>3.wait(),notify()必须成对出现，出现的方式可有3种形式。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> A.｛wait();.... notify();｝</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> B.｛wait();｝... ｛object.notify();｝</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> C.｛notify();｝... ｛object.wait();｝</p>
<p>4.<strong>wait(),notify()</strong><strong>必须出现在synchronized方法或块中，否则会出现异常</strong>。原因是因为wait()会释放对象锁，而锁必然是出现在同步方法或块中。另外，wait()同sleep()一样，<strong>也必须捕捉异常InterruptedException</strong>。</p>
<p>5.wait(),notify()的执行一般与外在的条件有关，只有条件改变了才触发唤醒等待的线程。这种条件的改变通常是以旗标(Tag)的方式出现，也即当某一方法执行完后，应当立即改变旗标值。假若需要让线程交替执行，则还需要加入互斥条件的判断。eg.同步方法1中{if(a)}，则同步方法2中{if(!a)}</p>
<p>6.当执行完notify()时，程序并不会立即去运行调用wait()的线程，而直到释放notify()的对象锁。当释放完锁后，程序重新分配cpu，要注意的是，此时系统并不一定就让wait的线程去运行，而有可能是刚才调用notify()的线程接着继续运行。这一点正说明了线程运行与中断的不确定性。</p>
<p>7.一般说来，notify()是唤醒等待池中等待时间最长的线程；而notifyAll()是唤醒等待池中所有等待线程，然后线程去竞争对象锁。这里说的是一般情况，有时情况并非如此，这是由系统中线程运行与中断的不确定性决定的。</p>
<p>8.wait()，notify()通常情况下需要sleep()的配合，否则屏幕中的运行显式会&#8220;飞速&#8221;。</p>
<p>9.多线程间的通信会出现死锁现象，即wait的线程有可能永远也得不到对象锁。</p>
<p>-------------------------------------------------------------------------------</p>
<p>◆<strong>其他注意问题</strong></p>
<p>☆&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 数组</p>
<p>a．数组在使用之前，必须要保证给其分配内存（系统会用默认值初始化），不可只定义。否则编译通过运行也会出现空指针错误。分配内存只需通过new就可以了。</p>
<p>b．二维数组的第二维可以是变长的，而且可以在定义时不指定具体值。这意味着java中的二维数组不必像矩阵那样要求每一维长度都相同。</p>
<p>☆&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 变量赋值</p>
<p>a．实例变量只可在定义时显式赋值，不可先定义，再赋值（这样的话编译出错）。</p>
<p>b．方法变量既可以在定义时显式赋值，又可以先定义以后再赋值。</p>
<p>c．static变量可以在类的任何地方赋值（若在方法中赋值，实际上是重赋值了）。</p>
<p>d．final变量可以在任何地方赋值，但是一旦赋值，就不允许再次重赋值。</p>
<p>e．static final变量只能在定义处赋值（即：常量）。</p>
<p>☆&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 移位</p>
<p>a．&gt;&gt;&nbsp;<wbr> 首位的拷贝右移位。等同于有符号的除法。</p>
<p>b．&gt;&gt;&gt; 零填充右移位。</p>
<p>c．&lt;&lt;&nbsp;<wbr> 左移位。等同于有符号乘法，但是必须遵循整数的溢出原则。</p>
<p>d．&gt;&gt;32 &gt;&gt;&gt;32<strong>任何移多少位都是移模32的余数</strong>。eg.移32位即不移。</p>
<p>☆&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> byte、char和int</p>
<p>由于char的取值范围和int的正取值范围相同，所以，整型字面量可以直接赋给char。但是要是明确将一个整型（int）变量直接赋给char变量则编译错误。</p>
<p>另外，int i=5;char c=&#8217;a&#8217;;c+=i;编译是通过的。</p>
<p>byte类型在强制转型的情况下，当范围超出时会循环溢出。</p>
<p>☆&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 求模%</p>
<p>求余只管左边的符号，右边不管。</p>
<p>eg. int a=-5;int b=-2;System.out.println(a%b) //-1</p>
<p>&nbsp;<wbr>&nbsp;<wbr> int a=-5;int b=2;System.out.println(a%b) //-1</p>
<p>&nbsp;<wbr>&nbsp;<wbr> int a=5;int b=-2;System.out.println(a%b) //1</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298542.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:49 <a href="http://www.blogjava.net/balajinima/articles/298542.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第九部分：集合类框架</title><link>http://www.blogjava.net/balajinima/articles/298540.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:44:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298540.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298540.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298540.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298540.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298540.html</trackback:ping><description><![CDATA[<p style="text-indent: 2em" align="left">第九部分：集合类框架</p>
<ul style="text-indent: 2em" type="square">
    <li>知道如何在特定的条件下选择适合的集合类/接口。
    <li>能正确地实现hashcode方法。 </li>
</ul>
<h2 style="text-indent: 2em">第一节&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 所有接口和class定义</h2>
<p style="text-indent: 2em">1:Set</p>
<p style="text-indent: 2em">public interface Set extends Collection</p>
<p style="text-indent: 2em">A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematical set abstraction.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">2:SortedSet</p>
<p style="text-indent: 2em">public interface SortedSet extends Set.</p>
<p style="text-indent: 2em">A set that further guarantees that its iterator will traverse the set in ascending element order, sorted according to the natural ordering of its elements (see Comparable), or by a Comparator provided at sorted set creation time.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">3:HashSet</p>
<p style="text-indent: 2em">public class HashSet extends AbstractSet implements Set, Cloneable, Serializable</p>
<p style="text-indent: 2em">This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time. This class permits the null element.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">4:TreeSet</p>
<p style="text-indent: 2em">public class TreeSet extends AbstractSet implements SortedSet, Cloneable, Serializable</p>
<p style="text-indent: 2em">This class implements the Set interface, backed by a TreeMap instance. This class guarantees that the sorted set will be in ascending element order, sorted according to the natural order of the elements (see Comparable), or by the comparator provided at set creation time, depending on which constructor is used.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">5:LinkedHashSet:</p>
<p style="text-indent: 2em">public class LinkedHashSet extends HashSet implements Set, Cloneable, Serializable</p>
<p style="text-indent: 2em">Hash table and linked list implementation of the Set interface, with predictable iteration order. This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order). Note that insertion order is not affected if an element is re-inserted into the set. (An element e is reinserted into a set s if s.add(e) is invoked when s.contains(e) would return true immediately prior to the invocation.)</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">5:Map</p>
<p style="text-indent: 2em">public interface Map</p>
<p style="text-indent: 2em">An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">6:SortedMap</p>
<p style="text-indent: 2em">public interface SortedMap extends Map</p>
<p style="text-indent: 2em">A map that further guarantees that it will be in ascending key order, sorted according to the natural ordering of its keys (see the Comparable interface), or by a comparator provided at sorted map creation time. (This interface is the map analogue of the SortedSet interface.)</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">7:HashMap(允许key和value为NULL)</p>
<p style="text-indent: 2em">public class HashMap extends AbstractMap implements Map, Cloneable, Serializable</p>
<p style="text-indent: 2em">Hash table based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.) This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">8:TreeMap</p>
<p style="text-indent: 2em">public class TreeMap extends AbstractMap implements SortedMap, Cloneable, Serializable</p>
<p style="text-indent: 2em">Red-Black tree based implementation of the SortedMap interface. This class guarantees that the map will be in ascending key order, sorted according to the natural order for the key's class (see Comparable), or by the comparator provided at creation time, depending on which constructor is used.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">9:HashTable(不允许key和value为NULL)</p>
<p style="text-indent: 2em">public class Hashtable extends Dictionary implements Map, Cloneable, Serializable.</p>
<p style="text-indent: 2em">This class implements a hashtable, which maps keys to values. Any non-null object can be used as a key or as a value.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">9:LinkedHashMap</p>
<p style="text-indent: 2em">public class LinkedHashMap extends HashMap</p>
<p style="text-indent: 2em">Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order). Note that insertion order is not affected if a key is re-inserted into the map. (A key k is reinserted into a map m if m.put(k, v) is invoked when m.containsKey(k) would return true immediately prior to the invocation.)</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">9:IdentityHashMap</p>
<p style="text-indent: 2em">public class IdentityHashMap extends AbstractMap implements Map, Serializable, Cloneable</p>
<p style="text-indent: 2em">This class implements the Map interface with a hash table, using reference-equality in place of object-equality when comparing keys (and values). In other words, in an IdentityHashMap, two keys k1 and k2 are considered equal if and only if (k1==k2). (In normal Map implementations (like HashMap) two keys k1 and k2 are considered equal if and only if (k1==null ? k2==null : k1.equals(k2)).)</p>
<p style="text-indent: 2em">This class is not a general-purpose Map implementation! While this class implements the Map interface, it intentionally violates Map's general contract, which mandates the use of the equals method when comparing objects. This class is designed for use only in the rare cases wherein reference-equality semantics are required.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">10:List</p>
<p style="text-indent: 2em">public interface List extends Collection</p>
<p style="text-indent: 2em">An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">Unlike sets, lists typically allow duplicate elements. More formally, lists typically allow pairs of elements e1 and e2 such that e1.equals(e2), and they typically allow multiple null elements if they allow null elements at all.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">11:ArrayList</p>
<p style="text-indent: 2em">public class ArrayList extends AbstractList implements List, Cloneable, Serializable</p>
<p style="text-indent: 2em">Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface, this class provides methods to manipulate the size of the array that is used internally to store the list. (This class is roughly equivalent to Vector, except that it is unsynchronized.)</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">12:LinkedList</p>
<p style="text-indent: 2em">public class LinkedList extends AbstractSequentialList implements List, Cloneable, Serializable</p>
<p style="text-indent: 2em">Linked list implementation of the List interface. Implements all optional list operations, and permits all elements (including null). In addition to implementing the List interface, the LinkedList class provides uniformly named methods to get, remove and insert an element at the beginning and end of the list. These operations allow linked lists to be used as a stack, queue, or double-ended queue (deque).</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">13:Vector</p>
<p style="text-indent: 2em">public class Vector extends AbstractList implements List, Cloneable, Serializable</p>
<p style="text-indent: 2em">The Vector class implements a growable array of objects. Like an array, it contains components that can be accessed using an integer index. However, the size of a Vector can grow or shrink as needed to accommodate adding and removing items after the Vector has been created.</p>
<p style="text-indent: 2em">&nbsp;<wbr></p>
<p style="text-indent: 2em">14:Collection</p>
<p style="text-indent: 2em">public interface Collection</p>
<p style="text-indent: 2em">The root interface in the collection hierarchy. A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and others unordered. The SDK does not provide any direct implementations of this interface: it provides implementations of more specific subinterfaces like Set and List. This interface is typically used to pass collections around and manipulate them where maximum generality is desired.</p>
<p style="text-indent: 2em">15:Collections</p>
<p style="text-indent: 2em">public class Collections extends Object</p>
<p style="text-indent: 2em">This class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends.</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298540.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:44 <a href="http://www.blogjava.net/balajinima/articles/298540.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第七部分：线程</title><link>http://www.blogjava.net/balajinima/articles/298538.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:43:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298538.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298538.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298538.html</trackback:ping><description><![CDATA[<p align="left">第七部分：线程</p>
<ul type="disc">
    <li>能用java.lang,Thread或java.lang.Runnable两种方法定义，实例化和开始一个新的线程。
    <li>知道哪些情况下可能阻止一个线程的执行。
    <li>能使用synchronized,wait,notify和notifyAll去避免并发访问的问题，以及线程间相互通讯的问题。
    <li>当执行synchronized,wait,notify和notifyAll时，知道线程和对象锁之间的交互作用。 </li>
</ul>
<div>
<h3><a name="_Toc74451196">&#167;1.1.1&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 一</a></h3>
<p>What will happen when you attempt to compile and run the following code?</p>
<p>class MyThread extends Thread</p>
<p>{</p>
<p>public void run()</p>
<p>{</p>
<p>System.out.println("MyThread: run()");</p>
<p>}</p>
<p>public void start()</p>
<p>{</p>
<p>System.out.println("MyThread: start()");</p>
<p>}</p>
<p>}</p>
<p>class MyRunnable implements Runnable</p>
<p>{</p>
<p>public void run()</p>
<p>{</p>
<p>System.out.println("MyRunnable: run()");</p>
<p>}</p>
<p>public void start()</p>
<p>{</p>
<p>System.out.println("MyRunnable: start()");</p>
<p>}</p>
<p>}</p>
<p>public class MyTest</p>
<p>{</p>
<p>public static void main(String args[])</p>
<p>{</p>
<p>MyThread myThread &nbsp;<wbr>= &nbsp;<wbr>new MyThread();</p>
<p>MyRunnable myRunnable = new MyRunnable();</p>
<p>Thread thread &nbsp;<wbr>= &nbsp;<wbr>new Thread(myRunnable);</p>
<p>myThread.start();</p>
<p>thread.start();</p>
<p>}</p>
<p>}</p>
<p>Choices:</p>
<p>a. Prints : MyThread: start() followed by MyRunnable:run()</p>
<p>b. Prints : MyThread: run() followed by MyRunnable:start()</p>
<p>c. Prints : MyThread: start() followed by MyRunnable:start()</p>
<p>d. Prints : MyThread: run() followed by MyRunnable:run()</p>
<p>e. Compile time error</p>
<p>f. None of the above</p>
<p>―――――――――――――――</p>
<p>A is the correct choice. In the above code there is not any compilation error. Thus choice E is incorrect. Inside main() method, objects of MyThread and MyRunnable class are created followed by creation of Thread with object of MyRunnable class. Note that MyThread class extends Thread class and overrides the start() method of the Thread class. Thus on execution of "myThread.start()" statement, the start() method of the MyThread class will be executed and as a result "MyThread:start()" will be printed. Had the start() method not there in MyThread class, the start() method of the Thread class would be called which in turn would call the run() method of the MyThread class. On execution of "thread.start();", the start() method of the Thread class would be called which in turn will call the run() method of the class which is passed to Thread constructor (i.e. MyRunnable class). Thus "MyRunnable:run()" will be printed out. Thus choice A is correct.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451197">&#167;1.1.2&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 二</a></h3>
<p>What will be the output on compiling/running the following code?</p>
<p>public class MyThread implements Runnable</p>
<p>{</p>
<p>&nbsp;<wbr> String myString = "Yes ";</p>
<p>&nbsp;<wbr> public void run()</p>
<p>&nbsp;<wbr> {</p>
<p>&nbsp;<wbr> &nbsp;<wbr> this.myString = "No ";</p>
<p>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr> public static void main(String[] args)</p>
<p>&nbsp;<wbr> {</p>
<p>&nbsp;<wbr> &nbsp;<wbr> MyThread t = new MyThread();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> new Thread(t).start();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> for (int i=0; i &lt; 10; i++)</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>System.out.print(t.myString);</p>
<p>&nbsp;<wbr> }</p>
<p>}</p>
<div>
<p>Choices:</p>
<p>a. Compilation Error &nbsp;<wbr></p>
<p>b. Prints : Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes and so on.</p>
<p>c. Prints : No No No No No No No No No No and so on.</p>
<p>d. Prints : Yes No Yes No Yes No Yes No Yes No and so on.</p>
<p>e. The Output cannot be determined.</p>
</div>
<p>E is correct. Please note that there will not be any compilation error when the above code is compiled. Also note that calling start() method on a Thread doesn't start the Thread. It only makes a Thread ready to be called. Depending on the operation system and other running threads, the thread on which start is called will get executed. In the above case it is not guaranteed that the thread will be executed(i.e. run() method will be called), always before "for" loop is executed. Thus the output cannot be determined.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451198">&#167;1.1.3&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 三</a></h3>
<p>Multiple objects of MyClass (given below) are used in a program that uses</p>
<p>multiple Threadsto create new integer count. What will happen when other threads</p>
<p>use the following code?</p>
<p>class MyClass</p>
<p>{</p>
<p>static private int myCount = 0;</p>
<p>int yourNumber;</p>
<p>private static synchronized int nextCount()</p>
<p>{</p>
<p>return ++myCount;</p>
<p>}</p>
<p>public void getYourNumber()</p>
<p>{</p>
<p>yourNumber = nextCount();</p>
<p>}</p>
<p>}</p>
<p>Choices:</p>
<p>a. The code will give compilation error.</p>
<p>b. The code will give runtime error.</p>
<p>c. Each thread will get a unique number.</p>
<p>d. The uniqueness of the number among different Threads can't be guaranteed.</p>
<p>―――――――――――――</p>
<p>C is correct. The use of synchronized ensures that the number generated will not be duplicated, no matter how many Threads are trying to create the number. Thus D is incorrect. A and B are incorrect as the above code will not give any compiletime or runtime error.</p>
<h3><a name="_Toc74451199">&#167;1.1.4&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 四</a></h3>
<p>What will happen when you attempt to compile and run the following code?</p>
<p>public class MyThread extends Thread</p>
<p>{</p>
<p>String myName;</p>
<p>MyThread(String name)</p>
<p>{</p>
<p>myName = name;</p>
<p>}</p>
<p>public void run()</p>
<p>{</p>
<p>for(int i=0; i&lt;100;i++)</p>
<p>{</p>
<p>System.out.println(myName);</p>
<p>}</p>
<p>}</p>
<p>public static void main(String args[])</p>
<p>{</p>
<p>try</p>
<p>{</p>
<p>MyThread mt1 = new MyThread("mt1");</p>
<p>MyThread mt2 = new MyThread("mt2");</p>
<p>mt1.start();</p>
<p>// XXX</p>
<p>mt2.start();</p>
<p>}</p>
<p>catch(InterruptedException ex)</p>
<p>{</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>Choices:</p>
<p>a.The above code in its current condition will not compile.</p>
<p>b. In order to make the MyThread class prints "mt1" (100 times) followed by</p>
<p>"mt2" (100 times), mt1.join(); can be placed at //XXX position.</p>
<p>c. In order to make the MyThread class prints "mt1" (100 times) followed by</p>
<p>"mt2" (100 times), mt1.sleep(100); can be placed at //XXX position.</p>
<p>d. In order to make the MyThread class prints "mt1" (100 times) followed by</p>
<p>"mt2" (100 times), mt1.run(); can be placed at //XXX position.</p>
<p>e. In order to make the MyThread class prints "mt1" (100 times) followed by</p>
<p>"mt2" (100 times), there is no need to write any code.</p>
<p>――――――――――――――</p>
<p>A and B are correct. In its current condition, the above code will not compile as "InterruptedException" is never thrown in the try block. The compiler will give following exception: "Exception java.lang.InterruptedException is never thrown in the body of the corresponding try statement." Note that calling start() method on a Thread doesn't start the Thread. It only makes a Thread ready to be called. Depending on the operating system and other running threads, the thread on which start is called will get executed. After making the above code to compile (by changing the InterruptedException to some other type like Exception), the output can't be predicted (the order in which mt1 and mt2 will be printed can't be guaranteed). In order to make the MyThread class prints "mt1" (100 times) followed by "mt2" (100 times), mt1.join() can be placed at //XXX position. The join() method waits for the Thread on which it is called to die. Thus on calling join() on mt1, it is assured that mt2 will not be executed before mt1 is completed. Also note that the join() method throws InterruptedException, which will cause the above program to compile successfully. Thus choice A and B are correct.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451200">&#167;1.1.5&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 五</a></h3>
<p>What will happen when you attempt to compile and run the following code?</p>
<p>public class MyThread extends Thread{</p>
<p>String myName;</p>
<p>MyThread(String name){</p>
<p>myName = name;</p>
<p>}</p>
<p>public void run(){</p>
<p>for(int i=0; i&lt;100;i++){</p>
<p>System.out.println(myName);</p>
<p>}</p>
<p>}</p>
<p>public static void main(String args[]){</p>
<p>try{</p>
<p>MyThread mt1 = new MyThread("mt1");</p>
<p>MyThread mt2 = new MyThread("mt2");</p>
<p>mt1.start();</p>
<p>// XXX</p>
<p>mt2.start();</p>
<p>}catch(InterruptedException ex){}</p>
<p>}</p>
<p>}</p>
<p>A. compile error</p>
<p>B. mt1.join();</p>
<p>C. mt1.sleep(100);</p>
<p>D. mt1.run()</p>
<p>E. nothing need</p>
<p>&nbsp;<wbr></p>
<p>Choice A and B are correct. In its current condition, the above code will not compile as "InterruptedException" is never thrown in the try block. The compiler will give following exception: "Exception java.lang.InterruptedException is never thrown in the body of the corresponding try statement."</p>
<p>Note that calling start() method on a Thread doesn't start the Thread. It only makes a Thread ready to be called. Depending on the operating system and other running threads, the thread on which start is called will get executed. After making the above code to compile (by changing the InterruptedException to some other type like Exception), the output can't be predicted (the order in which mt1 and mt2 will be printed can't be guaranteed). In order to make the MyThread class prints "mt1" (100 times) followed by "mt2" (100 times), mt1.join() can be placed at //XXX position. The join() method waits for the Thread on which it is called to die. Thus on calling join() on mt1, it is assured that mt2 will not be executed before mt1 is completed. Also note that the join() method throws InterruptedException, which will cause the above program to compile successfully. Thus choice A and B are correct.</p>
<h3><a name="_Toc74451201">&#167;1.1.6&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 六</a></h3>
<p>Multiple objects of MyClass (given below) are used in a program that uses multiple Threads to create new integer count. What will happen when other threads use the following code?</p>
<p>class MyClass{</p>
<p>static private int myCount = 0;</p>
<p>int yourNumber;</p>
<p>private static synchronized int nextCount(){</p>
<p>return ++myCount;&nbsp;<wbr>&nbsp;<wbr> //myCount为static</p>
<p>}</p>
<p>public void getYourNumber(){</p>
<p>yourNumber = nextCount();</p>
<p>}</p>
<p>}</p>
<p>A. the code ill give ompilation error</p>
<p>B. the code ill give runtime error</p>
<p>C. each thread will get a unique number</p>
<p>D. the uniqueness of the number different Threads can&#8217;t be guaranteed.</p>
<p>&nbsp;<wbr></p>
<p>C is correct. The use of synchronized ensures that the number generated will not be duplicated, no matter how many Threads are trying to create the number. Thus D is incorrect. A and B are incorrect as the above code will not give any compiletime or runtime error.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451202">&#167;1.1.7&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 七</a></h3>
<p>What will be the output on compiling/running the following code?</p>
<p>public class MyThread implements Runnable {</p>
<p>&nbsp;<wbr> String myString = "Yes ";</p>
<p>&nbsp;<wbr> public void run() {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> this.myString = "No ";</p>
<p>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr> public static void main(String[] args)&nbsp;<wbr> {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> MyThread t = new MyThread();</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> new Thread(t).start();</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> for (int i=0; i &lt; 10; i++)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.print(t.myString);</p>
<p>&nbsp;<wbr> }</p>
<p>}</p>
<p>A. compile error</p>
<p>B. prints: yes yes yes yes yes yes and so on</p>
<p>C. prints: no no no no no no no no and so on</p>
<p>D. prints: yes no yes no ye no ye no and so on</p>
<p>E. the output cannot be determinated</p>
<p>&nbsp;<wbr></p>
<p>E is correct. Please note that there will not be any compilation error when the above code is compiled. Also note that calling start() method on a Thread doesn't start the Thread. It only makes a Thread ready to be called. Depending on the operation system and other running threads, the thread on which start is called will get executed. In the above case it is not guaranteed that the thread will be executed(i.e. run() method will be called), always before "for" loop is executed. Thus the output cannot be determined.</p>
<h3><a name="_Toc74451203">&#167;1.1.8&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 八</a></h3>
<p>Which statements about thread are true?</p>
<p>　　A. Once a thread is created, it can star running immediately.</p>
<p>&nbsp;<wbr></p>
<p>　　B. To use the start() method makes a thread runnable, but it does not</p>
<p>necessarily start immediately.</p>
<p>&nbsp;<wbr></p>
<p>　　C. When a thread stops running because of pre-emptive, it is placed at</p>
<p>the front end of the runnable queue.</p>
<p>&nbsp;<wbr></p>
<p>　　D. A thread may cease to be ready for a variety of reasons.</p>
<p>&nbsp;<wbr></p>
<p>　　(bd)</p>
<p>&nbsp;<wbr></p>
<p>　　题目：有关线程的哪些叙述是对的。</p>
<p>&nbsp;<wbr></p>
<p>　　A. 一旦一个线程被创建，它就立即开始运行。</p>
<p>&nbsp;<wbr></p>
<p>　　B. 使用start()方法可以使一个线程成为可运行的，但是它不一定立即开始运行。</p>
<p>&nbsp;<wbr></p>
<p>　　C. 当一个线程因为抢先机制而停止运行，它被放在可运行队列的前面。</p>
<p>&nbsp;<wbr></p>
<p>　　D. 一个线程可能因为不同的原因停止（cease）并进入就绪状态。</p>
<p>&nbsp;<wbr></p>
<p>　　一个新创建的线程并不是自动的开始运行的，必须调用它的start()方法使之将线程放入</p>
<p>可运行态（runnable</p>
<p>state），这只是意味着该线程可为JVM的线程调度程序调度而不是意味着它可以立即运行。</p>
<p>线程的调度是抢先式的，而不是分时间片式的。具有比当前运行线程高优先级的线程可以使当</p>
<p>前线程停止运行而进入就绪状态，不同优先级的线程间是抢先式的，而同级线程间是轮转式的</p>
<p>。一个线程停止运行可以是因为不同原因，可能是因为更高优先级线程的抢占，也可能是因为</p>
<p>调用sleep()方法，而即使是因为抢先而停止也不一定就进入可运行队列的前面，因为同级线</p>
<p>程是轮换式的，它的运行可能就是因为轮换，而它因抢占而停止后只能在轮换队列中排队而不</p>
<p>能排在前面。</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451204">&#167;1.1.9&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 九</a></h3>
<p>Which two CANNOT directly cause a thread to stop executing? (Choose Two)</p>
<p>&nbsp;<wbr></p>
<p>A.Existing from a synchronized block</p>
<p>B.Calling the wait method on an object</p>
<p>C.Calling notify method on an object</p>
<p>D.Calling read method on an InputStream object</p>
<p>E.Calling the SetPriority method on a Thread object</p>
<p>Answer：AC。同55题</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451205">&#167;1.1.10 十</a></h3>
<p>&nbsp;<wbr>public class SyncTest{</p>
<p>&nbsp;<wbr>public static void main(String[] args)&nbsp;<wbr> {</p>
<p>&nbsp;<wbr>final StringBuffer s1= new StringBuffer();</p>
<p>&nbsp;<wbr>final StringBuffer s2= new StringBuffer();</p>
<p>&nbsp;<wbr>new Thread ()&nbsp;<wbr>&nbsp;<wbr> {</p>
<p>&nbsp;<wbr>&nbsp;<wbr> public void run() {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> synchronized(s1) {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> s2.append(&#8220;A&#8221;);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> synchronized(s2) {</p>
<p>&nbsp;<wbr>&nbsp;<wbr> s2.append(&#8220;B&#8221;);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.print(s1);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.print(s2);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr>&nbsp;<wbr> }&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>}.start();</p>
<p>&nbsp;<wbr>new Thread() {</p>
<p>&nbsp;<wbr>&nbsp;<wbr> public void run() {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> synchronized(s2) {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> s2.append(&#8220;C&#8221;);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> synchronized(s1) {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> s1.append(&#8220;D&#8221;);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.print(s2);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.print(s1);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }.start();</p>
<p>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr>}</p>
<p>Which two statements are true? (Choose Two)</p>
<p>A. The program prints &#8220;ABBCAD&#8221;</p>
<p>B. The program prints &#8220;CDDACB&#8221;</p>
<p>C. The program prints &#8220;ADCBADBC&#8221;</p>
<p>D. The output is a non-deterministic point because of a possible deadlock condition</p>
<p>E. The output is dependent on the threading model of the system the program is running on.</p>
<p>Answer：DE</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451206">&#167;1.1.11 十一</a></h3>
<p>What will happen when you attempt to compile and run the following code?</p>
<p>public class Test{&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr> int i = 0;&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr> public static void main(String argv[]) {&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> Test t = new Test();&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> t.myMethod();&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr> }&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr> public void myMethod(){&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> while(true) {&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> try {&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>wait();&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }catch (InterruptedException e) {}&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> i++;&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>}</p>
<p>A. Compile time error, no matching notify within the method.</p>
<p>B. Compile and run but an infinite looping of the while method.</p>
<p>C. Compilation and run without any output.</p>
<p>E. Runtime Exception "IllegalMonitorStatException".</p>
<p>Answer: E</p>
<p>Note: The wait/notify protocol can only be used within code that is synchronized. In this case calling code does not have a lock on the object(not synchronized) and will thus cause an Exception at runtime.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451207">&#167;1.1.12 十二</a></h3>
<p>1.10 What is the result of compiling and executing the following code?</p>
<p>public class ThreadTest extends Thread {&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> public void run() {&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.println("In run");&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> yield();&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.println("Leaving run");&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> public static void main(String args []) {&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> (new ThreadTest()).start();&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>}</p>
<p>A. The code fails to compile in the main() method.</p>
<p>B. The code fails to compile in the run() method.</p>
<p>C. Only the text "In run" will be displayed.</p>
<p>D. The text "In run" followed by "Leaving run" will be displayed.</p>
<p>E. The code compiles correctly, but nothing is displayed.</p>
<p>Answer: D</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451208">&#167;1.1.13 十三</a></h3>
<p>Which of the following will definitely stop a thread from executing?A. wait()B. notify()C. yield()D. suspend()E. sleep()Answer: ACDE</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451209">&#167;1.1.14 十四</a></h3>
<p>Which of the following will definitely stop a thread from executing?</p>
<p>A. wait()</p>
<p>B. notify()</p>
<p>C. yield()</p>
<p>D. suspend()</p>
<p>E. sleep()</p>
<p>Answer: ACDE</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451210">&#167;1.1.15 十五</a></h3>
<p>&nbsp;<wbr>Which of the following statements about threading are true?</p>
<p>A. You can only obtain a mutually exclusive lock on methods in a class that extends Thread or implements runnable.</p>
<p>B. You can obtain a mutually exclusive lock on any object.</p>
<p>C. You can't obtain a mutually exclusive lock on any object.</p>
<p>D. Thread scheduling algorithms are platform dependent.</p>
<p>Answer: BD</p>
<p>8:</p>
<p>Consider the following statement:&nbsp;<wbr>&nbsp;<wbr></p>
<p>Thread myThread = new Thread();</p>
<p>Which of the following statements are true regarding myThread?</p>
<p>A. The thread myThread is now in a runnable state.</p>
<p>B. The thread myThread has a priority of 5.</p>
<p>C. On calling the start() method on myThread, the run method in the Thread class will be executed.</p>
<p>D. On calling the start() method on myThread, the run method in the calling class will be executed.</p>
<p>Answer: C</p>
<p>Note: the priority of myThread will be inherited from the Thread that called the constructor.</p>
<h3><a name="_Toc74451211">&#167;1.1.16 十六</a></h3>
<p>What is the effect of issuing a wait() method on an object？（Mutiple）</p>
<p>1) If a notify() method has already been sent to that object then it has no effect</p>
<p>2) The object issuing the call to wait() will halt until another object sends a notify() or notifyAll() method</p>
<p>3) An exception will be raised</p>
<p>4) The object issuing the call to wait() will be automatically synchronized with any other objects using the receiving object.</p>
<p>ANSWER 1)</p>
<p>10:</p>
<p>Pick all the true statements below.</p>
<p>1) If a thread wants to call wait() on an object, the thread must own that object's lock.</p>
<p>2) There is a method that you can call on an instance of the Thread class that puts the instance to sleep for a specified&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> number of milliseconds.</p>
<p>3) At the moment when a thread is notified, it automatically gets the lock of the object for which it was waiting.</p>
<p>ANSWER 1</p>
<p>&nbsp;<wbr></p>
</div>
<img src ="http://www.blogjava.net/balajinima/aggbug/298538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:43 <a href="http://www.blogjava.net/balajinima/articles/298538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第八部分：在java.lang包中的基础类</title><link>http://www.blogjava.net/balajinima/articles/298539.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:43:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298539.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298539.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298539.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298539.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298539.html</trackback:ping><description><![CDATA[<p align="left">第八部分：在java.lang包中的基础类</p>
<ul type="disc">
    <li>能够应用Math类中的abs,ceil,floor,max,min,random,round,sin,cos,tan,sqrt方法。
    <li>正确理解String类不可改变的意义。
    <li>当执行一段程序，中间包含有wrapper类的一个实例，知道它运行的前提条件运行结果。能用下面wrapper类（例如Integer,Double,等等）的方法来写程序： </li>
</ul>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> doublevalue</p>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> floatvalue</p>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> intvalue</p>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> longvalue</p>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> parseXxx</p>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> getXxx</p>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> toString</p>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> toHexString</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:43 <a href="http://www.blogjava.net/balajinima/articles/298539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第六部分：覆盖，重载，运行时期类型及其面向对象</title><link>http://www.blogjava.net/balajinima/articles/298537.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:42:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298537.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298537.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298537.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298537.html</trackback:ping><description><![CDATA[<p align="left">第六部分：覆盖，重载，运行时期类型及其面向对象</p>
<ul type="disc">
    <li>知道面向对象设计中封装的好处以及如何实现，能知道is&nbsp;<wbr>a和has&nbsp;<wbr>a的意义。
    <li>能正确使用覆盖和重载的方法，能正确调用父类或重载的构造方法(constructor)，知道调用这些方法后的结果。
    <li>能正确实例化类或内部类 </li>
</ul>
<div>
<h3><a name="_Toc74451188">&#167;1.1.1&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 一</a></h3>
<p>3. What will happen when you attempt to compile and run the following code?</p>
<p>class MyParent</p>
<p>{</p>
<p>int x, y;</p>
<p>MyParent(int x, int y)</p>
<p>{</p>
<p>this.x = x;</p>
<p>this.y = y;</p>
<p>}</p>
<p>public int addMe(int x, int y)</p>
<p>{</p>
<p>return this.x + x + y + this.y;</p>
<p>}</p>
<p>public int addMe(MyParent myPar)</p>
<p>{</p>
<p>return addMe(myPar.x, myPar.y);</p>
<p>}</p>
<p>}</p>
<p>class MyChild extends MyParent</p>
<p>{</p>
<p>int z;</p>
<p>MyChild (int x, int y, int z)</p>
<p>{</p>
<p>super(x,y);</p>
<p>this.z = z;</p>
<p>}</p>
<p>public int addMe(int x, int y, int z)</p>
<p>{</p>
<p>return this.x + x + this.y + y + this.z + z;</p>
<p>}</p>
<p>public int addMe(MyChild myChi)</p>
<p>{</p>
<p>return addMe(myChi.x, myChi.y, myChi.z);</p>
<p>}</p>
<p>public int addMe(int x, int y)</p>
<p>{</p>
<p>return this.x + x + this.y + y;</p>
<p>}</p>
<p>}</p>
<p>public class MySomeOne</p>
<p>{</p>
<p>public static void main(String args[])</p>
<p>{</p>
<p>MyChild myChi = new MyChild(10, 20, 30);</p>
<p>MyParent myPar = new MyParent(10, 20);</p>
<p>int x = myChi.addMe(10, 20, 30);</p>
<p>int y = myChi.addMe(myChi);</p>
<p>int z = myPar.addMe(myPar);</p>
<p>System.out.println(x + y + z);</p>
<p>}</p>
<p>}</p>
<p>&nbsp;<wbr></p>
<p>Choices:</p>
<p>a. 300</p>
<p>b. 240</p>
<p>c. 120</p>
<p>d. 180</p>
<p>e. Compilation error</p>
<p>f. None of the above</p>
<p>――――――――――――</p>
<p>A is the correct choice. In the code, MyChild class overrides the addMe(int x, int y) method of the MyParent class. And in both the MyChild and MyParent class, addMe() method is overloaded. There is no compilation error anywhere in the above code. On execution, first, the object of MyChild class will be constructed. Please note that there is a super() call from the constructor of MyChild class, which will call the constructor of MyParent class. This will cause the value of z variable of MyChild class to be 30 and x, y variables of MyParent class will become 10 and 20 respectively. The next statement will again call the constructor of MyParent class with same x and y values. This is followed by execution of addMe() method of MyChild class with x as 10, y as 20 and z as 30. Also x and y are inherited by MyChild class from the MyParent class. Thus in the addMe() method of the MyChild class, the value of this.x will be 10, this.y will be 20 and this.z will be 30. The return value of this method will be "10 + 10 + 20 + 20 + 30 + 30", which is equal to 120. Thus x will become 120. This is followed by the invocation of the other addMe() method which takes object reference of the MyChild class. From this method, the method which was called earlier is invoked. This call is exactly the same as the earlier one. Thus the value of y will also be 120 like x. Now the addMe() method of MyParent class is invoked. This method invokes another addMe() method of the same class. Its equivalent to the invocation of addMe(int x, int y) method with x as 10 and y as 20. Also the value of instance variables x and y of My Parent class is 10 and 20 respectively. The value of z will be evaluated to "10 + 10 + 20 + 20", which is equal to 60. Thus the value of x, y and z after all the invocations will be 120, 120 and 60 respectively. As a result of this finally, "120 + 120 + 60" which is equal to 300 will be printed. Thus A is the correct choice.</p>
<p align="left">&nbsp;<wbr></p>
<h3><a name="_Toc74451189">&#167;1.1.2&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 二</a></h3>
<p>Given the code below, and making no other changes, which access modifiers</p>
<p>(public, protected or private) can legally be placed before myMethod() on line 3?</p>
<p>If line 3 is left as it is, which keywords can legally be placed before myMethod</p>
<p>on line 8?</p>
<p>1.class HumptyDumpty</p>
<p>2.{</p>
<p>3.void myMethod() {}</p>
<p>4.}</p>
<p>5.</p>
<p>6.class HankyPanky extends HumptyDumpty</p>
<p>7.{</p>
<p>8.void myMethod() {}</p>
<p>9.}</p>
<div>
<p>Choices:</p>
<p>a. private or nothing(i.e. leaving it as it is) on line 3.</p>
<p>Nothing(i.e. leaving it as it is) or protected or public</p>
<p>on line 8.</p>
<p>b. public or protected on line 3. private or nothing(i.e. leaving it</p>
<p>as it is) on line 8.</p>
<p>c. nothing(i.e. leaving it as it is) or protected or public on</p>
<p>line 3. private or nothing(i.e. leaving it as it is) on line 8.</p>
<p>d. None of the above.</p>
</div>
<p>A is correct. The basic principle is that a method cannot be overridden to be more private. Since the method is being overridden to be friendly(default modifier) it can only be private or friendly in the superclass. Secondly if the method in superclass is left as it is(i.e. friendly access) the method in subclass can be friendly, protected or public.</p>
<h3><a name="_Toc74451190">&#167;1.1.3&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 三</a></h3>
<p>What results from the following code?</p>
<p>1.class MyClass</p>
<p>2.{</p>
<p>3.void myMethod(int i) {System.out.println("int version");}</p>
<p>4.void myMethod(String s) {System.out.println("String version");}</p>
<p>5.public static void main(String args[])</p>
<p>6.{</p>
<p>7.MyClass obj = new MyClass();</p>
<p>8.char ch = 'c';</p>
<p>9.obj.myMethod(ch);</p>
<p>10.}</p>
<p>11.}</p>
<p>Choices:</p>
<p>a. Line 4 will not compile as void methods can't be overridden.</p>
<p>b. An exception at line 9.</p>
<p>c. Line 9 will not compile as there is no version of myMethod which takes a char as argument.</p>
<p>d. The code compiles and produces output: int version.</p>
<p>e. The code compiles and produces output: String version.</p>
<p>――――――――――</p>
<p>D is correct. A is incorrect as void methods can be overridden without any problem. B is incorrect as char ch declaration is valid. C is incorrect as char type in java is internally stored as integer and there is a method which takes int as an input. D is correct, on line 9 char ch is widened to an int and passed to int version of the myMethod(). E is incorrect as int version of myMethod() is called.</p>
<h3><a name="_Toc74451191">&#167;1.1.4&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 四</a></h3>
<p>What is displayed when the following is executed?</p>
<p>class Parent</p>
<p>{</p>
<p>private void method1()</p>
<p>{</p>
<p>System.out.println("Parent's method1()");</p>
<p>}</p>
<p>public void method2()</p>
<p>{</p>
<p>System.out.println("Parent's method2()");</p>
<p>method1();</p>
<p>}</p>
<p>}</p>
<p>class Child extends Parent</p>
<p>{</p>
<p>public void method1()</p>
<p>{</p>
<p>System.out.println("Child's method1()");</p>
<p>}</p>
<p>public static void main(String args[])</p>
<p>{</p>
<p>Parent p = new Child();</p>
<p>p.method2();</p>
<p>}</p>
<p>}</p>
<p>Choices:</p>
<p>a. Compile time error</p>
<p>b. Run time error</p>
<p>c. prints : Parent's method2()</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> Parent's method1()</p>
<p>d. prints : Parent's method2()</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> Child's method1()</p>
<p align="left">―――――――</p>
<p>C is correct. The code will compile without any error and also will not give any run time error. The variable p refers to the Child class object. The statement p.method2() on execution will first look for method2() in Child class. Since there is no method2() in child class, the method2() of Parent class will be invoked and thus "Parent's method2()" will be printed. Now from the method2() , there is a call to method1(). Please note that method1() of Parent class is private, because of which the same method (method1() of Parent class) will be invoked. Had this method(method1() of Parent class) been public/protected/friendly (default), Child's class method1() would be called. Thus C is correct answer.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451192">&#167;1.1.5&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 五</a></h3>
<p>What is displayed when the following is executed?</p>
<p>class Parent{</p>
<p>private void method1(){</p>
<p>System.out.println("Parent's method1()");</p>
<p>}</p>
<p>public void method2(){</p>
<p>System.out.println("Parent's method2()");</p>
<p>method1();</p>
<p>}</p>
<p>}</p>
<p>class Child extends Parent{</p>
<p>public void method1(){</p>
<p>System.out.println("Child's method1()");</p>
<p>}</p>
<p>public static void main(String args[]){</p>
<p>Parent p = new Child();</p>
<p>p.method2();</p>
<p>}</p>
<p>}</p>
<p>&nbsp;<wbr></p>
<p>A. compile time error</p>
<p>B. run time error</p>
<p>C. prints: parent&#8217;s method2()&nbsp;<wbr> parent&#8217;s method1()</p>
<p>D. prints: parent&#8217;s method2()&nbsp;<wbr> child&#8217;s method1()</p>
<p>&nbsp;<wbr></p>
<p>C is correct. The code will compile without any error and also will not give any run time error. The variable p refers to the Child class object. The statement p.method2() on execution will first look for method2() in Child class. Since there is no method2() in child class, the method2() of Parent class will be invoked and thus "Parent's method2()" will be printed. Now from the method2() , there is a call to method1(). Please note that method1() of Parent class is private, because of which the same method (method1() of Parent class) will be invoked. Had this method(method1() of Parent class) been public/protected/friendly (default), Child's class method1() would be called. Thus C is correct answer.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451193">&#167;1.1.6&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 六</a></h3>
<p>　　1) class Person {</p>
<p>&nbsp;<wbr></p>
<p>　　2) public void printValue(int i, int j) { }</p>
<p>&nbsp;<wbr></p>
<p>　　3) public void printValue(int i){ }</p>
<p>&nbsp;<wbr></p>
<p>　　4) }</p>
<p>&nbsp;<wbr></p>
<p>　　5) public class Teacher extends Person {</p>
<p>&nbsp;<wbr></p>
<p>　　6) public void printValue() { }</p>
<p>&nbsp;<wbr></p>
<p>　　7) public void printValue(int i) {}</p>
<p>&nbsp;<wbr></p>
<p>　　8) public static void main(String args[]){</p>
<p>&nbsp;<wbr></p>
<p>　　9) Person t = new Teacher();</p>
<p>&nbsp;<wbr></p>
<p>　　10) t.printValue(10);</p>
<p>&nbsp;<wbr></p>
<p>　　11) }</p>
<p>&nbsp;<wbr></p>
<p>　　12) }</p>
<p>&nbsp;<wbr></p>
<p>　　Which method will the statement on line 10 call?</p>
<p>　　A. on line 2</p>
<p>&nbsp;<wbr></p>
<p>　　B. on line 3</p>
<p>&nbsp;<wbr></p>
<p>　　C. on line 6</p>
<p>&nbsp;<wbr></p>
<p>　　D. on line 7</p>
<p>　　翻译</p>
<p>　　第十行的声明将调用哪些方法。</p>
<p>&nbsp;<wbr></p>
<p>　　答案　D</p>
<p>&nbsp;<wbr></p>
<p>　　解析　变量t是一个Person对象，但是它是用Teacher实例化的，这个问题涉及到java的</p>
<p>编译时多态和运行时多态的问题，就编译时多态来说，t实际上是一个Person类，这涉及到类</p>
<p>型的自动转换（将一个子类的实例赋值给一个父类的变量是不用进行强制类型转换，反之则需</p>
<p>要进行强制类型转换，而且被赋值的变量实际上应该是一个子类的对象），如果对t调用了子</p>
<p>类中新增的方法则造成编译时错误编译将不能通过，而在运行时，运行时系统将根据t实际指</p>
<p>向的类型调用对应的方法，对于本例来说，t.print(10)将调用t实际指向的Teacher类的对应</p>
<p>方法。在java中，可以用一个子类的实例实例化父类的一个变量，而变量在编译时是一个父类</p>
<p>实例，在运行时可能是一个子类实例。</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451194">&#167;1.1.7&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 七</a></h3>
<p>35、public class Parent {</p>
<p>　　public int addValue( int a, int b) {</p>
<p>　　int s;</p>
<p>　　s = a+b;</p>
<p>　　return s;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　class Child extends Parent {</p>
<p>&nbsp;<wbr></p>
<p>　　}</p>
<p>　　Which methods can be added into class Child?</p>
<p>　　A. int addValue( int a, int b ){// do something...}</p>
<p>&nbsp;<wbr></p>
<p>　　B. public void addValue (){// do something...}</p>
<p>&nbsp;<wbr></p>
<p>　　C. public int addValue( int a ){// do something...}</p>
<p>&nbsp;<wbr></p>
<p>　　D. public int addValue( int a, int b )throws MyException {//do</p>
<p>something...}</p>
<p>&nbsp;<wbr></p>
<p>　　(bc)</p>
<p>&nbsp;<wbr></p>
<p>　　题目：哪些方法可以加入类Child中。</p>
<p>&nbsp;<wbr></p>
<p>　　此题涉及方法重载（overload），方法重写（override）以及类派生时方法重写的规则</p>
<p>。方法重载的规则是：一、参数列表必须不同，个数的不同完全可以，如果个数相同则参数类</p>
<p>型的不同不能引起歧意，例如int</p>
<p>和long,float和double就不能作为唯一的类型不同；二、返回值可以不同，但是不能是重载</p>
<p>时唯一的不同点（这点和c++中不同，c++中返回类型必须一致）。方法重写发生在类继承时，</p>
<p>子类可以重写一个父类中已有的方法，必须在返回类型和参数列表一样时才能说是重写，否则</p>
<p>就是重载，java中方法重写的一个重要而且容易被忽略的规则是重写的方法的访问权限不能比</p>
<p>被重写的方法的访问权限低！重写的另一个规则是重写的方法不能比被重写的方法抛弃(thro</p>
<p>ws)更多种类的异常，其抛弃的异常只能少，或者是其子类，不能以抛弃异常的个数来判断种</p>
<p>类，而应该是异常类层次结果上的种类。此题中答案a的错误就是重写的访问权限比被重写的</p>
<p>方法的低，而b,c都属于重载，d的错误在于比被重写的方法抛弃了更多种类的异常。</p>
</div>
<img src ="http://www.blogjava.net/balajinima/aggbug/298537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:42 <a href="http://www.blogjava.net/balajinima/articles/298537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第五部分：操作与赋值</title><link>http://www.blogjava.net/balajinima/articles/298536.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:41:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298536.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298536.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298536.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298536.html</trackback:ping><description><![CDATA[<p align="left">第五部分：操作与赋值</p>
<ul type="disc">
    <li>能知道各种操作符（包括赋值操作符和intanceof操作符）应用于不同类型的结果。
    <li>知道String，Boolean和类使用equals()方法后的结果。
    <li>知道当对已经知道值的变量进行&amp;,|,&amp;&amp;,||操作时，哪些操作数被运算了，表达式最终的结果是怎样的。
    <li>知道对象和原始类型数据传入方法后，在方法内部进行赋值或其它修改操作的结果。 </li>
</ul>
<div>
<h3>&#167;1.1.1&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 一</h3>
<p>Which of the following lines will print false?</p>
<p>1.public class MyClass</p>
<p>2.{</p>
<p>3.static String s1 = "I am unique!";</p>
<p>4.public static void main(String args[])</p>
<p>5.{</p>
<p>6.String s2 = "I am unique!";</p>
<p>7.String s3 = new String(s1);</p>
<p>8.System.out.println(s1 == s2);</p>
<p>9.System.out.println(s1.equals(s2));</p>
<p>10.System.out.println(s3 == s1);</p>
<p>11.System.out.println(s3.equals(s1));</p>
<p>12.System.out.println(TestClass.s4 == s1);</p>
<p>13.}</p>
<p>14.}</p>
<p>15.</p>
<p>16.class TestClass</p>
<p>17.{</p>
<p>18.static String s4 = "I am unique!";</p>
<p>19.}</p>
<p>Choices:</p>
<p>a. Lines 10 and 12</p>
<p>b. Line 12 only</p>
<p>c. Line 8 and 10</p>
<p>d. None of these</p>
<p align="left">――――――――――</p>
<p align="left">D is correct. Only line 10 will print false. Strings are immutable objects. That is, a string is read only once the string has been created and initialized, and Java optimizes handling of string literals; only one anonymous string object is shared by all string literals with the same contents. Hence in the above code the strings s1, s2 and s4 refer to the same anonymous string object, initialized with the character string: "I am unique!". Thus s1 == s2 and TestClass.s4 will both return true and obviously s1.equals(s2) will return true. But creating string objects using the constructor String(String s) creates a new string, hence s3 == s1 will return false even though s3.equals(s1) will return true because s1 and s3 are referring to two different string objects whose contents are same.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451179">&#167;1.1.2&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 二</a></h3>
<p>What is displayed when the following code is compiled and executed?</p>
<p>String s1 = new String("Test");</p>
<p>String s2 = new String("Test");</p>
<p>if (s1==s2)</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>System.out.println("Same");</p>
<p>if (s1.equals(s2))</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>System.out.println("Equals");</p>
<p>Choices:</p>
<p>a. Same</p>
<p>Equals</p>
<p>b. Equals</p>
<p>c. Same</p>
<p>d. The code compiles, but nothing is displayed upon execution.</p>
<p>e. The code fails to compile.</p>
<div>
<p align="left">&nbsp;<wbr></p>
</div>
<p align="left">B is correct. Here s1 and s2 are two different object references, referring to different objects in memory. Please note that operator == checks for the memory address of two object references being compared and not their value. The "equals()" method of String class compares the values of two Strings. Thus s1==s2 will return "false" while s1.equals(s2) will return "true". Thus only "Equals" will be printed.</p>
<h3>&#167;1.1.3&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 三</h3>
<p>Given the following code, what will be the output?</p>
<p>class Value</p>
<p>{</p>
<p>public int i = 15;</p>
<p>}</p>
<p>public class Test</p>
<p>{</p>
<p>public static void main(String argv[])</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> Test t = new Test();</p>
<p>t.first();</p>
<p>&nbsp;<wbr> &nbsp;<wbr>}</p>
<p>public void first()</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> int i = 5;</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> Value v = new Value();</p>
<p>v.i = 25;</p>
<p>second(v, i);</p>
<p>&nbsp;<wbr> &nbsp;<wbr> System.out.println(v.i);</p>
<p>}</p>
<p>public void second(Value v, int i)</p>
<p>{</p>
<p>i = 0;</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> v.i = 20;</p>
<p>Value val = new Value();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> v = &nbsp;<wbr>val;</p>
<p>&nbsp;<wbr> &nbsp;<wbr> System.out.println(v.i + " " + i);</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr></p>
<p>}</p>
<p>}</p>
<p>Choices:</p>
<p>a. 15 0</p>
<p>&nbsp;<wbr> &nbsp;<wbr>20</p>
<p>b. 15 0</p>
<p>&nbsp;<wbr> &nbsp;<wbr>15</p>
<p>c. 20 0</p>
<p>&nbsp;<wbr> 20</p>
<p>d. 0 15</p>
<p>&nbsp;<wbr> 20</p>
<p align="left">―――――――――――――――</p>
<p align="left">A is correct. When we pass references in Java what actually gets passed is the value of that reference (i.e. memory address of the object being referenced and not the actual object referenced by that reference) and it gets passed as value (i.e a copy of the reference is made). Now when we make changes to the object referenced by that reference it reflects on that object even outside of the method being called but any changes made to the reference itself is not reflected on that reference outside of the method which is called. In the example above when the reference v is passed from method first() to second() the value of v is passed. When we assign the value val to v it is valid only inside the method second() and thus inside the method second() what gets printed is 15 (initial value of i in the object referenced by val), then a blank space and then 0 (value of local variable i). After this when we return to the method first() v actually refers to the same object to which it was referring before the method second() was called, but one thing should be noted here that the value of i in that object (referred by v inside the method first()) was changed to 20 in the method second() and this change does reflect even outside the method second(), hence 20 gets printed in the method first(). Thus overall output of the code in consideration is 15 0 20</p>
<p>&nbsp;<wbr></p>
<h3>&#167;1.1.4&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 四</h3>
<p>&nbsp;<wbr>What will happen when you attempt to compile and run the following code?</p>
<p>interface MyInterface</p>
<p>{</p>
<p>}</p>
<p>public class MyInstanceTest implements MyInterface</p>
<p>{</p>
<p>static String s;</p>
<p>public static void main(String args[])</p>
<p>{</p>
<p>MyInstanceTest t = new MyInstanceTest();</p>
<p>if(t instanceof MyInterface)</p>
<p>{</p>
<p>System.out.println("I am true interface");</p>
<p>}</p>
<p>else</p>
<p>{</p>
<p>System.out.println("I am false interface");</p>
<p>}</p>
<p>if(s instanceof String)</p>
<p>{</p>
<p>System.out.println("I am true String");</p>
<p>}</p>
<p>else</p>
<p>{</p>
<p>System.out.println("I am false String");</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>Choices:</p>
<p>a. Compiletime error</p>
<p>b. Runtime error</p>
<p>c. Prints : "I am true interface" followed by " I am true String"</p>
<p>d. Prints : "I am false interface" followed by " I am false String"</p>
<p>e. Prints : "I am true interface" followed by " I am false String"</p>
<p>f. Prints : "I am false interface" followed by " I am true String"</p>
<p>――――――――――――</p>
<p>E is the correct choice. The "instanceof" operator tests the class of an object at runtime. It returns true if the class of the left-hand argument is the same as, or is some subclass of, the class specified by the right-hand operand. The right-hand operand may equally well be an interface. In such a case, the test determines if the object at left-hand argument implements the specified interface. In the above case there will not be any compiletime or runtime error. The result of "t instance of MyInterface" will be true as "t" is the object of MyInstanceTest class which implements the MyInstance interface. But the result of "s instanceof String" will be false as "s" refers to null. Thus the output of the above program will be : "I am true interface" followed by " I am false String". Thus choice E is correct and others are incorrect.</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<h3>&#167;1.1.5&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>五</h3>
<p>What will happen when you attempt to compile and run the following code snippet?</p>
<p>String str = "Java";</p>
<p>StringBuffer buffer = new StringBuffer(str);</p>
<p>if(str.equals(buffer)){</p>
<p>System.out.println("Both are equal");</p>
<p>}else{</p>
<p>System.out.println("Both are not equal");</p>
<p>}</p>
<p>A. it will print &#8211; both are not equal</p>
<p>B. it will print &#8211; both are equal</p>
<p>C. compile time error</p>
<p>D. Runtime error</p>
<p>&nbsp;<wbr></p>
<p>A is the correct choice. The equals method overridden in String class returns true if and only if the argument is not null and is a String object that represents the same sequence of characters as this String object. Hence, though the contents of both str and buffer contain "Java", the str.equals(buffer) call results in false.</p>
<p>The equals method of Object class is of form -public boolean equals(Object anObject). Hence, comparing objects of different classes will never result in compile time or runtime error.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451183">&#167;1.1.6&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 六</a></h3>
<p>10. Which of the following statements are true?</p>
<p>　　A. The equals() method determines if reference values refer to the same</p>
<p>object.</p>
<p>&nbsp;<wbr></p>
<p>　　B. The == operator determines if the contents and type of two separate</p>
<p>objects match.</p>
<p>&nbsp;<wbr></p>
<p>　　C. The equals() method returns true only when the contents of two</p>
<p>objects match.</p>
<p>&nbsp;<wbr></p>
<p>　　D. The class File overrides equals() to return true if the contents and</p>
<p>type of two separate objects match.</p>
<p>　　翻译</p>
<p>　　下面的哪些叙述为真。</p>
<p>　　A. equals()方法判定引用值是否指向同一对象。</p>
<p>&nbsp;<wbr></p>
<p>　　B. == 操作符判定两个分立的对象的内容和类型是否一致。</p>
<p>&nbsp;<wbr></p>
<p>　　C. equals()方法只有在两个对象的内容一致时返回true。</p>
<p>&nbsp;<wbr></p>
<p>　　D. 类File重写方法equals()在两个分立的对象的内容和类型一致时返回true。</p>
<p>&nbsp;<wbr></p>
<p>　　答案　A,D</p>
<p>　</p>
<p>　　解析　严格来说这个问题的答案是不确定的，因为equals()方法是可以被重载的，但是</p>
<p>按照java语言的本意来说：如果没有重写（override）新类的equals()，则该方法和</p>
<p>==</p>
<p>操作符一样在两个变量指向同一对象时返回真，但是java推荐的是使用equals()方法来判断</p>
<p>两个对象的内容是否一样，就像String类的equals()方法所做的那样：判定两个String对象的</p>
<p>内容是否相同，而==操作符返回true的唯一条件是两个变量指向同一对象。从这个意义上来说</p>
<p>选择给定的答案。从更严格的意义来说正确答案应该只有d。</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451184">&#167;1.1.7&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 七</a></h3>
<p>Use the operators "&lt;&lt;", "&gt;&gt;", which statements are true?</p>
<p>　　A. 0000 0100 0000 0000 0000 0000 0000 0000&lt;&lt;5 gives</p>
<p>&nbsp;<wbr>&nbsp;<wbr> 　　1000 0000 0000 0000 0000 0000 0000 0000</p>
<p>&nbsp;<wbr></p>
<p>　　B. 0000 0100 0000 0000 0000 0000 0000 0000&lt;&lt;5 gives</p>
<p>&nbsp;<wbr>&nbsp;<wbr> 　　1111 1100 0000 0000 0000 0000 0000 0000</p>
<p>&nbsp;<wbr></p>
<p>　　C. 1100 0000 0000 0000 0000 0000 0000 0000&gt;&gt;5 gives</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 　1111 1110 0000 0000 0000 0000 0000 0000</p>
<p>&nbsp;<wbr></p>
<p>　　D. 1100 0000 0000 0000 0000 0000 0000 0000&gt;&gt;5 gives</p>
<p>&nbsp;<wbr>&nbsp;<wbr> 　　0000 0110 0000 0000 0000 0000 0000 0000</p>
<p>　　翻译</p>
<p>　　使用"&lt;&lt;"和 "&gt;&gt;"操作符的哪些陈述是对的。</p>
<p>&nbsp;<wbr></p>
<p>　　答案　A,C</p>
<p>　　</p>
<p>　　解析　Java的移位操作符一共有三种，分别是&#8221;&gt;&gt;&#8221;,&#8221;&gt;&gt;&gt;&#8221;,&#8221;&lt;&lt;&#8221;,执行的操作分别</p>
<p>是有符号右移，无符号右移，左移，有符号右移的意思是说移入的最高位和原最高符号位相同</p>
<p>，无符号右移是移入位始终补零，左移时最低位始终补零，最高位被舍弃。移位操作符另一个</p>
<p>非常值得注意的特点是其右操作数是取模运算的，意思是说对于一个int型数据而言，对它移</p>
<p>位32位的结果是保持不变而非变成零，即：a&gt;&gt;32的结果是a而不是0，同理，对long型数是对</p>
<p>右操作数取64的模，a&gt;&gt;64==a；还有一点需要注意的是移位操作符&#8221;&gt;&gt;&gt;&#8221;只对int型和long型</p>
<p>有效，对byte或者short的操作将导致自动类型转换，而且是带符号的。</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451185">&#167;1.1.8&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 八</a></h3>
<p>　　String s= "hello";</p>
<p>　　String t = "hello";</p>
<p>　　char c[] = {'h','e','l','l','o'} ;</p>
<p>　　Which return true?</p>
<p>　　A. s.equals(t);</p>
<p>&nbsp;<wbr></p>
<p>　　B. t.equals(c);</p>
<p>&nbsp;<wbr></p>
<p>　　C. s==t;</p>
<p>&nbsp;<wbr></p>
<p>　　D. t.equals(new String("hello"));</p>
<p>&nbsp;<wbr></p>
<p>　　E. t==c.</p>
<p>&nbsp;<wbr></p>
<p>　　(acd)</p>
<p>&nbsp;<wbr></p>
<p>　　题目：哪些返回true。</p>
<p>&nbsp;<wbr></p>
<p>　　这个在前面第10题的equals()方法和==操作符的讨论中论述过。==操作符比较的是操作</p>
<p>符两端的操作数是否是同一个对象，而String的equals()方法比较的是两个String对象的内容</p>
<p>是否一样，其参数是一个String对象时才有可能返回true，其它对象都返回假。需要指出的是</p>
<p>由于s和t并非使用new创建的，他们指向内存池中的同一个字符串常量，因此其地址实际上是</p>
<p>相同的（这个可以从反编译一个简单的测试程序的结果得到，限于篇幅不列出测试代码和反编</p>
<p>译的分析），因此答案c也是正确的。</p>
<h3><a name="_Toc74451186">&#167;1.1.9&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 九</a></h3>
<p>Class Teacher and Student are subclass of class Person.</p>
<p>　　Person p;</p>
<p>　　Teacher t;</p>
<p>　　Student s;</p>
<p>　　p, t and s are all non-null.</p>
<p>　　if(t instanceof Person) { s = (Student)t; }</p>
<p>　　What is the result of this sentence?</p>
<p>　　A. It will construct a Student object.</p>
<p>&nbsp;<wbr></p>
<p>　　B. The expression_r is legal.</p>
<p>&nbsp;<wbr></p>
<p>　　C. It is illegal at compilation.</p>
<p>&nbsp;<wbr></p>
<p>　　D. It is legal at compilation but possible illegal at runtime.</p>
<p>&nbsp;<wbr></p>
<p>　　(c)</p>
<p>&nbsp;<wbr></p>
<p>　　题目：类Teacher和Student都是类Person的子类</p>
<p>　　&#8230;</p>
<p>　　p,t和s都是非空值</p>
<p>　　&#8230;</p>
<p>　　这个语句导致的结果是什么</p>
<p>&nbsp;<wbr></p>
<p>　　A. 将构造一个Student对象。</p>
<p>&nbsp;<wbr></p>
<p>　　B. 表达式合法。</p>
<p>&nbsp;<wbr></p>
<p>　　C. 编译时非法。</p>
<p>&nbsp;<wbr></p>
<p>　　D. 编译时合法而在运行时可能非法。</p>
<p>&nbsp;<wbr></p>
<p>　　instanceof操作符的作用是判断一个变量是否是右操作数指出的类的一个对象，由于ja</p>
<p>va语言的多态性使得可以用一个子类的实例赋值给一个父类的变量，而在一些情况下需要判断</p>
<p>变量到底是一个什么类型的对象，这时就可以使用instanceof了。当左操作数是右操作数指出</p>
<p>的类的实例或者是子类的实例时都返回真，如果是将一个子类的实例赋值给一个父类的变量，</p>
<p>用instanceof判断该变量是否是子类的一个实例时也将返回真。此题中的if语句的判断没有问</p>
<p>题，而且将返回真，但是后面的类型转换是非法的，因为t是一个Teacher对象，它不能被强制</p>
<p>转换为一个Student对象，即使这两个类有共同的父类。如果是将t转换为一个Person对象则可</p>
<p>以，而且不需要强制转换。这个错误在编译时就可以发现，因此编译不能通过。</p>
<p>&nbsp;<wbr></p>
</div>
<img src ="http://www.blogjava.net/balajinima/aggbug/298536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:41 <a href="http://www.blogjava.net/balajinima/articles/298536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第四部分：语言基础</title><link>http://www.blogjava.net/balajinima/articles/298535.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:40:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298535.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298535.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298535.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298535.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298535.html</trackback:ping><description><![CDATA[<p align="left">第四部分：语言基础</p>
<ul type="disc">
    <li>能正确声明包、import、类（包括内部类）、接口、方法（包括用于开始一个类的执行的main方法）、变量，并正确使用修饰符。
    <li>能够正确使用实现了接口的类，包括java.lang.Runnable接口或题目中指定的接口。
    <li>知道命令行参数是如何传递给类的main方法的。
    <li>知道哪些是JAVA的合法keyword。注意：考试中不会出现要你解释keyword和各种常数这种深奥的问题。
    <li>明白如果没有显式地赋值，各种变量或者数组的默认值是什么。
    <li>掌握所有原始数据类型的取值范围，如何声明各种数据类型。 </li>
</ul>
<div>
<h3><a name="_Toc74451167">&#167;1.1.1&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 一</a></h3>
<p>1. What will happen when you attempt to compile and run the following code?</p>
<p>public class Static</p>
<p>{</p>
<p>static</p>
<p>{</p>
<p>int x = 5;</p>
<p>}</p>
<p>static int x,y;</p>
<p>public static void main(String args[])</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>x--;</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>myMethod();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>System.out.println(x + y + ++x);</p>
<p>}</p>
<p>public static void myMethod()</p>
<p>{</p>
<p>y = x++ + ++x;</p>
<p>}</p>
<p>}</p>
<p>Choices:</p>
<p>a. Compiletime error</p>
<p>b. prints : 1</p>
<p>c. prints : 2</p>
<p>d. prints : 3</p>
<p>e. prints : 7</p>
<p>f. prints : 8</p>
<p>――――――――――――――――――――</p>
<p>1) D is the correct choice. The above code will not give any compilation error. Note that "Static" is a valid class name. Thus choice A is incorrect. In the above code, on execution, first the static variables (x and y) will be initialized to 0. Then static block will be called and finally main() method will be called. The execution of static block will have no effect on the output as it declares a new variable (int x). The first statement inside main (x--) will result in x to be -1. After that myMethod() will be executed. The statement "y = x++ + ++x;" will be evaluated to y = -1 + 1 and x will become 1. In case the statement be "y =++x + ++x", it would be evaluated to y = 0 + 1 and x would become 1. Finally when System.out is executed "x + y + ++x" will be evaluated to "1 + 0 + 2" which result in 3 as the output. Thus choice D is correct.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451168">&#167;1.1.2&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 二</a></h3>
<p>Considering the following code, Which variables may be referenced correctly at line 12?</p>
<p>1.public class Outer</p>
<p>2.{</p>
<p>3.public int a = 1;</p>
<p>4.private int b = 2;</p>
<p>5.public void method(final int c)</p>
<p>6.{</p>
<p>7.int d = 3;</p>
<p>8.class Inner</p>
<p>9.{</p>
<p>10.private void iMethod(int e)</p>
<p>11. {</p>
<p>12.</p>
<p>13.}</p>
<p>14.}</p>
<p>15.}</p>
<p>16.}</p>
<p>Choices:</p>
<p>a. a</p>
<p>b. b</p>
<p>c. c</p>
<p>d. d</p>
<p>e. e</p>
<p>A, B, C and E are correct. Since Inner is not a static inner class, it has a reference to an enclosing object, and all the variables of that object are accessible. Therefore A and B are correct, even if b is private. Variables in the enclosing method are only accessible when they are marked as final hence c is accessible but not d. E is obviously correct as it is a parameter to the method containing line 12 itself.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451169">&#167;1.1.3&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 三</a></h3>
<p>What will be the result of executing the following code?</p>
<p>// Filename; SuperclassX.java</p>
<p>package packageX;</p>
<p>public class SuperclassX</p>
<p>{</p>
<p>protected void superclassMethodX()</p>
<p>{</p>
<p>}</p>
<p>int superclassVarX;</p>
<p>}</p>
<p>&nbsp;<wbr></p>
<p>// Filename SubclassY.java</p>
<p>1.package packageX.packageY;</p>
<p>2.</p>
<p>3.public class SubclassY extends SuperclassX</p>
<p>4.{</p>
<p>5.SuperclassX objX = new SubclassY();</p>
<p>6.SubclassY objY = new SubclassY();</p>
<p>7.void subclassMethodY()</p>
<p>8.{</p>
<p>9.objY.superclassMethodX();</p>
<p>10.int i;</p>
<p>11.i = objY.superclassVarX;</p>
<p>12.}</p>
<p>13.}</p>
<p>Choices:</p>
<p>a.Compilation error at line 5</p>
<p>b. Compilation error at line 9</p>
<p>c. Runtime exception at line 11</p>
<p>d. None of these</p>
<p>――――――――</p>
<p>D is correct. When no access modifier is specified for a member, it is only accessible by another class in the package where its class is defined. Even if its class is visible in another package, the member is not accessible there. In the question above the variable superclassVarX has no access modifier specified and hence it cannot be accessed in the packageY even though the class SuperclassX is visible and the protected method superclassMethodX() can be accessed. Thus the compiler will raise an error at line 11.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451170">&#167;1.1.4&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 四</a></h3>
<p>&nbsp;<wbr>Consider the class hierarchy shown below:</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>--------------------------------------------------------------------</p>
<p>class FourWheeler implements DrivingUtilities</p>
<p>class Car extends FourWheeler</p>
<p>class Truck extends FourWheeler</p>
<p>class Bus extends FourWheeler</p>
<p>class Crane extends FourWheeler</p>
<p>----------------------------------------------------------------------</p>
<p>&nbsp;<wbr> &nbsp;<wbr></p>
<p>Consider the following code below:</p>
<p>1.DrivingUtilities du;</p>
<p>2.FourWheeler fw;</p>
<p>3.Truck myTruck = new Truck();</p>
<p>4.du = (DrivingUtilities)myTruck;</p>
<p>5.fw = new Crane();</p>
<p>6.fw = du;</p>
<p>Which of the statements below are true?</p>
<p>Choices:</p>
<p>a. Line 4 will not compile because an interface cannot refer to an object.</p>
<p>b. The code will compile and run.</p>
<p>c. The code will not compile without an explicit cast at line 6, because going</p>
<p>down the hierarchy without casting is not allowed.</p>
<p>d.The code at line 4 will compile even without the explicit cast.</p>
<p>e.The code will compile if we put an explicit cast at line 6 but will throw an exception at runtime.</p>
<p>―――――――――――</p>
<p>C and D are correct. A and B are obviously wrong because there is nothing wrong in an interface referring to an object. C is correct because an explicit cast is needed to go down the hierarchy. D is correct because no explicit cast is needed at line 4, because we are going up the hierarchy. E is incorrect because if we put an explicit cast at line 6, the code will compile and run perfectly fine, no exception will be thrown because the runtime class of du (that is Truck) can be converted to type FourWheeler without any problem.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451171">&#167;1.1.5&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 五</a></h3>
<p>What will be printed when you execute the following code?</p>
<p>class X</p>
<p>{</p>
<p>Y b = new Y();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>X()</p>
<p>{</p>
<p>System.out.print("X");</p>
<p>}</p>
<p>}</p>
<p>class Y</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>Y()</p>
<p>{</p>
<p>System.out.print("Y");</p>
<p>}</p>
<p>}</p>
<p>public class Z extends X</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>Y y = new Y();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>Z()</p>
<p>{</p>
<p>System.out.print("Z");</p>
<p>}</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>public static void main(String[] args)</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>new Z();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>}</p>
<p>}</p>
<p>Choices:</p>
<p>a. Z</p>
<p>b. YZ</p>
<p>c. XYZ</p>
<p>d. YXYZ</p>
<p>―――――――――</p>
<p align="left">D is correct. A difficult but a fundamental question, please observe carefully. Before any object is constructed the object of the parent class is constructed(as there is a default call to the parent's constructor from the constructor of the child class via the super() statement). Also note that when an object is constructed the variables are initialized first and then the constructor is executed. So when new Z() is executed , the object of class X will be constructed, which means Y b = new Y() will be executed and "Y" will be printed as a result. After that constructor of X will be called which implies "X" will be printed. Now the object of Z will be constructed and thus Y y = new Y() will be executed and Y will be printed and finally the constructor Z() will be called and thus "Z" will be printed. Thus YXYZ will be printed.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451172">&#167;1.1.6&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 六</a></h3>
<p>What will happen when you attempt to compile and run the following code?</p>
<p>class Base</p>
<p>{</p>
<p>int i = 99;</p>
<p>public void amethod()</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>System.out.println("Base.amethod()");</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>}</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>Base()</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>amethod();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>}</p>
<p>}</p>
<p>public class Derived extends Base</p>
<p>{</p>
<p>int i = -1;</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr></p>
<p>public static void main(String argv[])</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>Base b = new Derived();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>System.out.println(b.i);</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>b.amethod();</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>}</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>public void amethod()</p>
<p>{</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>System.out.println("Derived.amethod()");</p>
<p>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr>}</p>
<p>}</p>
<p>Choices:</p>
<p>a. Derived.amethod()</p>
<p>-1</p>
<p>Derived.amethod()</p>
<p>b. Derived.amethod()</p>
<p>99</p>
<p>c.Derived.amethod()</p>
<p>99</p>
<p>d. Derived.amethod()</p>
<p>e.Compile time error</p>
<p align="left">――――――――</p>
<p align="left">B is correct. The reason is that this code creates an instance of the Derived class but assigns it to a reference of a the Base class. In this situation a reference to any of the fields such as i will refer to the value in the Base class, but a call to a method will refer to the method in the class type rather than its reference handle. But note that if the amethod() was not present in the base class then compilation error would be reported as at compile time, when compiler sees the statement like b.amethod(), it checks if the method is present in the base class or not. Only at the run time it decides to call the method from the derived class.</p>
<p align="left">&nbsp;<wbr></p>
<h3><a name="_Toc74451173">&#167;1.1.7&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 七</a></h3>
<p>Given the following code fragment:</p>
<p>&nbsp;<wbr></p>
<p>　　1) public void create() {</p>
<p>&nbsp;<wbr></p>
<p>　　2) Vector myVect;</p>
<p>&nbsp;<wbr></p>
<p>　　3) myVect = new Vector();</p>
<p>&nbsp;<wbr></p>
<p>　　4) }</p>
<p>&nbsp;<wbr></p>
<p>　　Which of the following statements are true?</p>
<p>　　A. The declaration on line 2 does not allocate memory space for the</p>
<p>variable myVect.</p>
<p>&nbsp;<wbr></p>
<p>　　B. The declaration on line 2 allocates memory space for a reference to a</p>
<p>Vector object.</p>
<p>&nbsp;<wbr></p>
<p>　　C. The statement on line 2 creates an object of class Vector.</p>
<p>&nbsp;<wbr></p>
<p>　　D. The statement on line 3 creates an object of class Vector.</p>
<p>&nbsp;<wbr></p>
<p>　　E. The statement on line 3 allocates memory space for an object of class</p>
<p>Vector</p>
<p>　　翻译</p>
<p>　　给出下面的代码片断。。。下面的哪些陈述为true(真)?</p>
<p>　　A. 第二行的声明不会为变量myVect分配内存空间。</p>
<p>　　B. 第二行的声明分配一个到Vector对象的引用的内存空间。</p>
<p>　　C. 第二行语句创建一个Vector类对象。</p>
<p>　　D. 第三行语句创建一个Vector类对象。</p>
<p>　　E. 第三行语句为一个Vector类对象分配内存空间。</p>
<p>&nbsp;<wbr></p>
<p>　　答案　A,D,E</p>
<p>&nbsp;<wbr></p>
<p>　　解析</p>
<p>　　SL-275中指出：要为一个新对象分配空间必须执行new</p>
<p>Xxx()调用，new调用执行以下的操作：</p>
<p>&nbsp;<wbr></p>
<p>　　1．为新对象分配空间并将其成员初始化为0或者null。</p>
<p>　</p>
<p>&nbsp;<wbr> 　2．执行类体中的初始化。（例如在类中有一个成员声明int a=10;在第一步后a=0</p>
<p>，执行到第二步后a=10）</p>
<p>&nbsp;<wbr></p>
<p>　　3．执行构造函数。</p>
<p>&nbsp;<wbr></p>
<p>　　4．变量被分配为一个到内存堆中的新对象的引用。</p>
<h3><a name="_Toc74451174">&#167;1.1.8&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 八</a></h3>
<p>Which of the following statements about variables and their scopes</p>
<p>are true?</p>
<p>&nbsp;<wbr></p>
<p>　　A. Instance variables are member variables of a class.</p>
<p>&nbsp;<wbr></p>
<p>　　B. Instance variables are declared with the static keyword.</p>
<p>&nbsp;<wbr></p>
<p>　　C. Local variables defined inside a method are created when the method</p>
<p>is executed.</p>
<p>&nbsp;<wbr></p>
<p>　　D. Local variables must be initialized before they are used.</p>
<p>&nbsp;<wbr></p>
<p>　　(acd)</p>
<p>&nbsp;<wbr></p>
<p>　　题目：下面关于变量及其范围的陈述哪些是对的。</p>
<p>&nbsp;<wbr></p>
<p>　　A. 实例变量是类的成员变量。</p>
<p>&nbsp;<wbr></p>
<p>　　B. 实例变量用关键字static声明。</p>
<p>&nbsp;<wbr></p>
<p>　　C. 在方法中定义的局部变量在该方法被执行时创建</p>
<p>&nbsp;<wbr></p>
<p>　　D. 局部变量在使用前必须被初始化。</p>
<p>&nbsp;<wbr></p>
<p>　　类中有几种变量，分别是：局部变量（英文可以为：local\automatic\temporary\stac</p>
<p>k</p>
<p>variable）是定义在方法里的变量；实例变量（英文为：instance</p>
<p>variable）是在方法外而在类声明内定义的变量，有时也叫成员变量；类变量（英文为：cl</p>
<p>ass</p>
<p>variable）是用关键字static声明的实例变量，他们的生存期分别是：局部变量在定义该变</p>
<p>量的方法被调用时被创建，而在该方法退出后被撤销；实例变量在使用new</p>
<p>Xxxx()创建该类的实例时被创建，而其生存期和该类的实例对象的生存期相同；类变量在该</p>
<p>类被加载时被创建，不一定要用new</p>
<p>Xxxx()创建，所有该类的实例对象共享该类变量，其生存期是类的生存期。任何变量在使用</p>
<p>前都必须初始化,但是需要指出的是局部变量必须显式初始化，而实例变量不必，原始类型的</p>
<p>实例变量在该类的构造方法被调用时为它分配的缺省的值，整型是0，布尔型是false，而浮点</p>
<p>型是0.0f，引用类型（类类型）的实例变量的缺省值是null（没有进行实际的初始化，对它的</p>
<p>使用将引起NullPointException），类变量的规则和实例变量一样，不同的是类变量的初始化</p>
<p>是在类被加载时。</p>
<h3><a name="_Toc74451175">&#167;1.1.9&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 九</a></h3>
<p>　　public class Parent {</p>
<p>　　int change() {&#8230;}</p>
<p>　　}</p>
<p>　　class Child extends Parent {</p>
<p>&nbsp;<wbr></p>
<p>　　}</p>
<p>　　Which methods can be added into class Child?</p>
<p>　　A. public int change(){}</p>
<p>&nbsp;<wbr></p>
<p>　　B. int chang(int i){}</p>
<p>&nbsp;<wbr></p>
<p>　　C. private int change(){}</p>
<p>&nbsp;<wbr></p>
<p>　　D. abstract int chang(){}</p>
<p>&nbsp;<wbr></p>
<p>　　(ab)</p>
<p>&nbsp;<wbr></p>
<p>　　题目：哪些方法可被加入类Child。</p>
<p>&nbsp;<wbr></p>
<p>　　需要注意的是答案D的内容，子类可以重写父类的方法并将之声明为抽象方法，但是这引发的问题是类必须声明为抽象类，否则编译不能通过，而且抽象方法不能有方法体，也就是方法声明后面不能带上那两个大括号（{}），这些D都不能满足。</p>
</div>
<img src ="http://www.blogjava.net/balajinima/aggbug/298535.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:40 <a href="http://www.blogjava.net/balajinima/articles/298535.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第三部分：垃圾收集</title><link>http://www.blogjava.net/balajinima/articles/298534.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:39:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298534.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298534.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298534.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298534.html</trackback:ping><description><![CDATA[<p align="left">第三部分：垃圾收集</p>
<ul type="disc">
    <li>了解垃圾收集机制能保证执行什么。
    <li>能通过代码操作一个对象，使它能被垃圾收集器收集。
    <li>知道在程序的哪一行，垃圾收集器能合法地收集某个对象。 </li>
</ul>
<h2>第一节&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 垃圾收集解析</h2>
<p>&nbsp;<wbr>垃圾收集器是Java语言区别于其他程序设计语言的一大特色。它把程序员从手工回收内存空间的繁重工作中解脱了出来。在SUN公司的Java程序员（Java Programmer）认证考试中，垃圾收集器是必考的内容，一般最多可以占总分值的6%左右。但是由于SUN公司的Java Programming Language SL-275 课程的标准教材中，对有关垃圾收集器的内容只做了非常简单的介绍，而另外的一些关于Java技术的书籍，比如《Java 2 核心技术》（Core Java 2）、《Java编程思想》（Thinking in Java）、《精通Java 2》等等，里面关于垃圾收集器的内容也几乎没有，或者只是简单地提两句，所以很多参加Java Programmer认证考试的中国考生，在垃圾收集器这一部分的得分都为0分（笔者曾认识一位SUN公司授权的中国Java培训班的老师，其考试总分为89%，但垃圾收集器的部分竟然也为0分）。鉴于此，笔者总结了这个垃圾收集器的专题，希望对广大Java技术的爱好者和准备认证考试的考生们有所帮助。</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 我们知道，许多程序设计语言都允许在程序运行期动态地分配内存空间。分配内存的方式多种多样，取决于该种语言的语法结构。但不论是哪一种语言的内存分配方式，最后都要返回所分配的内存块的起始地址，即返回一个指针到内存块的首地址。</p>
<p>当已经分配的内存空间不再需要时，换句话说当指向该内存块的句柄超出了使用范围的时候，该程序或其运行环境就应该回收该内存空间，以节省宝贵的内存资源。</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 在C，C++或其他程序设计语言中，无论是对象还是动态配置的资源或内存，都必须由程序员自行声明产生和回收，否则其中的资源将消耗，造成资源的浪费甚至死机。但手工回收内存往往是一项复杂而艰巨的工作。因为要预先确定占用的内存空间是否应该被回收是非常困难的！如果一段程序不能回收内存空间，而且在程序运行时系统中又没有了可以分配的内存空间时，这段程序就只能崩溃。通常，我们把分配出去后，却无法回收的内存空间称为"内存渗漏体（Memory Leaks）"。</p>
<p>以上这种程序设计的潜在危险性在Java这样以严谨、安全著称的语言中是不允许的。但是Java语言既不能限制程序员编写程序的自由性，又不能把声明对象的部分去除（否则就不是面向对象的程序语言了），那么最好的解决办法就是从Java程序语言本身的特性入手。于是，Java技术提供了一个系统级的线程（Thread），即垃圾收集器线程（Garbage Collection Thread），来跟踪每一块分配出去的内存空间，当Java 虚拟机（Java Virtual Machine）处于空闲循环时，垃圾收集器线程会自动检查每一快分配出去的内存空间，然后自动回收每一快可以回收的无用的内存块。</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 垃圾收集器线程是一种低优先级的线程，在一个Java程序的生命周期中，它只有在内存空闲的时候才有机会运行。它有效地防止了内存渗漏体的出现，并极大可能地节省了宝贵的内存资源。但是，通过Java虚拟机来执行垃圾收集器的方案可以是多种多样的。</p>
<p>下面介绍垃圾收集器的特点和它的执行机制：</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 垃圾收集器系统有自己的一套方案来判断哪个内存块是应该被回收的，哪个是不符合要求暂不回收的。垃圾收集器在一个Java程序中的执行是自动的，不能强制执行，即使程序员能明确地判断出有一块内存已经无用了，是应该回收的，程序员也不能强制垃圾收集器回收该内存块。程序员唯一能做的就是通过调用System. gc 方法来"建议"执行垃圾收集器，但其是否可以执行，什么时候执行却都是不可知的。这也是垃圾收集器的最主要的缺点。当然相对于它给程序员带来的巨大方便性而言，这个缺点是瑕不掩瑜的。</p>
<p>垃圾收集器的主要特点有：</p>
<p>1．垃圾收集器的工作目标是回收已经无用的对象的内存空间，从而避免内存渗漏体的产生，节省内存资源，避免程序代码的崩溃。</p>
<p>2．垃圾收集器判断一个对象的内存空间是否无用的标准是：如果该对象不能再被程序中任何一个"活动的部分"所引用，此时我们就说，该对象的内存空间已经无用。所谓"活动的部分"，是指程序中某部分参与程序的调用，正在执行过程中，尚未执行完毕。</p>
<p>3．垃圾收集器线程虽然是作为低优先级的线程运行，但在系统可用内存量过低的时候，它可能会突发地执行来挽救内存资源。当然其执行与否也是不可预知的。</p>
<p>4．垃圾收集器不可以被强制执行，但程序员可以通过调用System. gc方法来建议执行垃圾收集器。</p>
<p>5．不能保证一个无用的对象一定会被垃圾收集器收集，也不能保证垃圾收集器在一段Java语言代码中一定会执行。因此在程序执行过程中被分配出去的内存空间可能会一直保留到该程序执行完毕，除非该空间被重新分配或被其他方法回收。由此可见，完全彻底地根绝内存渗漏体的产生也是不可能的。但是请不要忘记，Java的垃圾收集器毕竟使程序员从手工回收内存空间的繁重工作中解脱了出来。设想一个程序员要用C或C++来编写一段10万行语句的代码，那么他一定会充分体会到Java的垃圾收集器的优点！</p>
<p>6．同样没有办法预知在一组均符合垃圾收集器收集标准的对象中，哪一个会被首先收集。</p>
<p>7．循环引用对象不会影响其被垃圾收集器收集。</p>
<p>8．可以通过将对象的引用变量（reference variables，即句柄handles）初始化为null值，来暗示垃圾收集器来收集该对象。但此时，如果该对象连接有事件监听器（典型的 AWT组件），那它还是不可以被收集。所以在设一个引用变量为null值之前，应注意该引用变量指向的对象是否被监听，若有，要首先除去监听器，然后才可以赋空值。</p>
<p>9．每一个对象都有一个finalize( )方法，这个方法是从Object类继承来的。</p>
<p>10．finalize( )方法用来回收内存以外的系统资源，就像是文件处理器和网络连接器。该方法的调用顺序和用来调用该方法的对象的创建顺序是无关的。换句话说，书写程序时该方法的顺序和方法的实际调用顺序是不相干的。请注意这只是finalize( )方法的特点。</p>
<p>11．每个对象只能调用finalize( )方法一次。如果在finalize( )方法执行时产生异常（exception），则该对象仍可以被垃圾收集器收集。</p>
<p>12．垃圾收集器跟踪每一个对象，收集那些不可到达的对象（即该对象没有被程序的任何"活的部分"所调用），回收其占有的内存空间。但在进行垃圾收集的时候，垃圾收集器会调用finalize( )方法，通过让其他对象知道它的存在，而使不可到达的对象再次"复苏"为可到达的对象。既然每个对象只能调用一次finalize( )方法，所以每个对象也只可能"复苏"一次。</p>
<p>13．finalize( )方法可以明确地被调用，但它却不能进行垃圾收集。</p>
<p>14．finalize( )方法可以被重载（overload），但只有具备初始的finalize( )方法特点的方法才可以被垃圾收集器调用。</p>
<p>15．子类的finalize( )方法可以明确地调用父类的finalize( )方法，作为该子类对象的最后一次适当的操作。但Java编译器却不认为这是一次覆盖操作（overriding），所以也不会对其调用进行检查。</p>
<p>16．当finalize( )方法尚未被调用时，System. runFinalization( )方法可以用来调用finalize( )方法，并实现相同的效果，对无用对象进行垃圾收集。</p>
<p>17．当一个方法执行完毕，其中的局部变量就会超出使用范围，此时可以被当作垃圾收集，但以后每当该方法再次被调用时，其中的局部变量便会被重新创建。</p>
<p>18．Java语言使用了一种"标记交换区的垃圾收集算法"。该算法会遍历程序中每一个对象的句柄，为被引用的对象做标记，然后回收尚未做标记的对象。所谓遍历可以简单地理解为"检查每一个"。</p>
<p>19．Java语言允许程序员为任何方法添加finalize( )方法，该方法会在垃圾收集器交换回收对象之前被调用。但不要过分依赖该方法对系统资源进行回收和再利用，因为该方法调用后的执行结果是不可预知的。</p>
<p>通过以上对垃圾收集器特点的了解，你应该可以明确垃圾收集器的作用，和垃圾收集器判断一块内存空间是否无用的标准。简单地说，当你为一个对象赋值为null并且重新定向了该对象的引用者，此时该对象就符合垃圾收集器的收集标准。</p>
<p>判断一个对象是否符合垃圾收集器的收集标准，这是SUN公司程序员认证考试中垃圾收集器部分的重要考点（可以说，这是唯一的考点）。所以，考生在一段给定的代码中，应该能够判断出哪个对象符合垃圾收集器收集的标准，哪个不符合。下面结合几种认证考试中可能出现的题型来具体讲解：</p>
<p>Object obj = new Object ( ) ;</p>
<p>我们知道，obj为Object的一个句柄。当出现new关键字时，就给新建的对象分配内存空间，而obj的值就是新分配的内存空间的首地址，即该对象的值(请特别注意，对象的值和对象的内容是不同含义的两个概念：对象的值就是指其内存块的首地址，即对象的句柄；而对象的内容则是其具体的内存块)。此时如果有 obj = null；则obj指向的内存块此时就无用了，因为下面再没有调用该变量了。</p>
<p>请再看以下三种认证考试时可能出现的题型：</p>
<p>程序段1：</p>
<p>1．fobj = new Object ( ) ;</p>
<p>2．fobj. Method ( ) ;</p>
<p>3．fobj = new Object ( ) ;</p>
<p>4．fobj. Method ( ) ;</p>
<p>问：这段代码中，第几行的fobj 符合垃圾收集器的收集标准？</p>
<p>答：第3行。因为第3行的fobj被赋了新值，产生了一个新的对象，即换了一块新的内存空间，也相当于为第1行中的fobj赋了null值。这种类型的题在认证0考试中是最简单的。</p>
<p>程序段2：</p>
<p>1．Object sobj = new Object ( ) ;</p>
<p>2．Object sobj = null ;</p>
<p>3．Object sobj = new Object ( ) ;</p>
<p>4．sobj = new Object ( ) ;</p>
<p>问：这段代码中，第几行的内存空间符合垃圾收集器的收集标准？</p>
<p>答：第1行和第3行。因为第2行为sobj赋值为null，所以在此第1行的sobj符合垃圾收集器的收集标准。而第4行相当于为sobj赋值为null，所以在此第3行的sobj也符合垃圾收集器的收集标准。</p>
<p>如果有一个对象的句柄a，且你把a作为某个构造器的参数，即 new Constructor ( a )的时候，即使你给a赋值为null，a也不符合垃圾收集器的收集标准。直到由上面构造器构造的新对象被赋空值时，a才可以被垃圾收集器收集。</p>
<p>程序段3：</p>
<p>1．Object aobj = new Object ( ) ;</p>
<p>2．Object bobj = new Object ( ) ;</p>
<p>3．Object cobj = new Object ( ) ;</p>
<p>4．aobj = bobj;</p>
<p>5．aobj = cobj;</p>
<p>6．cobj = null;</p>
<p>7．aobj = null;</p>
<p>问：这段代码中，第几行的内存空间符合垃圾收集器的收集标准？</p>
<p>答：第7行。注意这类题型是认证考试中可能遇到的最难题型了。</p>
<p>行1-3分别创建了Object类的三个对象：aobj，bobj，cobj</p>
<p>行4：此时对象aobj的句柄指向bobj，所以该行的执行不能使aobj符合垃圾收集器的收集标准。</p>
<p>行5：此时对象aobj的句柄指向cobj，所以该行的执行不能使aobj符合垃圾收集器的收集标准。</p>
<p>行6：此时仍没有任何一个对象符合垃圾收集器的收集标准。</p>
<p>行7：对象cobj符合了垃圾收集器的收集标准，因为cobj的句柄指向单一的地址空间。在第6行的时候，cobj已经被赋值为null，但由cobj同时还指向了aobj（第5行），所以此时cobj并不符合垃圾收集器的收集标准。而在第7行，aobj所指向的地址空间也被赋予了空值null，这就说明了，由cobj所指向的地址空间已经被完全地赋予了空值。所以此时cobj最终符合了垃圾收集器的收集标准。但对于aobj和bobj，仍然无法判断其是否符合收集标准。</p>
<p>总之，在Java语言中，判断一块内存空间是否符合垃圾收集器收集标准的标准只有两个：</p>
<p>1．给对象赋予了空值null，以下再没有调用过。</p>
<p>2．给对象赋予了新值，既重新分配了内存空间。</p>
<p>最后再次提醒一下，一块内存空间符合了垃圾收集器的收集标准，并不意味着这块内存空间就一定会被垃圾收集器收集。</p>
<p>&nbsp;<wbr></p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:39 <a href="http://www.blogjava.net/balajinima/articles/298534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二部分：流程控制，断言和异常处理</title><link>http://www.blogjava.net/balajinima/articles/298533.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:38:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298533.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298533.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298533.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298533.html</trackback:ping><description><![CDATA[<p align="left">第二部分：流程控制，断言和异常处理</p>
<ul type="disc">
    <li>能够正确使用if,switch语句，并且能正确使用合法的参数类型。
    <li>能够正确使用所有带标签或不带标签的循环语句，能正确使用break,continue，能计算在循环中或循环后循环计数器的值。
    <li>能够正确使用异常和异常处理语句（try,catch,finally）。能正确声明抛出异常的方法，并知道怎样覆盖它。
    <li>了解代码段中的异常对程序跳转的影响。注意：异常可能是一个运行时异常（runtime&nbsp;<wbr>exception）,一个已经定义的异常（checked&nbsp;<wbr>exception），也可能是一个error。
    <li>能正确使用断言，并了解关于断言机制的正确说法。 </li>
</ul>
<div>
<ul type="disc">
    <li>能够正确使用if,switch语句，并且能正确使用合法的参数类型。
    <li>能够正确使用所有带标签或不带标签的循环语句，能正确使用break,continue，能计算在循环中或循环后循环计数器的值。
    <li>能够正确使用异常和异常处理语句（try,catch,finally）。能正确声明抛出异常的方法，并知道怎样覆盖它。
    <li>了解代码段中的异常对程序跳转的影响。注意：异常可能是一个运行时异常（runtime&nbsp;<wbr>exception）,一个已经定义的异常（checked&nbsp;<wbr>exception），也可能是一个error。
    <li>能正确使用断言，并了解关于断言机制的正确说法。 </li>
</ul>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<h2>第一节&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 断言 assert</h2>
<h3><a name="1">&#167;1.1.1&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assertion</a>的语法和语义</h3>
<p>J2SE 1.4在语言上提供了一个新特性，就是assertion(断言)功能，它是该版本在Java语言方面最大的革新。在软件开发中，assertion是一种经典的调试、测试方式，本文将深入解析assertion功能的使用以及其设计理念，并给出相关的例子。</p>
<p>assertion(断言)在软件开发中是一种常用的调试方式，很多开发语言中都支持这种机制，如C，C++和Eiffel等，但是支持的形式不尽相同，有的是通过语言本身、有的是通过库函数等。另外，从理论上来说，通过assertion方式可以证明程序的正确性，但是这是一项相当复杂的工作，目前还没有太多的实践意义。</p>
<p>在实现中，assertion就是在程序中的一条语句，它对一个boolean表达式进行检查，一个正确程序必须保证这个boolean表达式的值为true；如果该值为false，说明程序已经处于不正确的状态下，系统将给出警告或退出。一般来说，assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能，在软件发布后，assertion检查通常是关闭的。下面简单介绍一下Java中assertion的实现。</p>
<p><strong>1</strong><strong>．</strong><strong>1)</strong> <strong>语法表示</strong></p>
<p>在语法上，为了支持assertion，Java增加了一个关键字assert。它包括两种表达式，分别如下：</p>
<p>1.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assert expression_r1;</p>
<p>2.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assert expression_r1: expression_r2;</p>
<p>在两种表达式中，expression_r1表示一个boolean表达式，expression_r2表示一个基本类型或者是一个对象(Object) ，基本类型包括boolean,char,double,float,int和long。由于所有类都为Object的子类，因此这个参数可以用于所有对象。</p>
<p><strong>1</strong><strong>．</strong><strong>2)</strong> <strong>语义含义</strong></p>
<p>在运行时，如果关闭了assertion功能，这些语句将不起任何作用。如果打开了assertion功能，那么expression_r1的值将被计算，如果它的值为false，该语句强抛出一个AssertionError对象。如果assertion语句包括expression_r2参数，程序将计算出expression_r2的结果，然后将这个结果作为AssertionError的构造函数的参数，来创建AssertionError对象，并抛出该对象；如果expression_r1值为true，expression_r2将不被计算。</p>
<p>一种特殊情况是，如果在计算表达式时，表达式本身抛出Exception，那么assert将停止运行，而抛出这个Exception。</p>
<p><strong>1</strong><strong>．</strong><strong>3)</strong> <strong>一些</strong><strong>assertion</strong><strong>例子</strong></p>
<p>下面是一些Assert的例子。</p>
<p>1.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assert　　0 &lt; value;</p>
<p>2.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assert　　0 &lt; value:"value="+value;</p>
<p>3.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assert　　ref != null:"ref doesn't equal null";</p>
<p>4.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assert　　isBalanced();</p>
<p><strong>1</strong><strong>．</strong><strong>4)</strong> <strong>编译</strong></p>
<p>由于assert是一个新关键字，使用老版本的JDK是无法编译带有assert的源程序。因此，我们必须使用JDK1.4(或者更新)的Java编译器，在使用Javac命令时，我们必须加上-source 1.4作为参数。-source 1.4表示使用JDK 1.4版本的方式来编译源代码，否则编译就不能通过，因为缺省的Javac编译器使用JDK1.3的语法规则。</p>
<p>一个简单的例子如下：</p>
<p>javac&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> -source&nbsp;<wbr>&nbsp;<wbr> 1.4&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> test.java</p>
<p><strong>1</strong><strong>．</strong><strong>5)</strong> <strong>运行</strong></p>
<p>由于带有assert语句的程序运行时，使用了新的ClassLoader和Class类，因此，这种程序必须在JDK1.4(或者更高版本)的JRE下运行，而不能在老版本的JRE下运行。</p>
<p>1.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 由于我们可以选择开启assertion功能，或者不开启，另外我们还可以开启一部分类或包的assertion功能，所以运行选项变得有些复杂。通过这些选项，我们可以过滤所有我们不关心的类，只选择我们关心的类或包来观察。</p>
<h3><a name="2">&#167;1.1.2&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assertion</a>的设计问题</h3>
<p>首先，我们认为assertion是必要的。因为，如果没有统一的assertion机制，Java程序通常使用if-then-else或者switch-case语句进行assertion检查，而且检查的数据类型也不完全相同。assertion机制让Java程序员用统一的方式处理assertion问题，而不是按自己的方式处理。另外，如果用户使用自己的方式进行检查，那么这些代码在发布以后仍然将起作用，这可能会影响程序的性能。而从语言言层次支持assertion功能，这将把assertion对性能带来的负面影响降到最小。</p>
<p>Java是通过增强一个关键字assert实现支持assertion，而不是使用一个库函数支持，这说明Java认为assertion对于语言本身来说是非常重要的。实际上，在Java的早期的规范中，Java是能够支持assert的，但是由于一些实现的限制，这些特性从规范中除去了。因此，assert的再次引入应该是恢复了Java对assert的支持。C语言就是通过Assert.h函数库实现断言的支持。</p>
<p>Java的assertion的开启也和C语言不太一样，我们都知道在C语言中，assertion的开启是在编译时候决定的。当我们使用debug方式编译程序时候，assertion被开启，而使用release方式编译时候，assertion自动被关闭。而Java的assertion却是在运行的时候进行决定的。其实，这两种方式是各有优缺点。如果采用编译时决定方式，开发人员将处理两种类型的目标码，debug版本和release版本，这加大了文档管理的难度，但是提高了代码的运行效率。Java采用运行时决定的方式，这样所有的assertion信息将置于目标代码中，同一目标代码可以选择不同方式运行，增强目标代码的灵活性，但是它将牺牲因为assertion而引起一部分性能损失。Java专家小组认为，所牺牲的性能相当小，因此java采用了运行时决定方式。</p>
<p>另外，我们注意到AssertionError作为Error的一个子类，而不是RuntimeException。关于这一点，专家组也进行了长期的讨论。Error代表一些异常的错误，通常是不可以恢复的，而RuntimeException强调该错误在运行时才发生的特点。AssertionError通常为非常关键的错误，这些错误往往是不容易恢复的，而且assertion机制也不鼓励程序员对这种错误进行恢复。因此，为了强调assertion的含义，Java专家小组选择了让AssertError为Error的子类。</p>
<h3><a name="3">&#167;1.1.3&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assertion</a>与继承</h3>
<p>在本节，我们将考虑assertion与继承的关系，研究assert是如何定位的。如果开启一个子类的assertion，那么它的父类的assertion是否执行？</p>
<p>下面的例子将显示如果一个assert语句在父类，而当它的子类调用它时，该assert为false。我们看看在不同的情况下，该assertion是否被处理。</p>
<p>class Base</p>
<p>{</p>
<p>&nbsp;<wbr> public void baseMethod()</p>
<p>&nbsp;<wbr> { // 总是assertion失败</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assert&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> false : "Assertion failed:This is base ";</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.println("Base Method");</p>
<p>&nbsp;<wbr> }</p>
<p>}</p>
<p>&nbsp;<wbr></p>
<p>class Derived</p>
<p>&nbsp;<wbr> extends Base</p>
<p>{</p>
<p>&nbsp;<wbr> public void derivedMethod()</p>
<p>&nbsp;<wbr> { // 总是assertion失败</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assert false: "Assertion failed:This is derive";</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.println( "Derived Method" );</p>
<p>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr> public static void main( String[] args )</p>
<p>&nbsp;<wbr> {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> try</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> Derived derived = new Derived();</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> derived.baseMethod(&nbsp;<wbr> );</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>derived.derivedMethod();</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> catch( AssertionError ae )</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.println(ae);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p>&nbsp;<wbr> }</p>
<p>}</p>
<table border="1" cellpadding="0" width="98%">
    <tbody>
        <tr>
            <td width="26%">
            <p>运行命令</p>
            </td>
            <td width="32%">
            <p>含义</p>
            </td>
            <td width="40%">
            <p>结果</p>
            </td>
        </tr>
        <tr>
            <td width="26%">
            <p>Java Derived</p>
            </td>
            <td width="32%">
            <p>不启用assertion</p>
            </td>
            <td width="40%">
            <p>Base Method<br />
            Derived Method</p>
            </td>
        </tr>
        <tr>
            <td width="26%">
            <p>Java -ea Derived</p>
            </td>
            <td width="32%">
            <p>开启所有assertion</p>
            </td>
            <td width="40%">
            <p>Java.lang.AssertionError:Assertion Failed:This is base</p>
            </td>
        </tr>
        <tr>
            <td width="26%">
            <p>Java -da Derived</p>
            </td>
            <td width="32%">
            <p>关闭所有assertion</p>
            </td>
            <td width="40%">
            <p>Base Method<br />
            Derived Method</p>
            </td>
        </tr>
        <tr>
            <td width="26%">
            <p>Java -ea:Base Derived</p>
            </td>
            <td width="32%">
            <p>仅打开Base的assertion</p>
            </td>
            <td width="40%">
            <p>Java.lang.AssertionError:Assertion Failed:This is base</p>
            </td>
        </tr>
        <tr>
            <td width="26%">
            <p>Java -ea:Derived Derived</p>
            </td>
            <td width="32%">
            <p>仅打开Derived的assertion</p>
            </td>
            <td width="40%">
            <p>Base Method<br />
            Java.lang.AssertionError:Assertion Failed:This is derived</p>
            </td>
        </tr>
    </tbody>
</table>
<p>从这个例子我们可以看出，父类的assert语句将只有在父类的assert开启才起作用，如果仅仅开启子类的assert，父类的assert仍然不运行。例如，我们执行java -ea:Derived Derived的时候，Base类的assert语句并不执行。因此，我们可以认为，assert语句不具有继承功能。</p>
<h3><a name="4">&#167;1.1.4&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> assertion</a>的使用</h3>
<p>assertion的使用是一个复杂的问题，因为这将涉及到程序的风格，assertion运用的目标，程序的性质等问题。通常来说，assertion用于检查一些关键的值，并且这些值对整个程序，或者局部功能的完成有很大的影响，并且这种错误不容易恢复的。assertion表达式应该短小、易懂，如果需要评估复杂的表达式，应该使用函数计算。以下是一些使用assertion的情况的例子，这些方式可以让java程序的可靠性更高。</p>
<p align="left">1.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 检查控制流；在if-then-else和swith-case语句中，我们可以在不应该发生的控制支流上加上assert false语句。如果这种情况发生了，assert能够检查出来。<br />
例如：x取值只能使1,2,3，我们的程序可以如下表示</p>
<p align="left">2.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> switch (x)</p>
<p>3.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { case 1: &#8230;;</p>
<p>4.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>case 2: &#8230;;</p>
<p>5.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>case 3: &#8230;</p>
<p>6.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>default: assert false:"x value is invalid: "+x;</p>
<p>7.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align="left">8.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 在私有函数计算前，检查输入参数是否有效；对于一私有些函数，要求输入满足一些特定的条件，那么我们可以在函数开始处使用assert进行参数检查。对于公共函数，我们通常不使用assertion检查，因为一般来说，公共函数必须对无效的参数进行检查和处理。而私有函数往往是直接使用的。<br />
例如：某函数可能要求输入的参数必须不为null。那么我们可以在函数的一开始加上 assert parameter1!=null : "paramerter is null in test method";</p>
<p align="left">9.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 在函数计算后，检查函数结果是否有效；对于一些计算函数，函数运行完成后，某些值需要保证一定的性质，因此我们可以通过assert检查该值。<br />
例如，我们有一个计算绝对值的函数，那么我们就可以在函数的结果处，加上一个语句：</p>
<p align="left">assert&nbsp;<wbr> value&gt;=0:"Value should be bigger than 0:"+value;</p>
<p align="left">通过这种方式，我们可以对函数计算完的结果进行检查。</p>
<p align="left">10.&nbsp;<wbr>&nbsp;<wbr> 检查程序不变量；有些程序中，存在一些不变量，在程序的运行生命周期，这些不变量的值都是不变的。这些不变量可能是一个简单表达式，也可能是一个复杂的表达式。对于一些关键的不变量，我们可以通过assert进行检查。<br />
例如，在一个财会系统中，公司的支出和收入必须保持一定的平衡关系，因此我们可以编写一个表达式检查这种平衡关系，如下表示。</p>
<p align="left">11.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>private boolean isBalance() {</p>
<p align="left">12.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&#8230;&#8230;</p>
<p align="left">13.&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p align="left">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr></p>
<p align="left">在这个系统中，在一些可能影响这种平衡关系的方法的前后，我们都可以加上assert验证：assert isBalance():"balance is destoried";</p>
<h3><a name="5">&#167;1.1.5&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 结论</a></h3>
<p>assertion为开发人员提供了一种灵活地调试和测试机制，它的使用也非常简单、方便。但是，如何规范、系统地使用assertion(特别是在Java语言中)仍然是一个亟待研究的问题</p>
</div>
<img src ="http://www.blogjava.net/balajinima/aggbug/298533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:38 <a href="http://www.blogjava.net/balajinima/articles/298533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第一部分：声明和访问控制(练习题)</title><link>http://www.blogjava.net/balajinima/articles/298532.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Fri, 16 Oct 2009 03:37:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298532.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298532.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298532.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298532.html</trackback:ping><description><![CDATA[<p align="left">第一部分：声明和访问控制</p>
<ul type="disc">
    <li>知道怎么样声明、创建和初始化各种类型的数组
    <li>知道怎么样声明类、内部类、方法、成员变量、静态变量和方法内部变量，并会使用合法的修饰符（如public,final,static,abstract,等等）。了解这些修饰符单独使用或组合使用的含义，并且知道它们对于包作用域的影响。
    <li>了解类的构造器（constructor）
    <li>给定一个方法，能判断它的合法返回类型 </li>
</ul>
<div>
<h3><a name="_Toc74451139">&#167;1.1.1&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 一</a></h3>
<p>In the following pieces of code, A and D will compile without any error. True/False?</p>
<p>A: StringBuffer sb1 = "abcd";</p>
<p>B: Boolean b = new Boolean("abcd");</p>
<p>C: byte b = 255;</p>
<p>D: int x = 0x1234;</p>
<p>E: float fl = 1.2;</p>
<p>&nbsp;<wbr></p>
<p>Choices:</p>
<p>A. True</p>
<p>B. False</p>
<p>―――――――――――――――――――――――――――――――</p>
<p>答案 B. The code segments B and D will compile without any error. A is not a valid way to construct a StringBuffer, you need to creat a StringBuffer object using "new". B is a valid construction of a Boolean (any string other than "true" or "false" to the Boolean constructor will result in a Boolean with a value of "false"). C will fail to compile because the valid range for a byte is -128 to +127 (ie, 8 bits,signed). D is correct, 0x1234 is the hexadecimal representation in java. E fails to compile because the compiler interprets 1.2 as a double being assigned to a float (down-casting), which is not valid. You either need an explicit cast (as in "(float)1.2") or "1.2f", to indicate a float.</p>
<p align="left">&nbsp;<wbr></p>
<p align="left">&nbsp;<wbr></p>
<p align="left">&nbsp;<wbr></p>
<h3><a name="_Toc74451140">&#167;1.1.2&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 二</a></h3>
<p>What will be the result of executing the following code?</p>
<p>Given that Test1 is a class.</p>
<p>1. Test1[] t1 = new Test1[10];</p>
<p>2. Test1[][] t2 = new Test1[5][];</p>
<p>3. if (t1[0] == null)</p>
<p>4. {</p>
<p>5.t2[0] = new Test1[10]</p>
<p>6.t2[1] = new Test1[10]</p>
<p>7.t2[2] = new Test1[10]</p>
<p>8.t2[3] = new Test1[10]</p>
<p>9.t2[4] = new Test1[10]</p>
<p>10. }</p>
<p>11. System.out.println(t1[0]);</p>
<p>12. System.out.println(t2[1][0]);</p>
<p>Choices:</p>
<p>a. The code will not compile because the array t2 is not initialized in an unconditional statement before use.</p>
<p>b. The code will compile but a runtime exception will be thrown at line 12.</p>
<p>c. The code will compile but a runtime exception will be thrown at line 11.</p>
<p>d. None of these.</p>
<p>―――――――――――――――――――――</p>
<p>D is correct. Though we cannot use local variables without initializing them (compilation error), there is an exception to it. In case of arrays initialization is supposed to be complete when we specify the leftmost dimension of the array. The problem occurs at runtime if we try to access an element of the array which has not been initialized (specification of size). In the question above the array t2 is initialized before use, therefore there will be no problem at runtime also and the lines 11 and 12 will both print null.</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451141">&#167;1.1.3&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 三</a></h3>
<p>Which declarations of identifiers are legal?</p>
<p>　A. $persons</p>
<p>　　B. TwoUsers</p>
<p>　　C. *point</p>
<p>　　D. this</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> E. _endline</p>
<p>　　</p>
<p>　　答案　A,B,E</p>
<p>　　</p>
<p>　　解析　Java的标识符可以以一个Unicode字符，下滑线（_），美元符（$）开始，后续字</p>
<p>符可以是前面的符号和数字，没有长度限制，大小写敏感，不能是保留字。</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451142">&#167;1.1.4&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 四</a></h3>
<p>Which of the following answer is correct to express the value 8 in octal number?</p>
<p>　　A. 010</p>
<p>　　B. 0x10</p>
<p>　　C. 08</p>
<p>　　D. 0x8</p>
<p>&nbsp;<wbr></p>
<p>　　翻译</p>
<p>　　下面的哪些答案可以用以表示八进制值8。</p>
<p>　　答案　A</p>
<p>&nbsp;<wbr></p>
<p>　　解析　　八进制值以0开头，以0x开头的为十六进制值，八进制中不能出现数字8，最大只有7。</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451143">&#167;1.1.5&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 五</a></h3>
<p>Which are not Java keywords?</p>
<p>　　A. TRUE</p>
<p>　　B. sizeof</p>
<p>　　C. const</p>
<p>　　D. super</p>
<p>　　E. void</p>
<p>&nbsp;<wbr></p>
<p>　　翻译</p>
<p>　　哪些不是Java关键字。</p>
<p>&nbsp;<wbr></p>
<p>　　答案　A,B</p>
<p>&nbsp;<wbr></p>
<p>　　解析</p>
<p>　&nbsp;<wbr> A：不是，Java中有true,但是这也不是关键字而是字面量（literal）。</p>
<p>　B：不是，Java中不需要这个操作符，所有的类型（原始类型）的大小都是固定的。</p>
<p>　C、D、E都是，需要说明的是const是java中未被使用的关键字。</p>
<p>&nbsp;<wbr></p>
<h3><a name="_Toc74451144">&#167;1.1.6&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 六</a></h3>
<p>Which statements about Java code security are true?</p>
<p>　　A. The bytecode verifier loads all classes needed for the execution of a program.</p>
<p>　　B. Executing code is performed by the runtime interpreter.</p>
<p>　　C. At runtime the bytecodes are loaded, checked and run in an interpreter.</p>
<p>　　D. The class loader adds security by separating the namespaces for the</p>
<p>classes of the local file system from those imported from network sources.</p>
<p>&nbsp;<wbr></p>
<p>――――――――――――――</p>
<p>答案 BCD</p>
<p>&nbsp;<wbr></p>
<h3>&#167;1.1.7&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 七</h3>
<p>　　题目：下面有关java代码安全性的叙述哪些是对的。</p>
<p>　　A. 字节码校验器加载查询执行需要的所有类。</p>
<p>&nbsp;<wbr></p>
<p>　　B. 运行时解释器执行代码。</p>
<p>&nbsp;<wbr></p>
<p>　　C. 在运行时，字节码被加载，验证然后在解释器里面运行。</p>
<p>&nbsp;<wbr></p>
<p>　　D. 类加载器通过分离本机文件系统的类和从网络导入的类增加安全性。</p>
<p>&nbsp;<wbr></p>
<p>　　SL275中描述的Java程序运行的过程是这样的：类加载器（class loader）加载程序运行所需要的所有类，它通过区分本机文件系统的类和网络系统导入的类增加安全性，这可以限制任何的特洛伊木马程序，因为本机类总是先被加载，一旦所有的类被加载完，执行文件的内存划分就固定了，在这个时候特定的内存地址被分配给对应的符号引用，查找表（lookuo table）也被建立，由于内存划分发生在运行时，解释器在受限制的代码区增加保护防止未授权的访问；然后字节码校验器（byte code verifier）进行校验，主要执行下面的检查：类符合JVM规范的类文件格式，没有违反访问限制，代码没有造成堆栈的上溢或者下溢，所有操作代码的参数类型都是正确的，没有非法的数据类型转换（例如将整型数转换成对象类型）发生；校验通过的字节码被解释器（interpreter）执行，解释器在必要时通过运行时系统执行对底层硬件的合适调用。后三个答案是SL275中的原话。</p>
<h3>&#167;1.1.8&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 八</h3>
<p>Which fragments are correct in Java source file?</p>
<p>　　A. package testpackage;</p>
<p>　　public class Test{//do something...}</p>
<p>&nbsp;<wbr></p>
<p>　　B. import java.io.*;</p>
<p>　　package testpackage;</p>
<p>　　public class Test{// do something...}</p>
<p>&nbsp;<wbr></p>
<p>　　C. import java.io.*;</p>
<p>　　class Person{// do something...}</p>
<p>　　public class Test{// do something...}</p>
<p>&nbsp;<wbr></p>
<p>　　D. import java.io.*;</p>
<p>　　import java.awt.*;</p>
<p>　　public class Test{// do something...}</p>
<p>&nbsp;<wbr></p>
<p>------------------------</p>
<p>答案 ACD</p>
<p>　</p>
<h3>&#167;1.1.9&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 九</h3>
<p>Which of the following statements are legal?</p>
<p>　　A. long l = 4990;</p>
<p>　　B. int i = 4L;</p>
<p>　　C. float f = 1.1;</p>
<p>　　D. double d = 34.4;</p>
<p>　　E. double t = 0.9F.</p>
<p>----------------------------</p>
<p>答案　ADE</p>
<p>&nbsp;</p>
</div>
<img src ="http://www.blogjava.net/balajinima/aggbug/298532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-16 11:37 <a href="http://www.blogjava.net/balajinima/articles/298532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解析Java对象的equals()和hashCode()的使用</title><link>http://www.blogjava.net/balajinima/articles/298351.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Thu, 15 Oct 2009 03:21:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298351.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298351.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298351.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298351.html</trackback:ping><description><![CDATA[<p><strong>前言</strong> </p>
<p>在Java语言中，equals()和hashCode()两个函数的使用是紧密配合的，你要是自己设计其中一个，就要设计另外一个。在多数情况 下，这两个函数是不用考虑的，直接使用它们的默认设计就可以了。但是在一些情况下，这两个函数最好是自己设计，才能确保整个程序的正常运行。最常见的是当 一个对象被加入集合对象（collection object）时，这两个函数必须自己设计。更细化的定义是：如果你想将一个对象A放入另一个Collection Object B里，或者使用这个对象A为查找一个元对象在Collection Object&nbsp;&nbsp;&nbsp; B里位置的key，并支持是否容纳，删除Collection Object&nbsp;&nbsp;&nbsp; B里的元对象这样的操作，那么，equals()和hashCode()函数必须开发者自己定义。其他情 况下，这两个函数是不需要定义的。</p>
<p><strong>equals():</strong> <br />
它是用于进行两个对象的比较的，是对象内容的比较，当然也能用于进行对象参阅值的比较。什么是对象参阅值的比较？就是两个参阅变量的值得比较，我们 都知道参阅变量的值其实就是一个数字，这个数字可以看成是鉴别不同对象的代号。两个对象参阅值的比较，就是两个数字的比较，两个代号的比较。这种比较是默 认的对象比较方式，在Object这个对象中，这种方式就已经设计好了。所以你也不用自己来重写，浪费不必要的时间。</p>
<p>对象内容的比较才是设计equals()的真正目的，Java语言对equals()的要求如下，这些要求是必须遵循的。否则，你就不该浪费时间： <br />
对称性：如果x.equals(y)返回是&#8220;true&#8221;，那么y.equals(x)也应该返回是&#8220;true&#8221;。 <br />
反射性：x.equals(x)必须返回是&#8220;true&#8221;。 <br />
类推性：如果x.equals(y)返回是&#8220;true&#8221;，而且y.equals(z)返回是&#8220;true&#8221;，那么z.equals(x)也应该返回是&#8220;true&#8221;。 <br />
还有一致性：如果x.equals(y)返回是&#8220;true&#8221;，只要x和y内容一直不变，不管你重复x.equals(y)多少次，返回都是&#8220;true&#8221;。 <br />
任何情况下，x.equals(null)，永远返回是&#8220;false&#8221;；x.equals(和x不同类型的对象)永远返回是&#8220;false&#8221;。 <br />
<strong>hashCode():</strong><br />
这 个函数返回的就是一个用来进行hash操作的整型代号，请不要把这个代号和前面所说的参阅变量所代表的代号弄混了。后者不仅仅是个代号还具有在内存中才查找对 象的位置的功能。hashCode()所返回的值是用来分类对象在一些特定的Collection对象中的位置。这些对象是HashMap, Hashtable, HashSet，等等。这个函数和上面的equals()函数必须自己设计，用来协助HashMap, Hashtable, HashSet，等等对自己所收集的大量对象进行搜寻和定位。</p>
<p>这些Collection对象究竟如何工作的，想象每个元对象hashCode是一个箱子的 编码，按照编码，每个元对象就是根据hashCode()提供的代号归入相应的箱子里。所有的箱子加起来就是一个HashSet，HashMap，或 Hashtable对象，我们需要寻找一个元对象时，先看它的代码，就是hashCode()返回的整型值，这样我们找到它所在的箱子，然后在箱子里，每 个元对象都拿出来一个个和我们要找的对象进行对比，如果两个对象的内容相等，我们的搜寻也就结束。这种操作需要两个重要的信息，一是对象的 hashCode()，还有一个是对象内容对比的结果。</p>
<p>hashCode()的返回值和equals()的关系如下：</p>
<p>如果x.equals(y)返回&#8220;true&#8221;，那么x和y的hashCode()必须相等。 <br />
如果x.equals(y)返回&#8220;false&#8221;，那么x和y的hashCode()有可能相等，也有可能不等。 </p>
<p>为什么这两个规则是这样的，原因其实很简单，拿HashSet来说吧，HashSet可以拥有一个或更多的箱子，在同一个箱子中可以有一个 或更多的独特元对象（HashSet所容纳的必须是独特的元对象）。这个例子说明一个元对象可以和其他不同的元对象拥有相同的hashCode。但是一个 元对象只能和拥有同样内容的元对象相等。所以这两个规则必须成立。(在实际的某个集合对象如HashSet set.contains(object o);时，是先通过 hashcode()找到&#8220;箱子&#8221; ，在根据 equals判断对象内容 是否相等，从而判断集合对象是否包含某个元对象）</p>
<p><strong>设计这两个函数所要注意到的：<br />
</strong>如果你设计的对象类型并不使用于Collection对象，那么没有必要自己再设计这两个函数的处理方式。这是正确的面向对象设计方法，任何用户一时用不到的功能，就先不要设计，以免给日后功能扩展带来麻烦。</p>
<p>如果你在设计时想别出心裁，不遵守以上的两套规则，那么劝你还是不要做这样想入非非的事。我还没有遇到过哪一个开发者和我说设计这两个函数要违背前面说的两个规则，我碰到这些违反规则的情况时，都是作为设计错误处理。</p>
<p>当一个对象类型作为Collection对象的元对象时，这个对象应该拥有自己处理equals()，和/或处理hashCode()的设计，而且要遵守前面所说 的两种原则。equals()先要查null和是否是同一类型。查同一类型是为了避免出现ClassCastException这样的异常给丢出来。查 null是为了避免出现NullPointerException这样的异常给丢出来。</p>
<p>如果你的对象里面容纳的数据过多，那么这两个函数 equals()和hashCode()将会变得效率低。如果对象中拥有无法serialized的数据，equals()有可能在操作中出现错误。想象 一个对象x，它的一个整型数据是transient型（不能被serialize成二进制数据流）。然而equals()和hashCode()都有依靠 这个整型数据，那么，这个对象在serialization之前和之后，是否一样？答案是不一样。因为serialization之前的整型数据是有效的 数据，在serialization之后，这个整型数据的值并没有存储下来，再重新由二进制数据流转换成对象后，两者（对象在serialization 之前和之后）的状态已经不同了。这也是要注意的。</p>
<p><strong>知道以上这些能够帮助你：<br />
</strong>1. 进行更好的设计和开发。<br />
2. 进行更好的测试案例开发。<br />
3. 在面试过程中让面试者对你的学识渊博感到满意。 </p>
<p><span style="color: red">在Hibernate中，POJO类要重写hashcode()方法和equals()方法。为什么呢？</span></p>
<p>1，重点是equals，重写hashCode只是技术要求（为了提高效率） </p>
<p>2，为什么要重写equals呢，因为在java的集合框架中，是通过equals来判断两个对象是否相等的 </p>
<p>3，在hibernate中，经常使用set集合来保存相关对象，而set集合是不允许重复的，但是下面的程序，判断一下运行结果：</p>
<p>&nbsp;&nbsp;&nbsp; Set user = new HashSet(); <br />
&nbsp;&nbsp;&nbsp; user.add(new Book("精通struts")); <br />
&nbsp;&nbsp;&nbsp; user.add(new Book("精通struts")); <br />
&nbsp;&nbsp;&nbsp; System.out.println(user.size()); </p>
<p>上面程序的运行结果取决于Book类是否重写了equals方法。</p>
<p>如果没有重写，默认equals是比较地址，那么这两个book对象不一样，输出2，意味着hibernate会认为这是两个对象，再接下来的持久化过程中可能会出错。</p>
<p>如果重写了equals，比如按照主键（书名）比较，那么这两个对象是一样的，输出1 。</p>
<p><br />
&nbsp;</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-15 11:21 <a href="http://www.blogjava.net/balajinima/articles/298351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java异常分类</title><link>http://www.blogjava.net/balajinima/articles/298342.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Thu, 15 Oct 2009 03:03:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298342.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298342.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298342.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298342.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298342.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><strong><span style="font-size: 14pt"><span style="font-family: Times New Roman">Java</span></span></strong><strong><span style="font-family: 宋体; font-size: 14pt">中异常的分类</span></strong></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: 宋体">所有异常，都继承自</span><span style="font-family: Times New Roman">java.lang.Throwable</span><span style="font-family: 宋体">类。</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: Times New Roman">Throwable</span><span style="font-family: 宋体">有两个直接子类，</span><span style="font-family: Times New Roman">Error</span><span style="font-family: 宋体">类和</span><span style="font-family: Times New Roman">Exception</span><span style="font-family: 宋体">类。</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><strong><span style="font-size: 14pt"><span style="font-family: Times New Roman">Exception</span></span></strong></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: Times New Roman">Exception</span><span style="font-family: 宋体">则可使从任何标准</span><span style="font-family: Times New Roman">Java</span><span style="font-family: 宋体">库的类方法，自己的方法以及运行时任何异常中抛出来的基类型。</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: 宋体">异常可分为执行异常（</span><span style="font-family: Times New Roman">RuntimeException</span><span style="font-family: 宋体">）和检查异常（</span><span style="font-family: Times New Roman">Checked Exceptions</span><span style="font-family: 宋体">）两种</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><strong><span style="font-size: 14pt"><span style="font-family: Times New Roman">RuntimeException</span></span></strong></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">RuntimeException</span><span style="font-size: small"><span style="font-family: 宋体">在默认情况下会得到自动处理。所以通常用不着捕获</span><span style="font-family: Times New Roman">RuntimeException</span><span style="font-family: 宋体">，但在自己的封装里，也许仍然要选择抛出一部分</span><span style="font-family: Times New Roman">RuntimeException</span><span style="font-family: 宋体">。</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><code><span style="font-size: 12pt"><span style="font-family: 宋体">RuntimeException</span></span></code><span style="font-size: small"><span style="font-family: 宋体">是那些可能在</span><span style="font-family: Times New Roman"> Java </span><span style="font-family: 宋体">虚拟机正常运行期间抛出的异常的超类。可能在执行方法期间抛出但未被捕获的</span><code><span style="font-size: 12pt"><span style="font-family: 宋体">RuntimeException</span></span></code><span style="font-family: 宋体">的任何子类都<strong><span style="color: red">无需</span></strong>在</span><code><span style="font-size: 12pt"><span style="font-family: 宋体">throws</span></span></code><span style="font-family: 宋体">子句中进行声明。（</span><span style="font-family: Times New Roman">java api</span><span style="font-family: 宋体">）</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: 宋体">它是</span><span style="font-family: Times New Roman">uncheckedExcepiton</span><span style="font-family: 宋体">。</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.ArithmeticException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.ArrayStoreExcetpion</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.ClassCastException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.EnumConstantNotPresentException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.IllegalArgumentException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java.lang.IllegalThreadStateException</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java.lang.NumberFormatException</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.IllegalMonitorStateException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.IllegalStateException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.IndexOutOfBoundsException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java.lang.ArrayIndexOutOfBoundsException</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java.lang.StringIndexOutOfBoundsException</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.NegativeArraySizeException&#8217;</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.NullPointerException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.SecurityException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.TypeNotPresentException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.UnsupprotedOperationException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><strong><span style="font-size: 14pt"><span style="font-family: Times New Roman">CheckedException</span></span></strong></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: 宋体">除了</span><span style="font-family: Times New Roman">runtimeException</span><span style="font-family: 宋体">以外的异常，都属于</span><span style="font-family: Times New Roman">checkedException</span><span style="font-family: 宋体">，它们都在</span><span style="font-family: Times New Roman">java.lang</span><span style="font-family: 宋体">库内部定义。</span><span style="font-family: Times New Roman">Java</span><span style="font-family: 宋体">编译器要求程序必须捕获或声明抛出这种异常。</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: 宋体">一个方法必须通过</span><span style="font-family: Times New Roman">throws</span><span style="font-family: 宋体">语句在方法的声明部分说明它可能抛出但并未捕获的所有</span><span style="font-family: Times New Roman">checkedException</span><span style="font-family: 宋体">。</span></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.ClassNotFoundException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.CloneNotSupportedException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.IllegalAccessException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.InterruptedException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.NoSuchFieldException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: Times New Roman; font-size: small">Java.lang.NoSuchMetodException</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><strong><span style="font-size: 14pt"><span style="font-family: Times New Roman">Error</span></span></strong></p>
<p style="margin: 0cm 0cm 0pt" class="Default"><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">当程序发生不可控这种错误时，通常的做法是通知用户并中止程序的执行。</span></p>
<p style="margin: 0cm 0cm 0pt" class="Default"><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">与异常不同的是</span><span style="font-family: 'Times New Roman'; color: windowtext; font-size: 10.5pt">Error</span><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">及其子类的对象不应被抛出。</span></p>
<p style="margin: 0cm 0cm 0pt" class="Default"><span style="font-family: 'Times New Roman'; color: windowtext; font-size: 10.5pt">Error </span><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">是</span><span style="font-family: 'Times New Roman'; color: windowtext; font-size: 10.5pt"> Throwable </span><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">的子类，代表编译时间和系统错误，用于指示合理的应用程序</span><strong><span style="font-family: 宋体; color: red; font-size: 10.5pt">不应该试图捕获</span></strong><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">的严重问题。大多数这样的错误都是异常条件。虽然</span><span style="font-family: 'Times New Roman'; color: windowtext; font-size: 10.5pt"> ThreadDeath </span><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">错误是一个</span><span style="font-family: 'Times New Roman'; color: windowtext; font-size: 10.5pt">&#8220;</span><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">正规</span><span style="font-family: 'Times New Roman'; color: windowtext; font-size: 10.5pt">&#8221;</span><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">的条件，但它也是</span><span style="font-family: 'Times New Roman'; color: windowtext; font-size: 10.5pt"> Error </span><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">的子类，因为大多数应用程序都不应该试图捕获它。</span></p>
<p style="margin: 0cm 0cm 0pt" class="Default"><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">在执行该方法期间，</span><strong><span style="font-family: 宋体; color: red; font-size: 10.5pt">无需在其</span></strong><strong><span style="font-family: 'Times New Roman'; color: red; font-size: 10.5pt"> throws </span></strong><strong><span style="font-family: 宋体; color: red; font-size: 10.5pt">子句中声明可能抛出但是未能捕获</span></strong><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">的</span><span style="font-family: 'Times New Roman'; color: windowtext; font-size: 10.5pt"> Error </span><span style="font-family: 宋体; color: windowtext; font-size: 10.5pt">的任何子类，因为这些错误可能是再也不会发生的异常条件。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: small"><span style="font-family: 宋体">它是</span><span style="font-family: Times New Roman">uncheckedExcepiton</span><span style="font-family: 宋体">。</span></span></p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298342.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-15 11:03 <a href="http://www.blogjava.net/balajinima/articles/298342.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Set中equals()和hashCode()</title><link>http://www.blogjava.net/balajinima/articles/298260.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Wed, 14 Oct 2009 09:41:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298260.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298260.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298260.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298260.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298260.html</trackback:ping><description><![CDATA[<p>equals()是判读两个Set是否相等[前提是equals()在类中被覆盖]。==决定引用值是否指向同一对象。</p>
<p>1、当向集合set中增加对象时，首先计算要增加对象的hashCode码，根据该值来得到一个位置来存放当前的对象，当在该位置没有一个对象存在的话，那么集合set认为该对象在集合中不存在，直接增加进去。如果在该位置有一个对象的话，接着将准备增加到集合中的对象与该位置上的对象进行equals方法比较，如果该equals方法返回false，那么集合认为集合中不存在该对象，再进行一次散列，将该对象放到散列后计算出的新地址里，如果equals方法返回true，那么集合认为集合中已经存在该对象了，不会再将该对象增加到集合中了。</p>
<p>2、当重写equals方法时，必须要重写hashCode方法。在java的集合中，判断两个对象是否相等的规则是：</p>
<p>1)，判断两个对象的hashCode是否相等 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果不相等，认为两个对象也不相等，完毕 ； 如果相等，转入2 </p>
<p>2)，判断两个对象用equals运算是否相等 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果不相等，认为两个对象也不相等 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果相等，认为两个对象相等（equals()是判断两个对象是否相等的关键） </p>
<p>&nbsp;&nbsp;&nbsp; 可见hashcode()相等时，equals()方法也可能不等。 </p>
<p>public static void main(String args[]){ </p>
<p>String s1=new String("zhaoxudong"); //此语句创建了两个对象，一个是字符串对象&#8220;zhaoxudong&#8221;（存放于栈中的字面量），另一个是new后在堆中产生的对象。详细见下面的四.4</p>
<p>String s2=new String("zhaoxudong"); </p>
<p>//上述两条语句一共是产生了三个对象，因为栈中只有产生了一个对象。</p>
<p>System.out.println(s1==s2);//false </p>
<p>System.out.println(s1.equals(s2));//true </p>
<p>System.out.println(s1.hashCode());//s1.hashcode()等于s2.hashcode() ，指向同一内存的引用</p>
<p>System.out.println(s2.hashCode()); //equals和hashCode方法只用于两个对象的比较和容器中，与对象的创建没有关系</p>
<p>Set hashset=new HashSet(); </p>
<p>hashset.add(s1); </p>
<p>hashset.add(s2); /*在添加s1,s2时， hashset认为s1和s2是相等的，所以让s2覆盖了s1;*/ </p>
<p>Iterator it=hashset.iterator(); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(it.hasNext()){ </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(it.next()); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } //最后在while循环的时候只打印出了一个&#8221;zhaoxudong&#8221;。 </p>
<p>这是因为String类已经重写了equals()方法和hashcode()方法。 </p>
<p>但是看下面的程序： </p>
<p>public class HashSetTest { </p>
<p>&nbsp;&nbsp; public static void main(String[] args)&nbsp;&nbsp; { </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HashSet hs=new HashSet(); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hs.add(new Student(1,"zhangsan")); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hs.add(new Student(2,"lisi")); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hs.add(new Student(3,"wangwu")); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hs.add(new Student(1,"zhangsan")); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Iterator it=hs.iterator(); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(it.hasNext()){ </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(it.next()); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } } } </p>
<p>class Student { </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; int num; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; String name; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; Student(int num,String name) { </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.num=num; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.name=name; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; public String toString() { return num+":"+name; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>输出结果为： </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1:zhangsan </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1:zhangsan </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3:wangwu </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2:lisi </p>
<p>问题出现了，为什么hashset添加了相等的元素呢，这是不是和hashset的原则违背了呢？回答是：没有因为在根据hashcode()对两次建立的new Student(1,"zhangsan")对象进行比较时，生成的是不同的哈希码值，所以hashset把他当作不同的对象对待了，当然此时的equals()方法返回的值也不等。那么为什么会生成不同的哈希码值呢？原因就在于我们自己写的Student类并没有重新自己的hashcode()和equals()方法，所以在比较时，是继承的object类中的hashcode()方法，它是一个本地方法，比较的是对象的地址（引用地址），使用new方法创建对象，两次生成的当然是不同的对象了，造成的结果就是两个对象的hashcode()返回的值不一样。那么怎么解决这个问题呢？？ </p>
<p>答案是：在Student类中重新hashcode()和equals()方法。 </p>
<p>例如： </p>
<p>class Student{ </p>
<p>int num; </p>
<p>String name; </p>
<p>Student(int num,String name){ </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.num=num; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.name=name; } </p>
<p>public int hashCode(){ //重写hashCode的方法</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return num*name.hashCode(); } </p>
<p>public boolean equals(Object o) { </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Student s=(Student)o; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return num==s.num &amp;&amp; name.equals(s.name); //&amp;&amp;的优先级比==低，所以前面不必加括号</p>
<p>} </p>
<p>public String toString(){return num+":"+name; } </p>
<p>} </p>
<p>根据重写的方法，即便两次调用了new Student(1,"zhangsan")，我们在获得对象的哈希码时，根据重写的方法hashcode()，获得的哈希码肯定是一样的。所以运行修改后的程序时，我们会看到重复元素的问题已经消除。 </p>
<p>在hibernate的pojo类中，经常使用set集合来保存相关对象，而set集合是不允许重复的。所以需要重写equals和hashCode()方法。 </p>
<p>比如可以这样写： </p>
<p>public int hashCode(){ </p>
<p>&nbsp;&nbsp; return 1;}//等价于hashcode无效 </p>
<p>这样做的效果就是在比较哈希码的时候不能进行判断，因为每个对象返回的哈希码都是1，每次都必须要经过比较equals()方法后才能进行判断是否重复，这当然会引起效率的大大降低。 </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/elia1208/archive/2009/10/12/4657644.aspx</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298260.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-14 17:41 <a href="http://www.blogjava.net/balajinima/articles/298260.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java多线程_创建线程的两种方式</title><link>http://www.blogjava.net/balajinima/articles/298239.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Wed, 14 Oct 2009 09:10:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298239.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298239.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298239.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298239.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298239.html</trackback:ping><description><![CDATA[<p>&nbsp;一、什么是线程</p>
<p>线程是一个程序内部的顺序控制流。</p>
<p>线程和进程</p>
<p>1.进程：每个进程都有独立的代码和数据空间，进程切换开销大。</p>
<p>2.线程：轻量的进程，同一个线程共享代码和数据空间，每个线程有独立运行的栈和程序计数器（PC），线程切换的开销小。</p>
<p>3.在操作系统中能同时运行多个任务（程序）。</p>
<p>4.在同一应用程序有多个顺序流同时执行。</p>
<p><br />
问题：对于单核的CPU，处理多个任务时。并不会同时真正的运两个以上的程序。那么它是怎样做到处理多任务的呢？</p>
<p>解答：实际上是操作系统负责对处理器就是CPU等资源进行分配组织和管理。实际上每一时刻只能做一件事，或者运行某一个程序。由于在操作系统的管理下，CPU的处理功能被以非常小的时间间隔进行划分、进行交替，每一个小的时间间隔我们称为时间片。当时间片到期之后将去执行下一个程序。由于交替的速度非常的快，这样就给人一种同时运行多个应用程序或者同时做多件事的一种感觉。这种情况我们称为并发执行。也就是假的，模拟的，通过快速的交替，表现成在同时做多件事。</p>
<p><br />
并行执行才是真正意义上的同一时刻做多个事情，同一个瞬间运行不同的应用程序。这样就要求有多个CPU。支持程序并发运行的操作系统我们称为多任务的操作系统或者说是多进程的操作系统。</p>
<p><br />
并发性的工作原理还可以应用在更高的层面上，我们可以在一个应用程序的内部，把它要完成的任务分解为多个更小的子任务以多条齐头并进的线索来并发的执行，这种就称为线程或多线程。</p>
<p><br />
二、线程的概念模型</p>
<p>Java语言实现或支持多线程的工作方式。</p>
<p>一个线程必须具备以下三方面的要素才能正常的工作。</p>
<p>1.虚拟的CPU，由java.lang.Thread类封装和虚拟。</p>
<p>2.CPU所执行的代码，传递给Thread类的对象。</p>
<p>3.CPU所处理的数据，传递给Thread类的对象。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>三、创建线程</p>
<p>第一种方式：使用Runnable接口创建线程</p>
<p><br />
1.Java的线程是通过java.lang.Thread类来实现。</p>
<p>2.每个线程都是通过某个特定的Thread对象所对应的run()方法来完成其操作。方法run()称为线程体。</p>
<p>例1：</p>
<p>public class Thread1{</p>
<p>public static void main(String[] args){</p>
<p>Runner1 r=new Runner1();//2.创建实现Runnable接口的对象</p>
<p>Thread t=new Thread(r); //3.创建一个Thread类的对象</p>
<p>t.start(); //4.启动线程</p>
<p>}</p>
<p><br />
}</p>
<p>class Runner1 implements Runnable{//1.Runner1实现Runnable接口</p>
<p>public void run(){</p>
<p>for(int i=1;i&lt;20;i++){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(i);</p>
<p>}</p>
<p>}&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>}</p>
<p>程序运行的结果是输出1到19个数字。与在main（）方法中直接写for循环是一样的效果。</p>
<p>但实现的原理不一样。</p>
<p>使用线程输出的有两个线程（main()主线程和t子线程），不使用只有一个线程。</p>
<p>创建线程的三个步骤</p>
<p>1.定义一个类实现Runnable接口，重写接口中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。</p>
<p>2.创建Runnable接口实现类的对象。</p>
<p>3.创建一个Thread类的对象，需要封装前面Runnable接口实现类的对象。（接口可以实现多继承）</p>
<p>4.调用Thread对象的start()方法，启动线程</p>
<p>第二种方式：直接继承Thread类创建对象</p>
<p><br />
例2：</p>
<p>public class Thread2{</p>
<p>public static void main(String[] args){</p>
<p>Thread t=new Runner2();</p>
<p>t.start();</p>
<p>}</p>
<p><br />
}</p>
<p>class Runner2 extends Thread{</p>
<p>public void run(){</p>
<p>for(int i=1;i&lt;20;i++){</p>
<p>String s=Thread.currentThread().getName();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(s+":"+i);</p>
<p>}</p>
<p>}&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>}</p>
<p>1.首先定义一个类去继承Thread父类，此时Runner2类并没有直接的实现Runnable接口，但其实Thread类在JDK中已经实现了Runnable接口。这样就Runner2类间接的实现了Runnable接口。重写父类中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。</p>
<p><br />
2.直接创建一个Runner2类的对象，也可以利用多态性，变量t声明为父类的类型。</p>
<p>3.线程t启动，隐含的调用run()方法。</p>
<p>比较两种方式：</p>
<p>a.使用Runnable接口创建线程</p>
<p>1.可以将CPU，代码和数据分开，形成清晰的模型</p>
<p>2.线程体run()方法所在的类可以从其它类中继承一些有用的属性和方法</p>
<p>3.有利于保持程序的设计风格一致</p>
<p>b.直接继承Thread类创建对象</p>
<p>1.Thread子类无法再从其它类继承（java语言的单继承）。</p>
<p>2.编写简单，run()方法的当前对象就是线程对象，可直接操作。</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298239.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-14 17:10 <a href="http://www.blogjava.net/balajinima/articles/298239.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java笔试题 常见题</title><link>http://www.blogjava.net/balajinima/articles/298226.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Wed, 14 Oct 2009 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298226.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298226.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298226.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298226.html</trackback:ping><description><![CDATA[<p>1、面向对象的特征有哪些方面 <br />
(1)抽象：<br />
抽象就是忽略一个主题中与当前目标无关的那些方面，以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题，而只是选择其中的一部分，暂时不用部分细节。抽象包括两个方面，一是过程抽象，二是数据抽象。<br />
(2)继承：<br />
继承是一种联结类的层次模型，并且允许和鼓励类的重用，它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生，这个过程称为类继承。新类继承了原始类的特性，新类称为原始类的派生类（子类），而原始类称为新类的基类（父类）。派生类可以从它的基类那里继承方法和实例变量，并且类可以修改或增加新的方法使之更适合特殊的需要。<br />
(3)封装：<br />
封装是把过程和数据包围起来，对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念，即现实世界可以被描绘成一系列完全自治、封装的对象，这些对象通过一个受保护的接口访问其他对象。<br />
(4) 多态性：<br />
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势，很好的解决了应用程序函数同名问题。</p>
<p>2、String是最基本的数据类型吗?<br />
基本数据类型包括byte、int、char、long、float、double、boolean和short。<br />
java.lang.String类是final类型的，因此不可以继承这个类、不能修改这个类。为了提高效率节省空间，我们应该用StringBuffer类</p>
<p>3、int 和 Integer 有什么区别<br />
Java 提供两种不同的类型：引用类型和原始类型（或内置类型）。Int是java的原始数据类型，Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。<br />
原始类型封装类<br />
booleanBoolean<br />
charCharacter<br />
byteByte<br />
shortShort<br />
intInteger<br />
longLong<br />
floatFloat<br />
doubleDouble<br />
引用类型和原始类型的行为完全不同，并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法，它们包括：大小和速度问题，这种类型以哪种类型的数据结构存储，当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null，而原始类型实例变量的缺省值与它们的类型有关。</p>
<p>4、String 和StringBuffer的区别<br />
JAVA 平台提供了两个类：String和StringBuffer，它们可以储存和操作字符串，即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地，你可以使用StringBuffers来动态构造字符数据。</p>
<p>5、运行时异常与一般异常有何异同？<br />
异常表示程序运行过程中可能出现的非正常状态，运行时异常表示虚拟机的通常操作中可能遇到的异常，是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常，但是并不要求必须声明抛出未被捕获的运行时异常。</p>
<p>6、说出Servlet的生命周期，并说出Servlet和CGI的区别。<br />
Servlet被服务器实例化后，容器运行其init方法，请求到达时运行其service方法，service方法自动派遣运行与请求对应的doXXX方法（doGet，doPost）等，当服务器决定将实例销毁的时候调用其destroy方法。<br />
与cgi的区别在于servlet处于服务器进程中，它通过多线程方式运行其service方法，一个实例可以服务于多个请求，并且其实例一般不会销毁，而CGI对每个请求都产生新的进程，服务完成后就销毁，所以效率上低于servlet。</p>
<p>7、说出ArrayList,Vector, LinkedList的存储性能和特性<br />
ArrayList 和Vector都是使用数组方式存储数据，此数组元素数大于实际存储的数据以便增加和插入元素，它们都允许直接按序号索引元素，但是插入元素要涉及数组元素移动等内存操作，所以索引数据快而插入数据慢，Vector由于使用了synchronized方法（线程安全），通常性能上较ArrayList差，而LinkedList使用双向链表实现存储，按序号索引数据需要进行前向或后向遍历，但是插入数据时只需要记录本项的前后项即可，所以插入速度较快。</p>
<p>8、EJB是基于哪些技术实现的？并说出SessionBean和EntityBean的区别，StatefulBean和StatelessBean的区别。<br />
EJB包括Session Bean、Entity Bean、Message Driven Bean，基于JNDI、RMI、JAT等技术实现。<br />
SessionBean在J2EE应用程序中被用来完成一些服务器端的业务操作，例如访问数据库、调用其他EJB组件。EntityBean被用来代表应用系统中用到的数据。<br />
对于客户机，SessionBean是一种非持久性对象，它实现某些在服务器上运行的业务逻辑。<br />
对于客户机，EntityBean是一种持久性对象，它代表一个存储在持久性存储器中的实体的对象视图，或是一个由现有企业应用程序实现的实体。<br />
Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ，这两种的 Session Bean都可以将系统逻辑放在 method之中执行，不同的是 Stateful Session Bean 可以记录呼叫者的状态，因此通常来说，一个使用者会有一个相对应的 Stateful Session Bean 的实体。Stateless Session Bean 虽然也是逻辑组件，但是他却不负责记录使用者状态，也就是说当使用者呼叫 Stateless Session Bean 的时候，EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method。换言之，很可能数个使用者在执行某个 Stateless Session Bean 的 methods 时，会是同一个 Bean 的 Instance 在执行。从内存方面来看， Stateful Session Bean 与 Stateless Session Bean 比较， Stateful Session Bean 会消耗 J2EE Server 较多的内存，然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。</p>
<p>9、Collection 和 Collections的区别。 <br />
　　Collection是集合类的上级接口，继承与他的接口主要有Set 和List.<br />
Collections是针对集合类的一个帮助类，他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。</p>
<p>10、&amp;和&amp;&amp;的区别。 <br />
&amp;是位运算符，表示按位与运算，&amp;&amp;是逻辑运算符，表示逻辑与（and）。</p>
<p>11、HashMap和Hashtable的区别。 <br />
HashMap是Hashtable的轻量级实现（非线程安全的实现），他们都完成了Map接口，主要区别在于HashMap允许空（null）键值（key）,由于非线程安全，效率上可能高于Hashtable。<br />
HashMap允许将null作为一个entry的key或者value，而Hashtable不允许。<br />
HashMap把Hashtable的contains方法去掉了，改成containsvalue和containsKey。因为contains方法容易让人引起误解。 <br />
Hashtable继承自Dictionary类，而HashMap是Java1.2引进的Map interface的一个实现。<br />
最大的不同是，Hashtable的方法是Synchronize的，而HashMap不是，在多个线程访问Hashtable时，不需要自己为它的方法实现同步，而HashMap 就必须为之提供外同步。 <br />
Hashtable和HashMap采用的hash/rehash算法都大概一样，所以性能不会有很大的差异。</p>
<p>12、final, finally, finalize的区别。 <br />
final 用于声明属性，方法和类，分别表示属性不可变，方法不可覆盖，类不可继承。<br />
finally是异常处理语句结构的一部分，表示总是执行。<br />
finalize是Object类的一个方法，在垃圾收集器执行的时候会调用被回收对象的此方法，可以覆盖此方法提供垃圾收集时的其他资源回收，例如关闭文件等。</p>
<p>13、sleep() 和 wait() 有什么区别? <br />
sleep是线程类（Thread）的方法，导致此线程暂停执行指定时间，把执行机会给其他线程，但是监控状态依然保持，到时后会自动恢复。调用sleep不会释放对象锁。<br />
wait是Object类的方法，对此对象调用wait方法导致本线程放弃对象锁，进入等待此对象的等待锁定池，只有针对此对象发出notify方法（或notifyAll）后本线程才进入对象锁定池准备获得对象锁进入运行状态。</p>
<p>14、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?<br />
方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现，重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数，我们说该方法被重写 (Overriding)。子类的对象使用这个方法时，将调用子类中的定义，对它而言，父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法，它们或有不同的参数个数或有不同的参数类型，则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。&nbsp;</p>
<p><br />
15、error和exception有什么区别?<br />
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。<br />
exception 表示一种设计或实现问题。也就是说，它表示如果程序运行正常，从不会发生的情况。</p>
<p>16、同步和异步有何异同，在什么情况下分别使用他们？举例说明。<br />
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到，或者正在读的数据可能已经被另一个线程写过了，那么这些数据就是共享数据，必须进行同步存取。<br />
当应用程序在对象上调用了一个需要花费很长时间来执行的方法，并且不希望让程序等待方法的返回时，就应该使用异步编程，在很多情况下采用异步途径往往更有效率。</p>
<p>17、abstract class和interface有什么区别?<br />
声明方法的存在而不去实现它的类被叫做抽象类（abstract class），它用于要创建一个体现某些基本行为的类，并为该类声明方法，但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量，其类型是一个抽象类，并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现，否则它们也是抽象类为。取而代之，在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。<br />
接口（interface）是抽象类的变体。在接口中，所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的，没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似，除了该实现类不能从接口定义中继承行为。当类实现特殊接口时，它定义（即将程序体给予）所有这种接口的方法。然后，它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类，它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换，instanceof 运算符可以用来决定某对象的类是否实现了接口。</p>
<p>18、heap和stack有什么区别。<br />
栈是一种线形集合，其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。<br />
堆是栈的一个组成元素</p>
<p>19、forward 和redirect的区别<br />
forward是服务器请求资源，服务器直接访问目标地址的URL，把那个URL的响应内容读取过来，然后把这些内容再发给浏览器，浏览器根本不知道服务器发送的内容是从哪儿来的，所以它的地址栏中还是原来的地址。<br />
redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址，一般来说浏览器会用刚才请求的所有参数重新请求，所以session,request参数都可以获取。</p>
<p>20、EJB与JAVA BEAN的区别？<br />
</p>
<p>21、Static Nested Class 和 Inner Class的不同。 <br />
Static Nested Class是被声明为静态（static）的内部类，它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化。</p>
<p>22、JSP中动态INCLUDE与静态INCLUDE的区别？<br />
&nbsp;&lt;jsp:include page="included.html" flush="true" /&gt; （动态包含）<br />
&nbsp;&lt;%@ include file="included.html" %&gt;（静态包含）<br />
<br />
include指令是静态包含页面，include动作是动态包含页面。二者的区别是静态包含不管三七二十一先把内容(代码)包含进来，然后作为一个文件进行处理；动态包含是先进行处理所包含的文件，然后将处理结果包含进来。简单说，一个是把代码包含进来，一个是把结果包含进来。<br />
静态包含，发生在JSP转换成Servlet的阶段，最后转换成的Servlet源文件及class文件都只有一个。<br />
动态包含，发生在执行阶段，原文件和被包含的文件（如果是jsp文件的话）都会生成自己的Servlet源文件及class文件。<br />
<br />
flush 属性 </p>
<p>您可能已注意到 jsp:include 代码示例中的 flush 属性。顾名思义， flush 指示在读入包含内容之前是否清空任何现有的缓冲区。JSP 1.1 中需要 flush 属性，因此，如果代码中不用它，会得到一个错误。但是，在 JSP 1.2 中， flush 属性缺省为 false。由于清空大多数时候不是一个重要的问题，因此，我的建议是：对于 JSP 1.1，将 flush 设置为 true；而对于 JSP 1.2 及更高版本，将其设置为关闭。</p>
<p>一种混合搭配的解决方案 </p>
<p>include 伪指令在某些网站上有其用武之地。例如，如果站点包含一些（如果有变化，也很少）几乎没有变化的页眉、页脚和导航文件，那么基本的 include 伪指令是这些组件的最佳选项。由于 include 伪指令采用了高速缓存，因此只需放入包含文件一次，其内容就会被高速缓存，其结果会是极大地提高了站点的性能。</p>
<p>然而，对于现在许多 Web 应用程序或站点而言，地毯式的高速缓存并不能解决问题。虽然页眉和页脚可能是静态的，但是不可能整个站点都是静态的。例如，从数据库提取导航链接是很常见的，并且许多基于 JSP 技术的站点还从其它站点或应用程序上的动态 JSP 页面提取内容。如果正在处理动态内容，那么需要采用 jsp:include 来处理该内容。</p>
<p><br />
<br />
23、什么时候用assert。 <br />
assertion (断言)在软件开发中是一种常用的调试方式，很多开发语言中都支持这种机制。在实现中，assertion就是在程序中的一条语句，它对一个 boolean表达式进行检查，一个正确程序必须保证这个boolean表达式的值为true；如果该值为false，说明程序已经处于不正确的状态下，系统将给出警告或退出。一般来说，assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能，在软件发布后，assertion检查通常是关闭的。&nbsp;</p>
<p>24、GC是什么? 为什么要有GC? <br />
　 　GC是垃圾收集的意思（Gabage Collection）,内存处理是编程人员容易出现问题的地方，忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃，Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的，Java语言没有提供释放已分配内存的显示操作方法。</p>
<p>25、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错? <br />
short s1 = 1; s1 = s1 + 1; （s1+1运算结果是int型，需要强制转换类型）<br />
short s1 = 1; s1 += 1;（可以正确编译）</p>
<p>26、Math.round(11.5)等於多少? Math.round(-11.5)等於多少? <br />
Math.round(11.5)==12<br />
Math.round(-11.5)==-11<br />
round方法返回与参数最接近的长整数，参数加1/2后求其floor.<br />
floor是java.lang.Math中的方法，Math.floor(X);是求出比数X大的最小整数；例如double X=2.6;那么System.out.println(Math.floor(X));输出值就为3. <br />
</p>
<p>27、String s = new String("xyz");创建了几个String Object? <br />
两个(一个是&#8220;xyx&#8221;,一个是指向&#8220;xyx&#8221;的引用对象s)</p>
<p>28、设计4个线程，其中两个线程每次对j增加1，另外两个线程对j每次减少1。写出程序。<br />
以下程序使用内部类实现线程，对j增减的时候没有考虑顺序问题。<br />
public class ThreadTest1{<br />
private int j;<br />
public static void main(String args[]){<br />
ThreadTest1 tt=new ThreadTest1();<br />
Inc inc=tt.new Inc();<br />
Dec dec=tt.new Dec();<br />
for(int i=0;i&lt;2;i++){<br />
Thread t=new Thread(inc);<br />
t.start();<br />
t=new Thread(dec);<br />
t.start();<br />
}<br />
}<br />
private synchronized void inc(){<br />
j++;<br />
System.out.println(Thread.currentThread().getName()+"-inc:"+j);<br />
}<br />
private synchronized void dec(){<br />
j--;<br />
System.out.println(Thread.currentThread().getName()+"-dec:"+j);<br />
}<br />
class Inc implements Runnable{<br />
public void run(){<br />
for(int i=0;i&lt;100;i++){<br />
inc();<br />
}<br />
}<br />
}<br />
class Dec implements Runnable{<br />
public void run(){<br />
for(int i=0;i&lt;100;i++){<br />
dec();<br />
}<br />
}<br />
}<br />
}<br />
附：<br />
创建多线的方法<br />
http://www.blogjava.net/balajinima/articles/298239.html</p>
<p>29、Java有没有goto?<br />
java中的保留字，现在没有在java中使用。</p>
<p>30、启动一个线程是用run()还是start()?<br />
启动一个线程是调用start()方法，使线程所代表的虚拟处理机处于可运行状态，这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。<br />
</p>
<p>31、EJB包括（SessionBean,EntityBean）说出他们的生命周期，及如何管理事务的？<br />
SessionBean： Stateless Session Bean 的生命周期是由容器决定的，当客户机发出请求要建立一个Bean的实例时，EJB容器不一定要创建一个新的Bean的实例供客户机调用，而是随便找一个现有的实例提供给客户机。当客户机第一次调用一个Stateful Session Bean 时，容器必须立即在服务器中创建一个新的Bean实例，并关联到客户机上，以后此客户机调用Stateful Session Bean 的方法时容器会把调用分派到与此客户机相关联的Bean实例。<br />
EntityBean：Entity Beans能存活相对较长的时间，并且状态是持续的。只要数据库中的数据存在，Entity beans就一直存活。而不是按照应用程序或者服务进程来说的。即使EJB容器崩溃了，Entity beans也是存活的。Entity Beans生命周期能够被容器或者 Beans自己管理。<br />
EJB通过以下技术管理实务：对象管理组织（OMG）的对象实务服务（OTS），Sun Microsystems的Transaction Service（JTS）、Java Transaction API（JTA），开发组（X/Open）的XA接口。</p>
<p>32、应用服务器有那些？<br />
BEA WebLogic Server，IBM WebSphere Application Server，Oracle9i Application Server，jBoss，Tomcat</p>
<p>33、给我一个你最常见到的runtime exception。<br />
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException</p>
<p>34、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?<br />
接口可以继承接口。抽象类可以实现(implements)接口，抽象类是否可继承实体类，但前提是实体类必须有明确的构造函数。</p>
<p>35、List, Set, Map是否继承自Collection接口?<br />
List，Set是，Map不是</p>
<p>36、说出数据连接池的工作机制是什么?<br />
J2EE 服务器启动时会建立一定数量的池连接，并一直维持不少于此数目的池连接。客户端程序需要连接时，池驱动程序会返回一个未使用的池连接并将其表记为忙。如果当前没有空闲连接，池驱动程序就新建一定数量的连接，新建连接的数量由配置参数决定。当使用的池连接调用完成后，池驱动程序将此连接表记为空闲，其他调用就可以使用这个连接。</p>
<p>37、abstract的method是否可同时是static,是否可同时是native，是否可同时是synchronized?<br />
都不能</p>
<p>38、数组有没有length()这个方法? String有没有length()这个方法？<br />
数组没有length()这个方法，有length的属性。String有有length()这个方法。</p>
<p>39*、Set里的元素是不能重复的，那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?<br />
Set里的元素是不能重复的，那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。<br />
equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖，为的是当两个分离的对象的内容和类型相配的话，返回真值。</p>
<p>40、构造器Constructor是否可被override?<br />
构造器Constructor不能被继承，因此不能重写Overriding，但可以被重载Overloading。</p>
<p>41、是否可以继承String类?<br />
String类是final类故不可以继承。</p>
<p>42、swtich是否能作用在byte上，是否能作用在long上，是否能作用在String上?<br />
switch（expr1）中，expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是int、 short、 char 或者 byte。long,string 都不能作用于swtich。</p>
<p>43、try {}里有一个return语句，那么紧跟在这个try后的finally {}里的co<wbr>de会不会被执行，什么时候被执行，在return前还是后?<br />
会执行，在return前执行。</p>
<p>44、编程题: 用最有效率的方法算出2乘以8等於几? <br />
2 &lt;&lt; 3　(有C背景的程序员特别喜欢问这种问题)</p>
<p>45、两个对象值相同(x.equals(y) == true)，但却可有不同的hash co<wbr>de，这句话对不对?<br />
不对，有相同的hash co<wbr>de。</p>
<p>46、当一个对象被当作参数传递到一个方法后，此方法可改变这个对象的属性，并可返回变化后的结果，那么这里到底是值传递还是引用传递? <br />
是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时，参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变，但对象的引用是永远不会改变的。</p>
<p>47、当一个线程进入一个对象的一个synchronized方法后，其它线程是否可进入此对象的其它方法?<br />
不能，一个对象的一个synchronized方法只能由一个线程访问。</p>
<p>48、编程题: 写一个Singleton出来。<br />
Singleton模式主要作用是保证在Java应用程序中，一个类Class只有一个实例存在。<br />
一般Singleton模式通常有几种种形式:<br />
第一种形式: 定义一个类，它的构造函数为private的，它有一个static的private的该类变量，在类初始化时实例话，通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。<br />
public class Singleton {<br />
private Singleton(){}<br />
　　 //在自己内部定义自己一个实例，是不是很奇怪？<br />
　　 //注意这是private 只供内部调用<br />
　　 private static Singleton instance = new Singleton();<br />
　　 //这里提供了一个供外部访问本class的静态方法，可以直接访问　　<br />
　　 public static Singleton getInstance() {<br />
　　　　 return instance; 　　<br />
　　 } <br />
} <br />
第二种形式: <br />
public class Singleton { <br />
　　private static Singleton instance = null;<br />
　　public static synchronized Singleton getInstance() {<br />
　　//这个方法比上面有所改进，不用每次都进行生成对象，只是第一次　　　　<br />
　　//使用时生成实例，提高了效率！<br />
　　if (instance==null)<br />
　　　　instance＝new Singleton();<br />
return instance; 　　} <br />
} <br />
其他形式:<br />
定义一个类，它的构造函数为private的，所有方法为static的。<br />
一般认为第一种形式要更加安全些</p>
<p>49、Java的接口和C++的虚类的相同和不同处。<br />
由于Java不支持多继承，而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性，现有的单继承机制就不能满足要求。与继承相比，接口有更高的灵活性，因为接口中没有任何实现代码。当一个类实现了接口以后，该类要实现接口里面所有的方法和属性，并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public.一个类可以实现多个接口。</p>
<p>50、Java中的异常处理机制的简单原理和应用。<br />
当JAVA 程序违反了JAVA的语义规则时，JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAVA允许程序员扩展这种语义检查，程序员可以创建自己的异常，并自由选择在何时用throw关键字引发异常。所有的异常都是 java.lang.Thowable的子类。<br />
<br />
附：<br />
java异常分类<br />
http://www.blogjava.net/balajinima/articles/298342.html</p>
<p>51、垃圾回收的优点和原理。并考虑2种回收机制。<br />
Java 语言中一个显著的特点就是引入了垃圾回收机制，使c++程序员最头疼的内存管理的问题迎刃而解，它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制，Java中的对象不再有"作用域"的概念，只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露，有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行，不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收，程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收，增量垃圾回收。</p>
<p>52、请说出你所知道的线程同步的方法。<br />
wait():使一个线程处于等待状态，并且释放所持有的对象的lock。<br />
sleep():使一个正在运行的线程处于睡眠状态，是一个静态方法，调用此方法要捕捉InterruptedException异常。<br />
notify():唤醒一个处于等待状态的线程，注意的是在调用此方法的时候，并不能确切的唤醒某一个等待状态的线程，而是由JVM确定唤醒哪个线程，而且不是按优先级。</p>
<p>Allnotity():唤醒所有处入等待状态的线程，注意并不是给所有唤醒线程一个对象的锁，而是让它们竞争。</p>
<p>53、你所知道的集合类都有哪些？主要方法？<br />
最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector，它们是可变大小的列表，比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。 <br />
Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对（称作"键"和"值"），其中每个键映射到一个值。</p>
<p>54、描述一下JVM加载class文件的原理机制?<br />
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。</p>
<p>55、char型变量中能不能存贮一个中文汉字?为什么? <br />
能够定义成为一个中文的，因为java中以unicode编码，一个char占16个字节，所以放一个中文是没问题的</p>
<p>56、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? <br />
多线程有两种实现方法，分别是继承Thread类与实现Runnable接口 <br />
同步的实现方面有两种，分别是synchronized,wait与notify</p>
<p>57、JSP的内置对象及方法。<br />
request表示HttpServletRequest对象。它包含了有关浏览器请求的信息，并且提供了几个用于获取cookie, header, 和session数据的有用的方法。 <br />
response表示HttpServletResponse对象，并提供了几个用于设置送回浏览器的响应的方法（如cookies,头信息等） <br />
out对象是javax.jsp.JspWriter的一个实例，并提供了几个方法使你能用于向浏览器回送输出结果。 <br />
pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API，并且包装了通用的servlet相关功能的方法。 <br />
session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息 <br />
applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息 <br />
config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。 <br />
page表示从该页面产生的一个servlet实例</p>
<p>58、线程的基本概念、线程的基本状态以及状态之间的关系<br />
线程指在程序执行过程中，能够执行程序代码的一个执行单位，每个程序至少都有一个线程，也就是程序本身。<br />
Java中的线程有四种状态分别是：运行、就绪、挂起、结束。</p>
<p>59、JSP的常用指令</p>
<p>isErrorPage(是否能使用Exception对象)，isELIgnored(是否忽略表达式)</p>
<p>" target="_blank"&gt;http://......"%&gt; </p>
<p>60、什么情况下调用doGet()和doPost()？<br />
Jsp页面中的form标签里的method属性为get时调用doGet()，为post时调用doPost()。</p>
<p>61、servlet的生命周期<br />
web容器加载servlet，生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现，根据请求的不同调用不同的do***()方法。结束服务，web容器调用servlet的destroy()方法。</p>
<p>62、如何现实servlet的单线程模式<br />
实现 SingleThreadModel 接口<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行，当然也就不存在线程安全的问题。如：<br />
<br />
public class Concurrent Test extends HttpServlet implements SingleThreadModel {<br />
&#8230;&#8230;&#8230;&#8230;<br />
}</p>
<p>63、页面间对象传递的方法<br />
request，session，application，cookie等</p>
<p>64、JSP和Servlet有哪些相同点和不同点，他们之间的联系是什么？ <br />
JSP 是Servlet技术的扩展，本质上是Servlet的简易方式，更强调应用的外表表达。JSP编译后是"类servlet"。Servlet和JSP最主要的不同点在于，Servlet的应用逻辑是在Java文件中，并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图，Servlet主要用于控制逻辑。</p>
<p>65、四种会话跟踪技术<br />
会话作用域ServletsJSP 页面描述<br />
page否是代表与一个页面相关的对象和属性。一个页面由一个编译好的 Java servlet 类（可以带有任何的 include 指令，但是没有 include 动作）表示。这既包括 servlet 又包括被编译成 servlet 的 JSP 页面<br />
request是是代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面，涉及多个 Web 组件（由于 forward 指令和 include 动作的关系）<br />
session是是代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求<br />
application是是代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序，包括多个页面、请求和会话的一个全局作用域</p>
<p>66、Request对象的主要方法：<br />
setAttribute(String name,Object)：设置名字为name的request的参数值<br />
getAttribute(String name)：返回由name指定的属性值<br />
getAttributeNames()：返回request对象所有属性的名字集合，结果是一个枚举的实例<br />
getCookies()：返回客户端的所有Cookie对象，结果是一个Cookie数组<br />
getCharacterEncoding()：返回请求中的字符编码方式<br />
getContentLength()：返回请求的Body的长度<br />
getHeader(String name)：获得HTTP协议定义的文件头信息<br />
getHeaders(String name)：返回指定名字的request Header的所有值，结果是一个枚举的实例<br />
getHeaderNames()：返回所以request Header的名字，结果是一个枚举的实例<br />
getInputStream()：返回请求的输入流，用于获得请求中的数据<br />
getMethod()：获得客户端向服务器端传送数据的方法<br />
getParameter(String name)：获得客户端传送给服务器端的有name指定的参数值<br />
getParameterNames()：获得客户端传送给服务器端的所有参数的名字，结果是一个枚举的实例<br />
getParameterValues(String name)：获得有name指定的参数的所有值<br />
getProtocol()：获取客户端向服务器端传送数据所依据的协议名称<br />
getQueryString()：获得查询字符串<br />
getRequestURI()：获取发出请求字符串的客户端地址<br />
getRemoteAddr()：获取客户端的IP地址<br />
getRemoteHost()：获取客户端的名字<br />
getSession([Boolean create])：返回和请求相关Session<br />
getServerName()：获取服务器的名字<br />
getServletPath()：获取客户端所请求的脚本文件的路径<br />
getServerPort()：获取服务器的端口号<br />
removeAttribute(String name)：删除请求中的一个属性</p>
<p>67、J2EE是技术还是平台还是框架？<br />
J2EE本身是一个标准，一个为企业分布式应用的开发提供的标准平台。<br />
J2EE也是一个框架，包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术。</p>
<p>68、我们在web应用开发过程中经常遇到输出某种编码的字符，如iso8859-1等，如何输出一个某种编码的字符串？<br />
Public String translate (String str) {<br />
String tempStr = "";<br />
try {<br />
tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");<br />
tempStr = tempStr.trim();<br />
}<br />
catch (Exception e) {<br />
System.err.println(e.getMessage());<br />
}<br />
return tempStr;<br />
}</p>
<p>69、简述逻辑操作(&amp;,|,^)与条件操作(&amp;&amp;,||)的区别。<br />
区别主要答两点：a.条件操作只能操作布尔型的,而逻辑操作不仅可以操作布尔型,而且可以操作数值型<br />
b.逻辑操作不会产生短路</p>
<p>70、XML文档定义有几种形式？它们之间有何本质区别？解析XML文档有哪几种方式？ <br />
a: 两种形式 dtd schema<br />
b: 本质区别:schema本身是xml的，可以被XML解析器解析(这也是从DTD上发展schema的根本目的)<br />
c:有DOM,SAX,STAX等<br />
DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的，这种结构占用的内存较多，而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问<br />
SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件，不需要一次全部装载整个文件。当遇到像文件开头，文档结束，或者标签开头与标签结束时，它会触发一个事件，用户通过在其回调事件中写入处理代码来处理XML文件，适合对XML的顺序访问 <br />
STAX:Streaming API for XML (StAX)<br />
xml文档有两种定义方法：<br />
dtd：数据类型定义（da<wbr>ta type definition），用以描述XML文档的文档结构，是早期的XML文档定义形式。<br />
schema：其本身是基于XML语言编写的，在类型和语法上的限定能力比dtd强，处理也比较方便，因为此正逐渐代替dtd成为新的模式定义语言。</p>
<p>71、简述synchronized和java.util.concurrent.locks.Lock的异同？<br />
主要相同点：Lock能完成synchronized所实现的所有功能<br />
主要不同点：Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁，而Lock一定要求程序员手工释放，并且必须在finally从句中释放。</p>
<p>&nbsp;</p>
<p><br />
91、Servlet执行时一般实现哪几个方法？<br />
public void init(ServletConfig config)<br />
public ServletConfig getServletConfig()<br />
public String getServletInfo()<br />
public void service(ServletRequest request,ServletResponse response)<br />
public void destroy() <br />
init ()方法在servlet的生命周期中仅执行一次，在服务器装载servlet时执行。缺省的init()方法通常是符合要求的，不过也可以根据需要进行 override，比如管理服务器端资源，一次性装入GIF图像，初始化数据库连接等，缺省的inti()方法设置了servlet的初始化参数，并用它的ServeltConfig对象参数来启动配置，所以覆盖init()方法时，应调用super.init()以确保仍然执行这些任务。<br />
service ()方法是servlet的核心，在调用service()方法之前，应确保已完成init()方法。对于HttpServlet，每当客户请求一个 HttpServlet对象，该对象的service()方法就要被调用，HttpServlet缺省的service()方法的服务功能就是调用与 HTTP请求的方法相应的do功能，doPost()和doGet()，所以对于HttpServlet，一般都是重写doPost()和doGet() 方法。<br />
destroy()方法在servlet的生命周期中也仅执行一次，即在服务器停止卸载servlet时执行，把servlet作为服务器进程的一部分关闭。缺省的destroy()方法通常是符合要求的，但也可以override，比如在卸载servlet时将统计数字保存在文件中，或是关闭数据库连接。<br />
getServletConfig()方法返回一个servletConfig对象，该对象用来返回初始化参数和servletContext。servletContext接口提供有关servlet的环境信息。<br />
getServletInfo()方法提供有关servlet的信息，如作者，版本，版权。 </p>
<p>92、j2ee常用的设计模式？说明工厂模式。<br />
Java中的23种设计模式：<br />
Factory（工厂模式）， Builder（建造模式）， Factory Method（工厂方法模式），<br />
Prototype（原始模型模式），Singleton（单例模式）， Facade（门面模式），<br />
Adapter（适配器模式）， Bridge（桥梁模式）， Composite（合成模式），<br />
Decorator（装饰模式）， Flyweight（享元模式）， Proxy（代理模式），<br />
Command（命令模式）， Interpreter（解释器模式）， Visitor（访问者模式），<br />
Iterator（迭代子模式）， Mediator（调停者模式）， Memento（备忘录模式），<br />
Observer（观察者模式）， State（状态模式）， Strategy（策略模式），<br />
Template Method（模板方法模式）， Chain Of Responsibleity（责任链模式）<br />
工厂模式：工厂模式是一种经常被使用到的模式，根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例，通常这一组类有一个公共的抽象父类并且实现了相同的方法，但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类，该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类，工厂类可以根据条件生成不同的子类实例。当得到子类的实例后，开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。 </p>
<p>94、排序都有哪几种方法？请列举。用JAVA实现一个快速排序。<br />
排序的方法有：插入排序（直接插入排序、希尔排序），交换排序（冒泡排序、快速排序），选择排序（直接选择排序、堆排序），归并排序，分配排序（箱排序、基数排序）<br />
快速排序的伪代码。<br />
/ /使用快速排序方法对a[ 0 :n- 1 ]排序<br />
从a[ 0 :n- 1 ]中选择一个元素作为m i d d l e，该元素为支点<br />
把余下的元素分割为两段left 和r i g h t，使得l e f t中的元素都小于等于支点，而right 中的元素都大于等于支点<br />
递归地使用快速排序方法对left 进行排序<br />
递归地使用快速排序方法对right 进行排序<br />
所得结果为l e f t + m i d d l e + r i g h t </p>
<p>95、请对以下在J2EE中常用的名词进行解释(或简单描述)<br />
web 容器：给处于其中的应用程序组件（JSP，SERVLET）提供一个环境，使JSP,SERVLET直接和容器中的环境变量接接口互，不必关注其它系统问题。主要有WEB服务器来实现。例如：TOMCAT,WEBLOGIC,WEBSPHERE等。该容器提供的接口严格遵守J2EE规范中的WEB APPLICATION 标准。我们把遵守以上标准的WEB服务器就叫做J2EE中的WEB容器。<br />
Web container：实现J2EE体系结构中Web组件协议的容器。这个协议规定了一个Web组件运行时的环境，包括安全，一致性，生命周期管理，事务，配置和其它的服务。一个提供和JSP和J2EE平台APIs界面相同服务的容器。一个Web container 由Web服务器或者J2EE服务器提供。<br />
EJB容器：Enterprise java bean 容器。更具有行业领域特色。他提供给运行在其中的组件EJB各种管理功能。只要满足J2EE规范的EJB放入该容器，马上就会被容器进行高效率的管理。并且可以通过现成的接口来获得系统级别的服务。例如邮件服务、事务管理。<br />
一个实现了J2EE体系结构中EJB组件规范的容器。<br />
这个规范指定了一个Enterprise bean的运行时环境，包括安全，一致性，生命周期，事务，<br />
配置，和其他的服务。<br />
JNDI：（Java Naming &amp; Directory Interface）JAVA命名目录服务。主要提供的功能是：提供一个目录系统，让其它各地的应用程序在其上面留下自己的索引，从而满足快速查找和定位分布式应用程序的功能。<br />
JMS：（Java Message Service）JAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播。<br />
JTA：（Java Transaction API）JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。<br />
JAF：（Java Act<wbr>ion FrameWork）JAVA安全认证框架。提供一些安全控制方面的框架。让开发者通过各种部署和自定义实现自己的个性安全控制策略。<br />
RMI/IIOP: （Remote Method Invocation /internet对象请求中介协议）他们主要用于通过远程调用服务。例如，远程有一台计算机上运行一个程序，它提供股票分析服务，我们可以在本地计算机上实现对其直接调用。当然这是要通过一定的规范才能在异构的系统之间进行通信。RMI是JAVA特有的。<br />
RMI-IIOP出现以前，只有RMI和 CORBA两种选择来进行分布式程序设计。RMI-IIOP综合了RMI和CORBA的优点，克服了他们的缺点，使得程序员能更方便的编写分布式程序设计，实现分布式计算。首先，RMI-IIOP综合了RMI的简单性和CORBA的多语言性（兼容性），其次RMI-IIOP克服了RMI只能用于Java 的缺点和CORBA的复杂性（可以不用掌握IDL）。</p>
<p>96、JAVA语言如何进行异常处理，关键字：throws,throw,try,catch,finally分别代表什么意义？在try块中可以抛出异常吗？<br />
Java 通过面向对象的方法进行异常处理，把各种不同的异常进行分类，并提供了良好的接口。在Java中，每个异常都是一个对象，它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象，该对象中包含有异常信息，调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的：try、catch、throw、throws和finally。一般情况下是用try来执行一段程序，如果出现异常，系统会抛出（throws）一个异常，这时候你可以通过它的类型来捕捉（catch）它，或最后（finally）由缺省处理器来处理。<br />
用try来指定一块预防所有"异常"的程序。紧跟在try程序后面，应包含一个catch子句来指定你想要捕捉的"异常"的类型。</p>
<p>throw语句用来明确地抛出一个"异常"。<br />
throws用来标明一个成员函数可能抛出的各种"异常"。<br />
Finally为确保一段代码不管发生什么"异常"都被执行一段代码。<br />
可以在一个成员函数调用的外面写一个try语句，在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句，"异常"的框架就放到堆栈上面，直到所有的try语句都完成。如果下一级的try语句没有对某种"异常"进行处理，堆栈就会展开，直到遇到有处理这种"异常"的try语句。<br />
<a href="http://www.programfan.com/article/showarticle.asp?id=2731">http://www.programfan.com/article/showarticle.asp?id=2731</a> </p>
<p>97、一个".java"源文件中是否可以包括多个类（不是内部类）？有什么限制？<br />
可以。必须只有一个类名与文件名相同。 </p>
<p>98、MVC的各个部分都有那些技术来实现?如何实现? <br />
MVC 是Model－View－Controller的简写。"Model" 代表的是应用的业务逻辑（通过JavaBean，EJB组件实现）， "View" 是应用的表示面，用于与用户的交互（由JSP页面产生），"Controller" 是提供应用的处理过程控制（一般是一个Servlet），通过这种设计模型把应用逻辑，处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。<br />
model层实现系统中的业务逻辑，view层用于与用户的交互，controller层是model与view之间沟通的桥梁，可以分派用户的请求并选择恰当的视图以用于显示，同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。 </p>
<p>99、java中有几种方法可以实现一个线程？用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用？<br />
有两种实现方法，分别是继承Thread类与实现Runnable接口<br />
用synchronized关键字修饰同步方法<br />
反对使用stop()，是因为它不安全。它会解除由线程获取的所有锁定，而且如果对象处于一种不连贯状态，那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候，目标线程会停下来，但却仍然持有在这之前获得的锁定。此时，其他任何线程都不能访问锁定的资源，除非被"挂起"的线程恢复运行。对任何线程来说，如果它们想恢复目标线程，同时又试图使用任何一个锁定的资源，就会造成死锁。所以不应该使用suspend()，而应在自己的Thread类中置入一个标志，指出线程应该活动还是挂起。若标志指出线程应该挂起，便用 wait()命其进入等待状态。若标志指出线程应当恢复，则用一个notify()重新启动线程。 </p>
<p>100、java中有几种类型的流？JDK为每种类型的流提供了一些抽象类以供继承，请说出他们分别是哪些类？<br />
字节流，字符流。字节流继承于InputStream OutputStream，字符流继承于InputStreamReader OutputStreamWriter。在java.io包中还有许多其他的流，主要是为了提高性能和使用方便。 </p>
<p>101、java中会存在内存泄漏吗，请简单描述。<br />
的确存在Java的内存泄漏, 并且事态可以变得相当严重 </p>
<p>Java garbage collector自动释放哪些内存里面程序不在需要的对象, 以此避免大多数的其他程序上下文的内存泄漏. 但是Java应用程序依旧会有相当的内存泄漏. 查找原因会十分困难. <br />
有两类主要的Java内存泄漏:<br />
* 不再需要的对象引用<br />
* 未释放的系统资源 <br />
2.2 非必要的对象引用<br />
Java代码常常保留对于不再需要的对象引用, 并且这组织了内存的垃圾收集器的工作. Java对象通常被其他对象包含引用, 为此一个单一对象可以保持整个对象树在内存中, 于是导致了如下问题: <br />
* 在向数组添加对象以后遗漏了对于他们的处理<br />
* 直到你再次使用对象的时候都不释放引用. 比如一个菜单指令可以插件一个对象实例引用并且不释放便于以后再次调用的时候使用, 但是也许永远不会发生. <br />
* 在其他引用依然需要旧有状态的时候贸然修改对象状态. 比如当你为了在一个文本文件里面保存一些属性而使用一个数组, 诸如"字符个数"等字段在不再需要的时候依然保留在内存当中.<br />
* 允许一个长久执行的线程所引用的对象. 设置引用为NULL也无济于事, 在线程退出和空闲之前, 对象不会被收集释放 <br />
2.3 未释放的系统资源<br />
Java方法可以定位Java实例意外的堆内存,诸如针对视窗和位图的内存资源. Java常常通过JNI(Java Native Interface)调用C/C++子程序定位这些资源.</p>
<p>102、java中实现多态的机制是什么？<br />
方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现，重载Overloading是一个类中多态性的一种表现。</p>
<p>103、垃圾回收器的基本原理是什么？垃圾回收器可以马上回收内存吗？有什么办法主动通知虚拟机进行垃圾回收？<br />
对于GC来说，当程序员创建对象时，GC就开始监控这个对象的地址、大小以及使用情况。通常，GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的"，哪些对象是"不可达的"。当GC确定一些对象为"不可达"时，GC就有责任回收这些内存空间。可以。程序员可以手动执行System.gc()，通知GC运行，但是Java语言规范并不保证GC一定会执行。</p>
<p>104、静态变量和实例变量的区别？<br />
static i = 10; //常量<br />
class A a; a.i =10;//可变</p>
<p>105、什么是java序列化，如何实现java序列化？<br />
序列化就是一种用来处理对象流的机制，所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作，也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。<br />
序列化的实现：将需要被序列化的类实现Serializable接口，该接口没有需要实现的方法，implements Serializable只是为了标注该对象是可被序列化的，然后使用一个输出流(如：FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象，接着，使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态)，要恢复的话则用输入流。</p>
<p>106、是否可以从一个static方法内部发出对非static方法的调用？<br />
不可以,如果其中包含对象的method()；不能保证对象初始化.</p>
<p>107、写clone()方法时，通常都有一行代码，是什么？<br />
Clone 有缺省行为，super.clone();他负责产生正确大小的空间，并逐位复制。</p>
<p>108、在JAVA中，如何跳出当前的多重嵌套循环？<br />
用break; return 方法。</p>
<p>109、List、Map、Set三个接口，存取元素时，各有什么特点？<br />
List 以特定次序来持有元素，可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value值，value可多值。</p>
<p>110、J2EE是什么？<br />
J2EE 是Sun公司提出的多层(multi-diered),分布式(distributed),基于组件(component-base)的企业级应用模型 (enterpriese application model).在这样的一个应用系统中，可按照功能划分为不同的组件，这些组件又可在不同计算机上，并且处于相应的层次(tier)中。所属层次包括客户层(clietn tier)组件,web层和组件,Business层和组件,企业信息系统(EIS)层。</p>
<p>111、UML方面 <br />
标准建模语言UML。用例图,静态图(包括类图、对象图和包图),行为图,交互图(顺序图,合作图),实现图。</p>
<p>112、说出一些常用的类，包，接口，请各举5个<br />
常用的类：BufferedReader BufferedWriter FileReader FileWirter String Integer<br />
常用的包：java.lang java.awt java.io java.util java.sql<br />
常用的接口：Remote List Map Document NodeList </p>
<p>113、开发中都用到了那些设计模式?用在什么场合? <br />
每个模式都描述了一个在我们的环境中不断出现的问题，然后描述了该问题的解决方案的核心。通过这种方式，你可以无数次地使用那些已有的解决方案，无需在重复相同的工作。主要用到了MVC的设计模式。用来开发JSP/Servlet或者J2EE的相关应用。简单工厂模式等。</p>
<p>114、jsp有哪些动作?作用分别是什么? <br />
JSP 共有以下6种基本动作 jsp:include：在页面被请求的时候引入一个文件。 jsp:useBean：寻找或者实例化一个JavaBean。 jsp:setProperty：设置JavaBean的属性。 jsp:getProperty：输出某个JavaBean的属性。 jsp:forward：把请求转到一个新的页面。 jsp:plugin：根据浏览器类型为Java插件生成OBJECT或EMBED标记。<br />
115、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类，是否可以implements(实现)interface(接口)? <br />
可以继承其他类或完成其他接口，在swing编程中常用此方式。</p>
<p>116、应用服务器与WEB SERVER的区别？<br />
应用服务器：Weblogic、Tomcat、Jboss<br />
WEB SERVER：IIS、 Apache</p>
<p>117、BS与CS的联系与区别。<br />
C/S是Client/Server的缩写。服务器通常采用高性能的PC、工作站或小型机，并采用大型数据库系统，如Oracle、Sybase、Informix或 SQL Server。客户端需要安装专用的客户端软件。<br />
B/Ｓ是Brower/Server的缩写，客户机上只要安装一个浏览器（Browser），如Netscape Navigator或Internet Explorer，服务器安装Oracle、Sybase、Informix或 SQL Server等数据库。在这种结构下，用户界面完全通过WWW浏览器实现，一部分事务逻辑在前端实现，但是主要事务逻辑在服务器端实现。浏览器通过Ｗeb Server 同数据库进行数据交互。<br />
C/S 与 B/S 区别： <br />
１．硬件环境不同: <br />
　　C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.<br />
　　B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例与电话上网, 租用设备. 信息自己管理. 有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行 <br />
２．对安全要求不同 <br />
　　C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用C/S 结构适宜. 可以通过B/S发布部分可公开信息.<br />
　　B/S 建立在广域网之上, 对安全的控制能力相对弱, 可能面向不可知的用户。<br />
３．对程序架构不同 <br />
　　C/S 程序可以更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑.<br />
　　B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上. 比C/S有更高的要求 B/S结构的程序架构是发展的趋势, 从MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持网络的构件搭建的系统. SUN 和IBM推的JavaBean 构件技术等,使 B/S更加成熟. <br />
４．软件重用不同 <br />
　　C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在B/S要求下的构件的重用性好.<br />
　　B/S 对的多重结构,要求构件相对独立的功能. 能够相对较好的重用.就入买来的餐桌可以再利用,而不是做在墙上的石头桌子 <br />
５．系统维护不同 <br />
　　C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级. 升级难. 可能是再做一个全新的系统<br />
　　B/S 构件组成,方面构件个别的更换,实现系统的无缝升级. 系统维护开销减到最小.用户从网上自己下载安装就可以实现升级. <br />
６．处理问题不同 <br />
　　C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关. 应该都是相同的系统<br />
　　B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S无法作到的. 与操作系统平台关系最小. <br />
７．用户接口不同 <br />
　　C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高<br />
　　B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流. 并且大部分难度减低,减低开发成本. <br />
８．信息流不同 <br />
　　C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低<br />
B/S 信息流向可变化, B-B B-C B-G等信息、流向的变化, 更像交易中心。</p>
<p>118、LINUX下线程，GDI类的解释。<br />
LINUX实现的就是基于核心轻量级进程的"一对一"线程模型，一个线程实体对应一个核心轻量级进程，而线程之间的管理在核外函数库中实现。 <br />
GDI类为图像设备编程接口类库。</p>
<p>119、STRUTS的应用(如STRUTS架构) <br />
Struts 是采用Java Servlet/JavaServer Pages技术，开发Web应用程序的开放源码的framework。采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能：一.包含一个controller servlet，能将用户的请求发送到相应的Act<wbr>ion对象。二.JSP自由tag库，并且在controller servlet中提供关联支持，帮助开发员创建交互式表单应用。三.提供了一系列实用对象：XML处理、通过Java reflection APIs自动处理JavaBeans属性、国际化的提示和消息。</p>
<p>120、Jdo是什么? <br />
JDO 是Java对象持久化的新的规范，为java da<wbr>ta object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储，因此对开发人员来说，存储数据对象完全不需要额外的代码（如JDBC API的使用）。这些繁琐的例行工作已经转移到JDO产品提供商身上，使开发人员解脱出来，从而集中时间和精力在业务逻辑上。另外，JDO很灵活，因为它可以在任何数据底层上运行。JDBC只是面向关系数据库（RDBMS）JDO更通用，提供到任何数据底层的存储功能，比如关系数据库、文件、XML以及对象数据库（ODBMS）等等，使得应用可移植性更强。 </p>
<p>121、内部类可以引用他包含类的成员吗？有没有什么限制？<br />
一个内部类对象可以访问创建它的外部类对象的内容<br />
内部类如果不是static的，那么它可以访问创建它的外部类对象的所有属性<br />
内部类如果是sattic的，即为nested class，那么它只可以访问创建它的外部类对象的所有static属性<br />
一般普通类只有public或package的访问修饰，而内部类可以实现static，protected，private等访问修饰。<br />
当从外部类继承的时候，内部类是不会被覆盖的，它们是完全独立的实体，每个都在自己的命名空间内，如果从内部类中明确地继承，就可以覆盖原来内部类的方法。</p>
<p>122、WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。 <br />
Web ServiceWeb Service是基于网络的、分布式的模块化组件，它执行特定的任务，遵守具体的技术规范，这些规范使得Web Service能与其他兼容的组件进行互操作。<br />
JAXP(Java API for XML Parsing) 定义了在Java中使用DOM, SAX, XSLT的通用的接口。这样在你的程序中你只要使用这些通用的接口，当你需要改变具体的实现时候也不需要修改代码。<br />
JAXM(Java API for XML Messaging) 是为SOAP通信提供访问方法和传输机制的API。<br />
WSDL是一种 XML 格式，用于将网络服务描述为一组端点，这些端点对包含面向文档信息或面向过程信息的消息进行操作。这种格式首先对操作和消息进行抽象描述，然后将其绑定到具体的网络协议和消息格式上以定义端点。相关的具体端点即组合成为抽象端点（服务）。<br />
SOAP即简单对象访问协议(Simple Object Access Protocol)，它是用于交换XML编码信息的轻量级协议。 <br />
UDDI 的目的是为电子商务建立标准；UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范，同时也包含一组使企业能将自身提供的Web Service注册，以使别的企业能够发现的访问协议的实现标准。<br />
soap是web service最关键的技术，是web service中数据和方法调传输的介质。<br />
WSDL（web service definition language）描述了web service的接口和功能。</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-14 16:08 <a href="http://www.blogjava.net/balajinima/articles/298226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java线程之同步化(Synchronized)</title><link>http://www.blogjava.net/balajinima/articles/298184.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Wed, 14 Oct 2009 03:52:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298184.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298184.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298184.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298184.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298184.html</trackback:ping><description><![CDATA[
		<p>1.  
如果一个对象所持有的数据可以被多线程同时共享存取，必须考虑到数据同步的问题。所谓数据同步指的是两份数据的整体性和一致性。数据在多线程下共享时容易由于同时多个线程可能更新同一个对象的信息，而造成对象数据的不同步，因为数据的不同步可能引发的错误通常不易察觉，而且可能是在程序执行了几千几万次之后，才会发生错误。这通常会发生在产品已经上线之后，甚至是程序已经执行了几年之后。</p>
		<p>2. 举个简单的例子，设计了一个PersonalInfo类：    </p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j">
						<li>
								<span>
										<span class="keyword">package</span>
										<span> ysu.hxy; 
  </span>
								</span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>
								</span>
								<span class="keyword">public</span>
								<span> </span>
								<span class="keyword">class</span>
								<span> PersonalInfo    </span>
						</li>
						<li>
								<span>{   </span>
						</li>
						<li>
								<span>    </span>
								<span class="keyword">private</span>
								<span> String name; 
  </span>
						</li>
						<li>
								<span>    </span>
								<span class="keyword">private</span>
								<span> String id; 
  </span>
						</li>
						<li>
								<span>    </span>
								<span class="keyword">private</span>
								<span> </span>
								<span class="keyword">int</span>
								<span> count;   </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>    </span>
								<span class="keyword">public</span>
								<span> PersonalInfo() 
  </span>
						</li>
						<li>
								<span>    {   </span>
						</li>
						<li>
								<span>        name = </span>
								<span class="string">"nobody"</span>
								<span>; 
  </span>
						</li>
						<li>
								<span>        id = </span>
								<span class="string">"N/A"</span>
								<span>; 
  </span>
						</li>
						<li>
								<span>    }   </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>    </span>
								<span class="keyword">public</span>
								<span> </span>
								<span class="keyword">void</span>
								<span> setNameAndID(String name,String id) 
  </span>
						</li>
						<li>
								<span>    {   </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">this</span>
								<span>.name = name; 
  </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">this</span>
								<span>.id = id; 
  </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">if</span>
								<span>(!checkNameAndIDEqual())   </span>
						</li>
						<li>
								<span>        {   </span>
						</li>
						<li>
								<span>             System.out.println(count + </span>
								<span class="string">") illegal name or ID..."</span>
								<span>);   </span>
						</li>
						<li>
								<span>        }   </span>
						</li>
						<li>
								<span>        count ++;   </span>
						</li>
						<li>
								<span>    }   </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>    </span>
								<span class="keyword">private</span>
								<span> </span>
								<span class="keyword">boolean</span>
								<span> checkNameAndIDEqual(){   </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">return</span>
								<span> (name.charAt(</span>
								<span class="number">0</span>
								<span>) == id.charAt(</span>
								<span class="number">0</span>
								<span>)) ? </span>
								<span class="keyword">true</span>
								<span>:</span>
								<span class="keyword">false</span>
								<span>; 
  </span>
						</li>
						<li>
								<span>    }   </span>
						</li>
						<li>
								<span>}  </span>
						</li>
				</ol>
		</div>
		<pre style="display: none;" class="java" name="code">package ysu.hxy;

public class PersonalInfo 
{
	private String name;
	private String id;
	private int count;

	public PersonalInfo()
	{
		name = "nobody";
		id = "N/A";
	}

	public void setNameAndID(String name,String id)
	{
		this.name = name;
		this.id = id;
		if(!checkNameAndIDEqual())
		{
             System.out.println(count + ") illegal name or ID...");
		}
		count ++;
	}

	private boolean checkNameAndIDEqual(){
		return (name.charAt(0) == id.charAt(0)) ? true:false;
	}
}
</pre>
		<p> 单就这个类本身而言，它并没有任何的错误，但如果它被用于多线程的程序中，而且同一个对象被多个线程存取时，就会有可能发生错误。下面是一个简单的测试程序，看看PersonalInfo类在多线程共享数据下会发生什么问题。</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j">
						<li>
								<span>
										<span class="keyword">package</span>
										<span> ysu.hxy; 
  </span>
								</span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>
								</span>
								<span class="keyword">public</span>
								<span> </span>
								<span class="keyword">class</span>
								<span> PersonalInfoTest    </span>
						</li>
						<li>
								<span>{   </span>
						</li>
						<li>
								<span>    </span>
								<span class="keyword">public</span>
								<span> </span>
								<span class="keyword">static</span>
								<span> </span>
								<span class="keyword">void</span>
								<span> main(String[] args)    </span>
						</li>
						<li>
								<span>    {   </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">final</span>
								<span> PersonalInfo person = </span>
								<span class="keyword">new</span>
								<span> PersonalInfo();   </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>        </span>
								<span class="comment">//假设会能两个线程可能更新person对象  
</span>
								<span>  </span>
						</li>
						<li>
								<span>        Thread thread1 = </span>
								<span class="keyword">new</span>
								<span> Thread(</span>
								<span class="keyword">new</span>
								<span> Runnable() {   </span>
						</li>
						<li>
								<span>            </span>
								<span class="keyword">public</span>
								<span> </span>
								<span class="keyword">void</span>
								<span> run() {   </span>
						</li>
						<li>
								<span>                </span>
								<span class="keyword">while</span>
								<span>(</span>
								<span class="keyword">true</span>
								<span>){ 
  </span>
						</li>
						<li>
								<span>                    person.setNameAndID(</span>
								<span class="string">"Justin Lin"</span>
								<span>,</span>
								<span class="string">"J.L"</span>
								<span>);   </span>
						</li>
						<li>
								<span>                }   </span>
						</li>
						<li>
								<span>            }   </span>
						</li>
						<li>
								<span>        });   </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>        Thread thread2 = </span>
								<span class="keyword">new</span>
								<span> Thread(</span>
								<span class="keyword">new</span>
								<span> Runnable() {   </span>
						</li>
						<li>
								<span>            </span>
								<span class="keyword">public</span>
								<span> </span>
								<span class="keyword">void</span>
								<span> run() {   </span>
						</li>
						<li>
								<span>                </span>
								<span class="keyword">while</span>
								<span>(</span>
								<span class="keyword">true</span>
								<span>){ 
  </span>
						</li>
						<li>
								<span>                    person.setNameAndID(</span>
								<span class="string">"Shang Hwang Lin"</span>
								<span>,</span>
								<span class="string">"S.H"</span>
								<span>);   </span>
						</li>
						<li>
								<span>                }   </span>
						</li>
						<li>
								<span>            }   </span>
						</li>
						<li>
								<span>        });   </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>        System.out.println();   </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>        thread1.start();   </span>
						</li>
						<li>
								<span>        thread2.start();   </span>
						</li>
						<li>
								<span>    }   </span>
						</li>
						<li>
								<span>}  </span>
						</li>
				</ol>
		</div>
		<pre style="display: none;" class="java" name="code">package ysu.hxy;

public class PersonalInfoTest 
{
	public static void main(String[] args) 
	{
		final PersonalInfo person = new PersonalInfo();

		//假设会能两个线程可能更新person对象 
		Thread thread1 = new Thread(new Runnable() {
			public void run() {
				while(true){
					person.setNameAndID("Justin Lin","J.L");
				}
			}
		});

        Thread thread2 = new Thread(new Runnable() {
			public void run() {
				while(true){
					person.setNameAndID("Shang Hwang Lin","S.H");
				}
			}
		});

		System.out.println();

		thread1.start();
		thread2.start();
	}
}</pre>
		<p> </p>
		<p>执行结果：</p>
		<p>D:\hxy&gt;java ysu.hxy.PersonalInfoTest<br />开始测试...<br />23466451) illegal name 
or ID...<br />78044494) illegal name or ID...<br />101630476) illegal name or 
ID...<br />106496643) illegal name or ID...<br />145330181) illegal name or 
ID...<br />169674022) illegal name or ID...<br />174072203) illegal name or 
ID...<br />214717201) illegal name or ID...<br />219668799) illegal name or 
ID...<br />240921750) illegal name or ID...<br />265875722) illegal name or 
ID...<br />270920923) illegal name or ID...<br />281256783) illegal name or 
ID...</p>
		<p>这个程序出现了错误，在23466451次的setNameAndID()执行时就开始了。如果程序完成并开始应用于实际场合之后，这个时间点可能是几个月甚至是几年之后。问题出在这里：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j">
						<li>
								<span>
										<span class="keyword">public</span>
										<span> </span>
										<span class="keyword">void</span>
										<span> setNameAndID(String name,String id) 
  </span>
								</span>
						</li>
						<li>
								<span>    {   </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">this</span>
								<span>.name = name; 
  </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">this</span>
								<span>.id = id; 
  </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">if</span>
								<span>(!checkNameAndIDEqual())   </span>
						</li>
						<li>
								<span>        {   </span>
						</li>
						<li>
								<span>             System.out.println(count + </span>
								<span class="string">") illegal name or ID..."</span>
								<span>);   </span>
						</li>
						<li>
								<span>        }   </span>
						</li>
						<li>
								<span>        count ++;   </span>
						</li>
						<li>
								<span>    }  </span>
						</li>
				</ol>
		</div>
		<pre style="display: none;" class="java" name="code">public void setNameAndID(String name,String id)
	{
		this.name = name;
		this.id = id;
		if(!checkNameAndIDEqual())
		{
             System.out.println(count + ") illegal name or ID...");
		}
		count ++;
	}
</pre>
		<p>      虽然传递给setNameAndID()的变量并没有问题，在某个时间点时，thread1设定了Justin 
Lin、J.L给name和id，在进行if测试的前一刻，thread2可能此时刚好调用setNameAndID("Shang 
Hwang","S.H")。在name被设定为Shang HWang时，checkNameAndIDEqual()开始执行，此时name等于Shang 
HWang，而id还是J.L。所以，checkNameAndIDEqual()就会返回false，结果就显示了错误信息。</p>
		<p>       
必须同步数据对对象的更新，方法在有一个线程正在设定person对象的数据时，不可以被另一个线程同时进行设定。可以使用synchronized关键词来进行这个动作。</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j">
						<li>
								<span>
										<span class="keyword">public</span>
										<span> </span>
										<span class="keyword">synchronized</span>
										<span> </span>
										<span class="keyword">void</span>
										<span> setNameAndID(String name,String id) 
  </span>
								</span>
						</li>
						<li>
								<span>    {   </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">this</span>
								<span>.name = name; 
  </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">this</span>
								<span>.id = id; 
  </span>
						</li>
						<li>
								<span>        </span>
								<span class="keyword">if</span>
								<span>(!checkNameAndIDEqual())   </span>
						</li>
						<li>
								<span>        {   </span>
						</li>
						<li>
								<span>             System.out.println(count + </span>
								<span class="string">") illegal name or ID..."</span>
								<span>);   </span>
						</li>
						<li>
								<span>        }   </span>
						</li>
						<li>
								<span>        count ++;   </span>
						</li>
						<li>
								<span>    }  </span>
						</li>
				</ol>
		</div>
		<pre style="display: none;" class="java" name="code">public synchronized void setNameAndID(String name,String id)
	{
		this.name = name;
		this.id = id;
		if(!checkNameAndIDEqual())
		{
             System.out.println(count + ") illegal name or ID...");
		}
		count ++;
	}
</pre>
		<p> 这是<span style="color: rgb(0, 0, 255);">synchronized关键词的一个使用方式，用于方法上让方法的范围内都成为被同步化区域</span>。被同步化区域在有一个线程占据时就像一个禁区，不允许其他线程进入。由于同时间只能有一个线程在被同步化区域，所以更新共享数据时，就像单线程程序在更新数据一样，以保证对象中的数据会与给定的数据同步。</p>
		<p>  <span style="color: rgb(0, 0, 255);">sychronized的设定不只可用于方法上，也可以用于限定某个程序区块上被同步化区域</span>。例如：  
</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j">
						<li>
								<span>
										<span class="keyword">public</span>
										<span> </span>
										<span class="keyword">void</span>
										<span> setNameAndID(String name,String id) 
  </span>
								</span>
						</li>
						<li>
								<span>  { </span>
								<span class="comment">//同步某个程序区块 
</span>
								<span>  </span>
						</li>
						<li>
								<span>       </span>
								<span class="keyword">synchronized</span>
								<span>(</span>
								<span class="keyword">this</span>
								<span>)   </span>
						</li>
						<li>
								<span>   {   </span>
						</li>
						<li>
								<span>       </span>
								<span class="keyword">this</span>
								<span>.name = name; 
  </span>
						</li>
						<li>
								<span>       </span>
								<span class="keyword">this</span>
								<span>.id = id; 
  </span>
						</li>
						<li>
								<span>       </span>
								<span class="keyword">if</span>
								<span>(!checkNameAndIDEqual())   </span>
						</li>
						<li>
								<span>          {   </span>
						</li>
						<li>
								<span>               System.out.println(count+</span>
								<span class="string">") illegal name or ID..."</span>
								<span>);   </span>
						</li>
						<li>
								<span>          }   </span>
						</li>
						<li>
								<span>   }   </span>
						</li>
						<li>
								<span>}  </span>
						</li>
				</ol>
		</div>
		<pre style="display: none;" class="java" name="code">public void setNameAndID(String name,String id)
  { //同步某个程序区块
       synchronized(this)
   {
       this.name = name;
       this.id = id;
       if(!checkNameAndIDEqual())
          {
               System.out.println(count+") illegal name or ID...");
          }
   }
}</pre>
		<p>   
这个程序片段的意思是，在线程执行到synchronized设定的被同步化区块时锁定当前对象，这样就没有其他线程可以来执行这个被同步化区块。这个方式可以应用于您不想锁定整个方法区块，而只是想在更新共享数据时再确保对象与数据的同步化。由于只锁定方法中的某个区块，在执行完区块后即释放对对象的锁定，以便让其他线程能有机会对对象进行操作，相对于锁定整个方法区块效率较高。</p>
		<p>   <span style="color: rgb(0, 0, 255);">也可以标示某个对象要求同步化</span>。例如在多线程中存取同一个ArrayList对象时，由于ArrayList并没有实现数据存取时的同步化，所以当它使用多线程环境时，必须注意多个线程存取同一个ArrayList时，有可能发生两个以上的线程将数据存入ArrayList的同一个位置，造成数据的相互覆盖。为了确保数据存入时的正确性，可以在存取ArrayList对象时要求同步化。例如：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j">
						<li>
								<span>
										<span class="comment">//arraylist参考至一个ArrayList的一个实例 
</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>
								</span>
								<span class="keyword">synchronized</span>
								<span>(arraylist) 
  </span>
						</li>
						<li>
								<span>{   </span>
						</li>
						<li>
								<span>     arrayList.add(</span>
								<span class="keyword">new</span>
								<span> SomeClass());   </span>
						</li>
						<li>
								<span>}  </span>
						</li>
				</ol>
		</div>
		<pre style="display: none;" class="java" name="code">//arraylist参考至一个ArrayList的一个实例
synchronized(arraylist)
{
     arrayList.add(new SomeClass());
}
</pre>
		<p> 同步化确保数据的同步，但所牺牲的就是在于一个线程占据同步化区块，而其他线程等待它释放区块执行权时的延迟。这在线程少时可能看不出来，但在线程多的环境中必然造成一定的效率问题（例如大型网站的多人联机时）。 <br /></p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298184.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-14 11:52 <a href="http://www.blogjava.net/balajinima/articles/298184.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sql_1</title><link>http://www.blogjava.net/balajinima/articles/298056.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Tue, 13 Oct 2009 05:55:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298056.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298056.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298056.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298056.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298056.html</trackback:ping><description><![CDATA[
		<p>1.一个表中的Id有多个记录，把所有这个id的记录查出来，并显示共有多少条记录数。<br />select ID,count(*) from Student 
group by ID having count(*)&gt;1<br />select * from(select ID,count(ID) as count 
from Student group by ID)T </p>
		<p>2.有一张表，里面有3个字段：语文，数学，英语。其中有3条记录分别表示语文70分，数学80分，英语58分，请用一条sql语句查询出这三条记录并按以下条件显示出来（并写出您的思路）：  
<br />   大于或等于80表示优秀，大于或等于60表示及格，小于60分表示不及格。  <br />if object_id('tb') is not null 
drop table tb<br />go<br />create table tb(yw int,sx int,yy int)<br />insert into 
tb<br />select 70,80,58</p>
		<p>select <br />(case when yw &lt;60 then '不及格'<br />         when yw &gt;= 80 then 
'优秀'<br />         else'及格' end) as '语文',<br />(case when sx &lt;60 then 
'不及格'<br />         when sx &gt;= 80 then '优秀'<br />         else'及格' end) as 
'数学',<br />(case when yy &lt;60 then '不及格'<br />         when yy &gt;= 80 then 
'优秀'<br />         else'及格' end) as '英语'<br />from tb</p>
		<p>drop table tb<br />3.请教一个面试中遇到的SQL语句的查询问题<br />表中有A B 
C三列,用SQL语句实现：当A列大于B列时选择A列否则选择B列，当B列大于C列时选择B列否则选择C列。<br />select (case when a&gt;b 
then a else b end),<br />(case when b&gt;c then b else c end)<br />from tb</p>
		<p>4.为管理岗位业务培训信息，建立3个表: <br />S (S#,SN,SD,SA) S#,SN,SD,SA 
分别代表学号、学员姓名、所属单位、学员年龄</p>
		<p>C (C#,CN ) C#,CN 分别代表课程编号、课程名称</p>
		<p>SC ( S#,C#,G ) S#,C#,G 分别代表学号、所选修的课程编号、学习成绩</p>
		<p>A. 使用标准SQL嵌套语句查询选修课程名称为’税收基础’的学员学号和姓名<br />B. 
使用标准SQL嵌套语句查询选修课程编号为’C2’的学员姓名和所属单位<br />C. 
使用标准SQL嵌套语句查询不选修课程编号为’C5’的学员姓名和所属单位<br />D. 使用标准SQL嵌套语句查询选修全部课程的学员姓名和所属单位<br />E. 
查询选修了课程的学员人数<br />F. 查询选修课程超过5门的学员学号和所属单位</p>
		<p>A. select S#,SN from S where S# in(select S# from SC,C where SC.C#=C.C# and 
CN='税收基础')</p>
		<p>B. select S.SN,S.SD from S,SC where S.S#=SC.S# and C#=C2</p>
		<p>C. SELECT SN,SD FROM S where [S#] NOT IN(SELECT [S#] FROM SC WHERE 
[C#]='C5')<br />  或者select S.SN,S.SD from S,SC where S.S#=SC.S# and C#!=C5</p>
		<p>D. select SN,SD, from S where (select count(S#) from SC group by S#)=(select 
count(*) from C group by C#)</p>
		<p>E. select count(distinct S#) from SC</p>
		<p>F. select S#,SD from S where S# in (SELECT [S#] FROM SC GROUP BY [S#] HAVING 
COUNT(DISTINCT [C#])&gt;5)</p>
		<p>5.问题描述:</p>
		<p>
				<br />S (SNO,SNAME) 学生关系。SNO 为学号，SNAME 为姓名</p>
		<p>
				<br />C (CNO,CNAME,CTEACHER) 课程关系。CNO 为课程号，CNAME 为课程名，CTEACHER 为任课教师</p>
		<p>
				<br />SC(SNO,CNO,SCGRADE) 选课关系。SCGRADE 为成绩</p>
		<p>
				<br />A. 找出没有选修过“李明”老师讲授课程的所有学生姓名<br />Select SNAME FROM S Where NOT EXISTS ( 
Select * FROM SC,C Where SC.CNO=C.CNO AND CNAME='李明' AND SC.SNO=S.SNO)</p>
		<p>B. 列出有二门以上(含两门)不及格课程的学生姓名及其平均成绩<br />Select 
S.SNO,S.SNAME,AVG_SCGRADE=AVG(SC.SCGRADE) FROM  S ,  SC , (Select SNO　FROM SC 
Where SCGRADE&lt;60 GROUP BY SNO HAVING COUNT(DISTINCT CNO)&gt;=2) A Where 
S.SNO=A.SNO AND SC.SNO=A.SNO GROUP BY S.SNO,S.SNAME</p>
		<p>C. 列出既学过“1”号课程，又学过“2”号课程的所有学生姓名<br />Select S.SNO,S.SNAME FROM S,(Select 
SC.SNO  FROM SC,C Where SC.CNO=C.CNO AND C.CNAME IN('1','2') GROUP BY SNO HAVING 
COUNT(DISTINCT CNO)=2)SC Where S.SNO=SC.SNO<br />D. 
列出“1”号课成绩比“2”号同学该门课成绩高的所有学生的学号<br />Select S.SNO,S.SNAME FROM S,<br />(Select 
SC1.SNOFROM SC SC1,C C1,SC SC2,C C2<br />Where SC1.CNO=C1.CNO AND 
C1.NAME='1'<br />AND SC2.CNO=C2.CNO AND C2.NAME='2'<br />AND 
SC1.SCGRADE&gt;SC2.SCGRADE  )  SC <br />Where S.SNO=SC.SNO</p>
		<p>E. 列出“1”号课成绩比“2”号课成绩高的所有学生的学号及其“1”号课和“2”号课的成绩<br />Select 
S.SNO,S.SNAME,SC.[1号课成绩],SC.[2号课成绩] FROM S,<br />(Select 
SC1.SNO,[1号课成绩]=SC1.SCGRADE,[2号课成绩]=SC2.SCGRADE<br />FROM SC SC1,C C1,SC SC2,C 
C2<br />Where SC1.CNO=C1.CNO AND C1.NAME='1'<br />AND SC2.CNO=C2.CNO AND 
C2.NAME='2'<br />AND SC1.SCGRADE&gt;SC2.SCGRADE)   SC <br />Where S.SNO=SC.SNO</p>
		<p>6.<br />======<br />有如下表记录:<br />ID          Name         EmailAddress           
LastLogon<br />100         test4       <a href="mailto:test4@yahoo.cn">test4@yahoo.cn</a>       2007-11-25 
16:31:26<br />13          test1       <a href="mailto:test1@yahoo.cn">test1@yahoo.cn</a>       2007-3-22 
16:27:07<br />19          test1       <a href="mailto:test1@yahoo.cn">test1@yahoo.cn</a>       2007-10-25 
14:13:46<br />42          test1       <a href="mailto:test1@yahoo.cn">test1@yahoo.cn</a>       2007-11-20 
14:20:10<br />45          test2       <a href="mailto:test2@yahoo.cn">test2@yahoo.cn</a>       2007-4-25 
14:17:39<br />49          test2       <a href="mailto:test2@yahoo.cn">test2@yahoo.cn</a>       2007-5-25 14:22:36</p>
		<p>
				<br />用一句sql查询出每个用户最近一次登录的记录(每个用户只显示一条最近登录的记录)<br />方法一:<br />SELECT a.* from 
users  a  inner join<br />                              (SELECT [Name], 
LastLogon=MAX(LastLogon)    FROM  users    GROUP BY [Name])  
b<br />                               on a.[Name]=b.[Name] and 
a.[LastLogon]=b.[LastLogon]</p>
		<p>方法二:<br />SELECT a.* from users  a   inner 
join<br />                               (SELECT  Name,MAX(LogonID) LogonID     
FROM  users    GROUP BY [Name])  b<br />                             on 
a.LogonID=b.LogonID<br />                             --where a.LogonId=b.LogonId 
</p>
		<p>7.现在我们假设只有一个table，名为pages，有四个字段，id, 
url,title,body。里面储存了很多网页，网页的url地址，title和网页的内容，然后你用一个sql查询将url匹配的排在最前， 
title匹配的其次，body匹配最后，没有任何字段匹配的，不返回。<br />select a.[id],a.mark from <br />( <br />select 
[page].[id],100 as mark from [page] where [page].[url] like '%baidu%' <br />union 
<br />select [page].[id],50 as mark from [page] where [page].[title] like 
'%baidu%' <br />union <br />select [page].[id],10 as mark from [page] where 
[page].[body] like '%baidu%' <br />) as a  order by mark desc  </p>
		<p> </p>
		<p>8.查询某表中的第30到40行的数据<br />select top * 10 from (select top * 40 from table order 
by id asc) table_a order by id desc</p>
		<p>9.对于教学数据库的三个基本表 <br />　　 　　学生 S(S#,SNAME,AGE,SEX) <br />　　 　　学习 SC(S#,C#,GRADE) 
<br />　　 　　课程 C(C#,CNAME,TEACHER) <br />试用SQL的查询语句表达下列查询： </p>
		<p>A.检索LIU老师所授课程的课程号和课程名。<br />  select C#,CNAME from C where TEACHER='LIU'</p>
		<p>B.检索年龄大于23岁的男学生的学号和姓名。<br />  select S#,SNAME from S where AGE&gt;23 and 
SEX='男'</p>
		<p>C.检索至少选修LIU老师所授课程中一门课程的女学生姓名。<br />  select SNAME from S left join SC on 
S.S#=SC.S# left join C on SC.C#=C.C# where S.SEX='女' and C.TEACHER='LIU'</p>
		<p>D.检索WANG同学不学的课程的课程号。<br />  SELECT C# FROM C WHERE C# NOT IN (SELECT C# FROM SC 
WHERE S# IN (SELECT S# FROM S WHERE SNAME='WANG')) 
<br /> <br />E.检索至少选修两门课程的学生学号。<br />  select distinct SC1.S# from SC as SC1 where 
(select count(*) from SC as SC2 where SC1.S#=SC2.S#)&gt;=2</p>
		<p>F.检索全部学生都选修的课程的课程号与课程名。<br />  SELECT C.C#,C.CNAME FROM C WHERE NOT EXISTS 
(SELECT S.S# FROM S WHERE S.S# NOT IN(SELECT SC.S# FROM SC WHERE SC.C# = 
C.C#))</p>
		<p>G.检索选修课程包含LIU老师所授课的学生学号。　<br />  select SC.S# from SC,C where SC.C#=C.C# and 
C.TEACHER='LIU'</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/298056.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-13 13:55 <a href="http://www.blogjava.net/balajinima/articles/298056.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java类加载_4</title><link>http://www.blogjava.net/balajinima/articles/298048.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Tue, 13 Oct 2009 04:47:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298048.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298048.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298048.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298048.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298048.html</trackback:ping><description><![CDATA[package test;<br /><br />class TestA {<br />    public TestA() {<br />        System.out.println("Test--A");<br />    }<br />}<br /><br />class TestB {<br />    public TestB() {<br />        System.out.println("Test--B");<br />    }<br />}<br /><br />public class TestOrder {<br />    // 静态变量<br />    public static TestA a = new TestA();<br /><br />    // 静态初始化块<br />    static {<br />        System.out.println("静态初始化块");<br />    }<br /><br />    // 静态变量<br />    public static TestB b = new TestB();<br /><br />    public static void main(String[] args) {<br />        new TestOrder();<br />    }<br />}<br />//<br />// 结果：<br />// *******<br />// Test--A<br />// 静态初始化块<br />// Test--B<br />// 大家可以随意改变变量a、变量b以及静态初始化块的前后位置，<br />//就会发现输出结果随着它们在类中出现的前后顺序而改变，<br />//这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。<br />//同样，变量和初始化块也遵循这个规律。<br /><br /><img src ="http://www.blogjava.net/balajinima/aggbug/298048.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-13 12:47 <a href="http://www.blogjava.net/balajinima/articles/298048.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java类加载_3</title><link>http://www.blogjava.net/balajinima/articles/298046.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Tue, 13 Oct 2009 04:38:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298046.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298046.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298046.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298046.html</trackback:ping><description><![CDATA[package test;<br /><br />class Parent {    <br />    // 静态变量    <br />    public static String p_StaticField = "父类--静态变量";    <br />    // 变量    <br />    public String p_Field = "父类--变量";    <br />   <br />    // 静态初始化块    <br />    static {    <br />         System.out.println(p_StaticField);    <br />         System.out.println("父类--静态初始化块");    <br />     }    <br />   <br />    // 初始化块    <br />     {    <br />         System.out.println(p_Field);    <br />         System.out.println("父类--初始化块");    <br />     }    <br />   <br />    // 构造器    <br />    public Parent() {    <br />         System.out.println("父类--构造器");    <br />     }    <br />}    <br />   <br />public class SubClass extends Parent {    <br />    // 静态变量    <br />    public static String s_StaticField = "子类--静态变量";    <br />    // 变量    <br />    public String s_Field = "子类--变量";    <br />    // 静态初始化块    <br />    static {    <br />         System.out.println(s_StaticField);    <br />         System.out.println("子类--静态初始化块");    <br />     }    <br />    // 初始化块    <br />     {    <br />         System.out.println(s_Field);    <br />         System.out.println("子类--初始化块");    <br />     }    <br />   <br />    // 构造器    <br />    public SubClass() {    <br />         System.out.println("子类--构造器");    <br />     }    <br />   <br />    // 程序入口    <br />    public static void main(String[] args) {    <br />        new SubClass();    <br />     }    <br />}   <br />//结果：<br />//*****************<br />//父类--静态变量<br />//父类--静态初始化块<br />//子类--静态变量<br />//子类--静态初始化块<br />//父类--变量<br />//父类--初始化块<br />//父类--构造器<br />//子类--变量<br />//子类--初始化块<br />//子类--构造器<br /><br /><img src ="http://www.blogjava.net/balajinima/aggbug/298046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-13 12:38 <a href="http://www.blogjava.net/balajinima/articles/298046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java类加载_2</title><link>http://www.blogjava.net/balajinima/articles/298041.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Tue, 13 Oct 2009 03:51:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298041.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298041.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298041.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298041.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298041.html</trackback:ping><description><![CDATA[对于静态变量、静态初始化块、变量、初始化块、构造器，它们的初始化顺序依次是（静态变量、静态初始化块）&gt;（变量、初始化块）&gt;构造器。我们也可以通过下面的测试代码来验证这一点：<br /><br /><br />package test;<br /><br />public class InitialOrderTest {<br /><br />    // 静态变量<br />    public static String staticField = "静态变量";<br /><br />    // 变量<br />    public String field = "变量";<br /><br />    // 静态初始化块<br />    static {<br />        System.out.println(staticField);<br />        System.out.println("静态初始化块");<br />    }<br /><br />    // 初始化块<br />    {<br />        System.out.println(field);<br />        System.out.println("初始化块");<br />    }<br /><br />    // 构造器<br />    public InitialOrderTest() {<br />        System.out.println("构造器");<br />    }<br /><br />    public static void main(String[] args) {<br />        System.out.println("main() 方法");<br />        new InitialOrderTest();<br />    }<br />}<br />//结果：<br />//************<br />//静态变量<br />//静态初始化块<br />//main() 方法<br />//变量<br />//初始化块<br />//构造器<br /><br /><img src ="http://www.blogjava.net/balajinima/aggbug/298041.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-13 11:51 <a href="http://www.blogjava.net/balajinima/articles/298041.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java类加载_1</title><link>http://www.blogjava.net/balajinima/articles/298037.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Tue, 13 Oct 2009 03:23:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/298037.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/298037.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/298037.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/298037.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/298037.html</trackback:ping><description><![CDATA[package test;<br /><br />class Super {<br />    static int x;<br />    static {<br />        System.out.println("Initialization Super");<br />    }<br />}<br /><br />class Sub extends Super {<br /><br />    static final int y = 2005;<br /><br />    static int z;<br /><br />    static {<br />        System.out.println("Initialization Sub");<br />    }<br />}<br /><br />public class Initialization {<br /><br />    public static void main(String[] args) {<br /><br />        System.out.println(Sub.x);<br />        // 不会引起Sub类的初始化，因为x是定义在Super类中的<br />        System.out.println("-------------------------");<br />        System.out.println(Sub.y);<br />        // 不会引起Sub类的初始化，因为y是常量<br />        System.out.println("-------------------------");<br />        System.out.println(Sub.z = 2004);<br />        // 将会引起Sub的初始化<br />    }<br />}<br />//结果：<br />//*****************************<br />//Initialization Super<br />//0<br />//-------------------------<br />//2005<br />//-------------------------<br />//Initialization Sub<br />//2004<br /><br /><img src ="http://www.blogjava.net/balajinima/aggbug/298037.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-13 11:23 <a href="http://www.blogjava.net/balajinima/articles/298037.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程-生产者消费者</title><link>http://www.blogjava.net/balajinima/articles/297931.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Mon, 12 Oct 2009 09:31:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/297931.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/297931.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/297931.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/297931.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/297931.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>package test;</p>
<p>class Thing {<br />
&nbsp;int id;</p>
<p>&nbsp;public Thing(int id) {<br />
&nbsp;&nbsp;this.id = id;<br />
&nbsp;}<br />
}</p>
<p>class Stack {<br />
&nbsp;int counter = 0;<br />
&nbsp;int stackSize;<br />
&nbsp;Thing[] things = null;</p>
<p>&nbsp;public Stack(int stackSize) {<br />
&nbsp;&nbsp;this.stackSize = stackSize;<br />
&nbsp;&nbsp;things = new Thing[stackSize];<br />
&nbsp;}</p>
<p>&nbsp;public synchronized void push(Thing thing) {<br />
&nbsp;&nbsp;// 生产<br />
&nbsp;&nbsp;while (counter == stackSize) {<br />
&nbsp;&nbsp;&nbsp;// 已经满了 等待消费<br />
&nbsp;&nbsp;&nbsp;System.out.println("已经存满！等待消费。。。。。");<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.wait();<br />
&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;this.notify();<br />
&nbsp;&nbsp;things[counter] = thing;<br />
&nbsp;&nbsp;counter++;<br />
&nbsp;}</p>
<p>&nbsp;public synchronized Thing pop() {<br />
&nbsp;&nbsp;// 消费<br />
&nbsp;&nbsp;while (counter == 0) {<br />
&nbsp;&nbsp;&nbsp;System.out.println("没有产品！等待生产。。。。");<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.wait();<br />
&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;this.notify();<br />
&nbsp;&nbsp;counter--;<br />
&nbsp;&nbsp;return things[counter];<br />
&nbsp;}<br />
}</p>
<p>class Producer implements Runnable {<br />
&nbsp;Stack stack;<br />
&nbsp;int level;// 生产水平</p>
<p>&nbsp;public Producer(Stack stack, int level) {<br />
&nbsp;&nbsp;this.stack = stack;<br />
&nbsp;&nbsp;this.level = level;<br />
&nbsp;}</p>
<p>&nbsp;public void run() {<br />
&nbsp;&nbsp;for (int i = 0; i &lt;= level; i++) {<br />
&nbsp;&nbsp;&nbsp;Thing thing = new Thing(i);<br />
&nbsp;&nbsp;&nbsp;stack.push(thing);<br />
&nbsp;&nbsp;&nbsp;System.out.println("生产: " + thing.id);<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(100);<br />
&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}</p>
<p>class Consumer implements Runnable {<br />
&nbsp;Stack stack;<br />
&nbsp;int level;// 消费水平</p>
<p>&nbsp;public Consumer(Stack stack, int level) {<br />
&nbsp;&nbsp;this.stack = stack;<br />
&nbsp;&nbsp;this.level = level;<br />
&nbsp;}</p>
<p>&nbsp;public void run() {<br />
&nbsp;&nbsp;for (int i = 0; i &lt;= level; i++) {<br />
&nbsp;&nbsp;&nbsp;Thing thing = stack.pop();<br />
&nbsp;&nbsp;&nbsp;System.out.println("消费: " + thing.id);<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(800);<br />
&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}</p>
<p>public class ProducterConsumer {<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;int stackSize = 5;</p>
<p>&nbsp;&nbsp;Stack stack = new Stack(stackSize);<br />
&nbsp;&nbsp;// 存储量为5的容器<br />
&nbsp;&nbsp;Producer p = new Producer(stack, 10);<br />
&nbsp;&nbsp;Consumer c = new Consumer(stack, 10);<br />
&nbsp;&nbsp;new Thread(p).start();<br />
&nbsp;&nbsp;new Thread(c).start();<br />
&nbsp;}<br />
}<br />
</p>
<img src ="http://www.blogjava.net/balajinima/aggbug/297931.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-12 17:31 <a href="http://www.blogjava.net/balajinima/articles/297931.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java多态 </title><link>http://www.blogjava.net/balajinima/articles/297909.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Mon, 12 Oct 2009 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/297909.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/297909.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/297909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/297909.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/297909.html</trackback:ping><description><![CDATA[package test;<br /><br />class Base {<br />    int x = 1;<br />    static int y = 2;<br />    int z = 3;<br /><br />    int method() {<br />        return x;<br />    }<br />}<br /><br />class Subclass extends Base {<br />    int x = 4;<br />    int y = 5;<br />    static int z = 6;<br /><br />    int method() {<br />        return x;<br />    }<br />}<br /><br />public class PolymorphismTest1 {<br />    public static void main(String[] args) {<br />        <br />        Base bs = new Subclass();<br />        System.out.println("bs.x:"+bs.x + " bs.y:" + bs.y + " bs.z:" + bs.z);<br />        System.out.println("bs.method:"+bs.method());<br />        System.out.println("================================");<br />        <br />        Base bb = new Base();<br />        System.out.println("bb.x:"+bb.x + " bb.y:" + bb.y + " bb.z:" + bb.z);<br />        System.out.println("bb.method:"+bb.method());<br />        System.out.println("================================");<br />        <br />        Subclass ss = new Subclass();<br />        System.out.println("ss.x:"+ss.x + " ss.y:" + ss.y + " ss.z:" + ss.z);<br />        System.out.println("ss.method:"+ss.method());<br />        System.out.println("================================");<br />        <br />        Subclass sb = (Subclass)new Base();//Exception in thread "main" java.lang.ClassCastException: test.Base<br />        //System.out.println("sb.x:"+sb.x + " sb.y:" + sb.y + " sb.z:" + sb.z);<br />        //System.out.println("sb.method:"+sb.method());<br />        //System.out.println("================================");<br />    }<br />}<br /><br /><br /><br /><br />=======================<br />结果：<br />=======================<br />bs.x:1 bs.y:2 bs.z:3<br />bs.method:4<br />================================<br />bb.x:1 bb.y:2 bb.z:3<br />bb.method:1<br />================================<br />ss.x:4 ss.y:5 ss.z:6<br />ss.method:4<br />================================<br /><br /><br /><br /><img src ="http://www.blogjava.net/balajinima/aggbug/297909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-10-12 16:28 <a href="http://www.blogjava.net/balajinima/articles/297909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java对象的序列化和反序列化实践</title><link>http://www.blogjava.net/balajinima/articles/286124.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Thu, 09 Jul 2009 09:52:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/286124.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/286124.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/286124.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/286124.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/286124.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
&nbsp;
<div id="artibody"><!-- Error -->
<div class="clear1">　　当两个进程在进行远程通信时，彼此可以发送各种类型的数据。无论是何种类型的数据，都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列，才能在网络上传送；接收方则需要把字节序列再恢复为Java对象。 <br />
<br />
　　把Java对象转换为字节序列的过程称为对象的序列化。<br />
<br />
　　把字节序列恢复为Java对象的过程称为对象的反序列化。<br />
<br />
　　对象的序列化主要有两种用途：<br />
<br />
　　1） 把对象的字节序列永久地保存到<a class="fllink" href="http://product.yesky.com/harddisk/" target="_bank">硬盘</a>上，通常存放在一个文件中；<br />
<br />
　　2） 在网络上传送对象的字节序列。<br />
<br />
　　<strong>一． JDK类库中的序列化API</strong><br />
<br />
　　java.io.ObjectOutputStream代表对象输出流，它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化，把得到的字节序列写到一个目标输出流中。<br />
<br />
　　java.io.ObjectInputStream代表对象输入流，它的readObject()方法从一个源输入流中读取字节序列，再把它们反序列化为一个对象，并将其返回。、<br />
<br />
　　只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口，实现Externalizable接口的类完全由自身来控制序列化的行为，而仅实现Serializable接口的类可以采用默认的序列化方式 。<br />
<br />
　　对象序列化包括如下步骤：<br />
<br />
　　1） 创建一个对象输出流，它可以包装一个其他类型的目标输出流，如文件输出流；<br />
<br />
　　2） 通过对象输出流的writeObject()方法写对象。<br />
<br />
　　对象反序列化的步骤如下：<br />
<br />
　　1） 创建一个对象输入流，它可以包装一个其他类型的源输入流，如文件输入流；<br />
<br />
　　2） 通过对象输入流的readObject()方法读取对象。<br />
<br />
　　下面让我们来看一个对应的例子，类的内容如下：<br />
<br />
<table width="90%" bgcolor="#d8d7d3" align="center">
    <tbody>
        <tr>
            <td>import java.io.*;<br />
            import java.util.Date;<br />
            <br />
            /**<br />
            * 对象的序列化和反序列化测试类. <br />
            * @author &lt;a href="mailto:xiexingxing1121@126.com"&gt;AmigoXie&lt;/a&gt;<br />
            * @version 1.0 <br />
            * Creation date: 2007-9-15 - 下午21:45:48<br />
            */<br />
            <br />
            public class ObjectSaver {<br />
            　/**<br />
            　* @param args<br />
            　* @author &lt;a href="mailto:xiexingxing1121@126.com"&gt;AmigoXie&lt;/a&gt;<br />
            　* Creation date: 2007-9-15 - 下午21:45:37<br />
            　*/<br />
            <br />
            public static void main(String[] args) throws Exception {<br />
            　ObjectOutputStream out = new ObjectOutputStream<br />
            (new FileOutputStream("D:""objectFile.obj"));<br />
            <br />
            　//序列化对象<br />
            <br />
            　Customer customer = new Customer("阿蜜果", 24);<br />
            　out.writeObject("你好!");<br />
            　out.writeObject(new Date());<br />
            　out.writeObject(customer);<br />
            　out.writeInt(123); //写入基本类型数据<br />
            　out.close();<br />
            　//反序列化对象<br />
            <br />
            　ObjectInputStream in = new ObjectInputStream<br />
            (new FileInputStream("D:""objectFile.obj"));<br />
            <br />
            　System.out.println("obj1=" + (String) in.readObject());<br />
            　System.out.println("obj2=" + (Date) in.readObject());<br />
            　Customer obj3 = (Customer) in.readObject();<br />
            　System.out.println("obj3=" + obj3);<br />
            　int obj4 = in.readInt();<br />
            　System.out.println("obj4=" + obj4);<br />
            　in.close();<br />
            }<br />
            }<br />
            <br />
            class Customer implements Serializable {<br />
            private String name;<br />
            private int age;<br />
            public Customer(String name, int age) {<br />
            this.name = name;<br />
            this.age = age;<br />
            }<br />
            <br />
            public String toString() {<br />
            return "name=" + name + ", age=" + age;<br />
            }<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　输出结果如下：<br />
<br />
<table width="90%" bgcolor="#d8d7d3" align="center">
    <tbody>
        <tr>
            <td>obj1=你好!<br />
            <br />
            obj2=Sat Sep 15 22:02:21 CST 2007<br />
            <br />
            obj3=name=阿蜜果, age=24<br />
            <br />
            obj4=123</td>
        </tr>
    </tbody>
</table>
<br />
　　因此例比较简单，在此不再详述。<br />
<br />
　　<strong>二．实现Serializable接口</strong><br />
<br />
　　ObjectOutputStream只能对Serializable接口的类的对象进行序列化。默认情况下，ObjectOutputStream按照默认方式序列化，这种序列化方式仅仅对对象的非transient的实例变量进行序列化，而不会序列化对象的transient的实例变量，也不会序列化静态变量。<br />
<br />
　　当ObjectOutputStream按照默认方式反序列化时，具有如下特点：<br />
<br />
　　1） 如果在<a class="fllink" href="http://product.yesky.com/memory/" target="_bank">内存</a>中对象所属的类还没有被加载，那么会先加载并初始化这个类。如果在classpath中不存在相应的类文件，那么会抛出ClassNotFoundException；<br />
<br />
　　2） 在反序列化时不会调用类的任何构造方法。<br />
<br />
　　如果用户希望控制类的序列化方式，可以在可序列化类中提供以下形式的writeObject()和readObject()方法。<br />
<br />
<table width="90%" bgcolor="#d8d7d3" align="center">
    <tbody>
        <tr>
            <td>private void writeObject(java.io.ObjectOutputStream out) throws IOException<br />
            <br />
            private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;</td>
        </tr>
    </tbody>
</table>
<br />
　　当ObjectOutputStream对一个Customer对象进行序列化时，如果该对象具有writeObject()方法，那么就会执行这一方法，否则就按默认方式序列化。在该对象的writeObjectt()方法中，可以先调用ObjectOutputStream的defaultWriteObject()方法，使得对象输出流先执行默认的序列化操作。同理可得出反序列化的情况，不过这次是defaultReadObject()方法。<br />
<br />
　　有些对象中包含一些敏感信息，这些信息不宜对外公开。如果按照默认方式对它们序列化，那么它们的序列化数据在网络上传输时，可能会被不法份子窃取。对于这类信息，可以对它们进行加密后再序列化，在反序列化时则需要解密，再恢复为原来的信息。<br />
<br />
　　默认的序列化方式会序列化整个对象图，这需要递归遍历对象图。如果对象图很复杂，递归遍历操作需要消耗很多的空间和时间，它的内部数据结构为双向列表。<br />
<br />
　　在应用时，如果对某些成员变量都改为transient类型，将节省空间和时间，提高序列化的性能。<br />
<br />
　　<strong>三． 实现Externalizable接口</strong><br />
<br />
　　Externalizable接口继承自Serializable接口，如果一个类实现了Externalizable接口，那么将完全由这个类控制自身的序列化行为。Externalizable接口声明了两个方法：<br />
<br />
<table width="90%" bgcolor="#d8d7d3" align="center">
    <tbody>
        <tr>
            <td>public void writeExternal(ObjectOutput out) throws IOException<br />
            <br />
            public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException</td>
        </tr>
    </tbody>
</table>
<br />
　　前者负责序列化操作，后者负责反序列化操作。<br />
<br />
　　在对实现了Externalizable接口的类的对象进行反序列化时，会先调用类的不带参数的构造方法，这是有别于默认反序列方式的。如果把类的不带参数的构造方法删除，或者把该构造方法的访问权限设置为private、默认或protected级别，会抛出java.io.InvalidException: no valid constructor异常。<br />
<br />
　　<strong>四． 可序列化类的不同版本的序列化兼容性</strong><br />
<br />
　　凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量：<br />
<br />
<table width="90%" bgcolor="#d8d7d3" align="center">
    <tbody>
        <tr>
            <td>private static final long serialVersionUID;</td>
        </tr>
    </tbody>
</table>
<br />
　　以上serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改，再重新编译，新生成的类文件的serialVersionUID的取值有可能也会发生变化。<br />
<br />
　　类的serialVersionUID的默认值完全依赖于Java编译器的实现，对于同一个类，用不同的Java编译器编译，有可能会导致不同的serialVersionUID，也有可能相同。为了提高哦啊serialVersionUID的独立性和确定性，强烈建议在一个可序列化类中显示的定义serialVersionUID，为它赋予明确的值。显式地定义serialVersionUID有两种用途：<br />
<br />
　　1） 在某些场合，希望类的不同版本对序列化兼容，因此需要确保类的不同版本具有相同的serialVersionUID；<br />
<br />
　　2） 在某些场合，不希望类的不同版本对序列化兼容，因此需要确保类的不同版本具有不同的serialVersionUID。<br />
</div>
</div>
<img src ="http://www.blogjava.net/balajinima/aggbug/286124.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2009-07-09 17:52 <a href="http://www.blogjava.net/balajinima/articles/286124.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>体验JAVA 5的新增语言特性 </title><link>http://www.blogjava.net/balajinima/articles/146905.html</link><dc:creator>李云泽</dc:creator><author>李云泽</author><pubDate>Thu, 20 Sep 2007 12:10:00 GMT</pubDate><guid>http://www.blogjava.net/balajinima/articles/146905.html</guid><wfw:comment>http://www.blogjava.net/balajinima/comments/146905.html</wfw:comment><comments>http://www.blogjava.net/balajinima/articles/146905.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/balajinima/comments/commentRss/146905.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/balajinima/services/trackbacks/146905.html</trackback:ping><description><![CDATA[		<br />
		<div style="MARGIN-TOP: 1px; MARGIN-LEFT: 15px">
				<h2>
						<a title="永久链接：体验JAVA 5的新增语言特性" href="http://kenshinlk.javaeye.com/blog/60570">
								<font color="#002c99">体验JAVA 5的新增语言特性</font>
						</a>
				</h2>
		</div>
		<div style="MARGIN-TOP: 5px; MARGIN-LEFT: 15px">
				<b>关键字:</b> &#160; 体验JAVA 5的新增语言特性&#160;&#160;&#160;&#160; </div>
		<div style="MARGIN-TOP: 10px; MARGIN-LEFT: 15px; OVERFLOW: auto">
				<table width="100%">
						<tbody>
								<tr>
										<td>
												<p>
														<img height="1" alt="" src="http://dev2dev.bea.com.cn/images/dot6B6B6B.gif" width="100%" />
												</p>
												<p>　　Java 5.0发布了，许多人都将开始使用这个JDK版本的一些新增特性。从增强的for循环到诸如泛型(generic)之类更复杂的特性，都将很快出现在您所编写的代码中。我们刚刚完成了一个基于Java 5.0的大型任务，而本文就是要介绍我们使用这些新特性的体验。本文不是一篇入门性的文章，而是对这些特性以及它们所产生的影响的深入介绍，同时还给出了一些在项目中更有效地使用这些特性的技巧。 </p>
												<p>
														<strong>简介</strong>
														<br />　　在JDK 1.5的beta阶段，我们为BEA的Java IDE开发了一个Java 5编译器。因为我们实现了许多新特性，所以人们开始以新的方式利用它们；有些用法很聪明，而有些用法明显应该被列入禁用清单。编译器本身使用了新的语言特性，所以我们也获得了使用这些特性维护代码的直接体验。本文将介绍其中的许多特性和使用它们的体验。 <br />　　我们假定您已经熟悉了这些新特性，所以不再全面介绍每个特性，而是谈论一些有趣的、但很可能不太明显的内容和用法。这些技巧出自我们的实际体验，并大致按照语言特性进行了分类。 <br />　　我们将从最简单的特性开始，逐步过渡到高级特性。泛型所包含的内容特别丰富，因此占了本文一半的篇幅。</p>
												<p>
														<strong>增强的for循环</strong>
														<br />　　为了迭代集合和数组，增强的for循环提供了一个简单、兼容的语法。有两点值得一提： </p>
												<p>
														<strong>Init表达式</strong>
														<br />　　在循环中，初始化表达式只计算一次。这意味着您通常可以移除一个变量声明。在这个例子中，我们必须创建一个整型数组来保存computeNumbers()的结果，以防止每一次循环都重新计算该方法。您可以看到，下面的代码要比上面的代码整洁一些，并且没有泄露变量numbers： <br /></p>
												<pre class="code">未增强的For：
int sum = 0;
Integer[] numbers = computeNumbers();
for (int i=0; i &lt; numbers.length ; i++)
    sum += numbers[i];
增强后的For： 
int sum = 0;

for ( int number: computeNumbers() )
    sum += number;</pre>
												<p>
														<strong>局限性</strong>
														<br />有时需要在迭代期间访问迭代器或下标，看起来增强的for循环应该允许该操作，但事实上不是这样，请看下面的例子： </p>
												<pre class="code">for (int i=0; i &lt; numbers.length ; i++) {
    if (i != 0) System.out.print(",");
    System.out.print(numbers[i]);
}</pre>
												<p>　　我们希望将数组中的值打印为一个用逗号分隔的清单。我们需要知道目前是否是第一项，以便确定是否应该打印逗号。使用增强的for循环是无法获知这种信息的。我们需要自己保留一个下标或一个布尔值来指示是否经过了第一项。 　　这是另一个例子： </p>
												<pre class="code">for (Iterator<integer></integer> it = n.iterator() ; it.hasNext() ; )
    if (it.next() &lt; 0)
        it.remove();</pre>
												<p>　　在此例中，我们想从整数集合中删除负数项。为此，需要对迭代器调用一个方法，但是当使用增强的for 循环时，迭代器对我们来说是看不到的。因此，我们只能使用Java 5之前版本的迭代方法。 　　顺便说一下，这里需要注意的是，由于Iterator是泛型，所以其声明是Iterator<integer></integer>。许多人都忘记了这一点而使用了Iterator的原始格式。 </p>
												<p>
														<strong>注释</strong>
														<br />　　注释处理是一个很大的话题。因为本文只关注核心的语言特性，所以我们不打算涵盖它所有的可能形式和陷阱。　　我们将讨论内置的注释（SuppressWarnings，Deprecated和Override）以及一般注释处理的局限性。 </p>
												<p>
														<strong>Suppress Warnings</strong>
														<br />　　该注释关闭了类或方法级别的编译器警告。有时候您比编译器更清楚地知道，代码必须使用一个被否决的方法或执行一些无法静态确定是否类型安全的动作，而使用：</p>
												<pre class="code">@SuppressWarnings("deprecation")
public static void selfDestruct() {
    Thread.currentThread().stop();
}</pre>
												<p>　　这可能是内置注释最有用的地方。遗憾的是，1.5.0_04的javac不支持它。但是1.6支持它，并且Sun正在努力将其向后移植到1.5中。 <br />Eclipse 3.1中支持该注释，其他IDE也可能支持它。这允许您把代码彻底地从警告中解脱出来。如果在编译时出现警告，可以确定是您刚刚把它添加进来——以帮助查看那些可能不安全的代码。随着泛型的添加，它使用起来将更趁手。 </p>
												<p>
														<strong>Deprecated</strong>
														<br />　　遗憾的是，Deprecated没那么有用。它本来旨在替换@deprecated javadoc标签，但是由于它不包含任何字段，所以也就没有方法来建议deprecated类或方法的用户应该使用什么做为替代品。大多数用法都同时需要javadoc标签和这个注释。 </p>
												<p>
														<strong>Override</strong>
														<br />　　Override表示，它所注释的方法应该重写超类中具有相同签名的方法： </p>
												<pre class="code">@Override
public int hashCode() {
    ...
}</pre>
												<p>　　看上面的例子，如果没有在hashCode中将&#8220;C&#8221;大写，在编译时不会出现错误，但是在运行时将无法像期望的那样调用该方法。通过添加Override标签，编译器会提示它是否真正地执行了重写。 <br />　　在超类发生改变的情况中，这也很有帮助。如果向该方法中添加一个新参数，而且方法本身也被重命名了，那么子类将突然不能编译，因为它不再重写超类的任何东西。 </p>
												<p>
														<strong>其它注释<br /></strong>　　注释在其他场景中非常有用。当不是直接修改行为而是增强行为时，特别是在添加样板代码的情况下，注释在诸如EJB和<a href="http://dev2dev.bea.com/pub/a/2004/10/Anil_WServices.html" target="_blank"><font color="#002c99">Web services</font></a>这样的框架中运行得非常好。 <br />注释不能用做预处理器。Sun的设计特别预防了完全因为注释而修改类的字节码。这样可以正确地理解该语言的成果，而且IDE之类的工具也可以执行深入的代码分析和重构之类的功能。 <br />注释不是银弹。第一次遇到的时候，人们试图尝试各种技巧。请看下面这个从别人那里获得的建议： </p>
												<pre class="code">public class Foo {
&#160;
    @Property
    private int bar;
&#160;
}</pre>
												<p>　　其思想是为私有字段bar自动创建getter和setter方法。遗憾的是，这个想法有两个失败之处：1)它不能运行，2)它使代码难以阅读和处理。 　　它是无法实现的，因为前面已经提到了，Sun特别阻止了对出现注释的类进行修改。 <br />　　即使是可能的，它也不是一个好主意，因为它使代码可读性差。第一次看到这段代码的人会不知道该注释创建了方法。此外，如果将来您需要在这些方法内部执行一些操作，注释也是没用的。 　　总之，不要试图用注释去做那些常规代码可以完成的事情。 </p>
												<p>
														<strong>枚举 </strong>
														<br />　　enum非常像public static final int声明，后者作为枚举值已经使用了很多年。对int所做的最大也是最明显的改进是类型安全——您不能错误地用枚举的一种类型代替另一种类型，这一点和int不同，所有的int对编译器来说都是一样的。除去极少数例外的情况，通常都应该用enum实例替换全部的枚举风格的int结构。 <br />　　枚举提供了一些附加的特性。EnumMap和EnumSet这两个实用类是专门为枚举优化的标准集合实现。如果知道集合只包含枚举类型，那么应该使用这些专门的集合来代替HashMap或HashSet。 <br />　　大部分情况下，可以使用enum对代码中的所有public static final int做插入替换。它们是可比的，并且可以静态导入，所以对它们的引用看起来是等同的，即使是对于内部类（或内部枚举类型）。注意，比较枚举类型的时候，声明它们的指令表明了它们的顺序值。 <br /><br /><strong>&#8220;隐藏的&#8221;静态方法 </strong><br />　　两个静态方法出现在所有枚举类型声明中。因为它们是枚举子类上的静态方法，而不是Enum本身的方法，所以它们在java.lang.Enum的javadoc中没有出现。 <br />　　第一个是values()，返回一个枚举类型所有可能值的数组。 <br />　　第二个是valueOf()，为提供的字符串返回一个枚举类型，该枚举类型必须精确地匹配源代码声明。 <br /><strong>方法<br /></strong>　　关于枚举类型，我们最喜欢的一个方面是它可以有方法。过去您可能需要编写一些代码，对public static final int进行转换，把它从数据库类型转换为JDBC URL。而现在则可以让枚举类型本身带一个整理代码的方法。下面就是一个例子，包括DatabaseType枚举类型的抽象方法以及每个枚举实例中提供的实现： <br /></p>
												<pre class="code">  public enum  DatabaseType {
  ORACLE {
  public String getJdbcUrl() {...}
  },
  MYSQL {
  public String getJdbcUrl() {...}
  };
  public abstract String getJdbcUrl();
  }</pre>
												<p>　　现在枚举类型可以直接提供它的实用方法。例如：<br /><br />DatabaseType dbType = ...;<br />String jdbcURL = dbType.getJdbcUrl();<br /><br />　　要获取URL，必须预先知道该实用方法在哪里。 </p>
												<p>
														<br />
														<strong>可变参数(Vararg)</strong>
														<br />　　正确地使用可变参数确实可以清理一些垃圾代码。典型的例子是一个带有可变的String参数个数的log方法： <br /></p>
												<pre class="code">    Log.log(String code)
    Log.log(String code,  String arg)
    Log.log(String code,  String arg1, String arg2)
    Log.log(String code,  String[] args)</pre>
												<p>　　当讨论可变参数时，比较有趣的是，如果用新的可变参数替换前四个例子，将是兼容的： <br />Log.log(String code, String... args)<br />　　所有的可变参数都是源兼容的——那就是说，如果重新编译log()方法的所有调用程序，可以直接替换全部的四个方法。然而，如果需要向后的二进制兼容性，那么就需要舍去前三个方法。只有最后那个带一个字符串数组参数的方法等效于可变参数版本，因此可以被可变参数版本替换。 <br /><strong><br />类型强制转换 </strong><br />　　如果希望调用程序了解应该使用哪种类型的参数，那么应该避免用可变参数进行类型强制转换。看下面这个例子，第一项希望是String，第二项希望是Exception： <br /></p>
												<pre class="code">    Log.log(Object...  objects) {
    String message = (String)objects[0];
    if (objects.length &gt; 1) {
    Exception e = (Exception)objects[1];
    // Do something with the exception
    }
    }</pre>
												<p>　　方法签名应该如下所示，相应的可变参数分别使用String和Exception声明： <br /><br />Log.log(String message, Exception e, Object... objects) {...}<br /><br />　　不要使用可变参数破坏类型系统。需要强类型化时才可以使用它。对于这个规则，PrintStream.printf()是一个有趣的例外：它提供类型信息作为自己的第一个参数，以便稍后可以接受那些类型。 <br /><strong><br />协变返回 </strong><br />　　协变返回的基本用法是用于在已知一个实现的返回类型比API更具体的时候避免进行类型强制转换。在下面这个例子中，有一个返回Animal对象的Zoo接口。我们的实现返回一个AnimalImpl对象，但是在JDK 1.5之前，要返回一个Animal对象就必须声明。:<br /></p>
												<pre class="code">    public interface Zoo  {
    public Animal getAnimal();
    }
  public class ZooImpl  implements Zoo {
  public Animal getAnimal(){
  return new AnimalImpl();
  }
  }</pre>
												<p>　　协变返回的使用替换了三个反模式： </p>
												<p>&#160;</p>
												<ul>
														<li>直接字段访问。为了规避API限制，一些实现把子类直接暴露为字段： </li>
												</ul>
												<p align="left">ZooImpl._animal</p>
												<ul>
														<li>另一种形式是，在知道实现的实际上是特定的子类的情况下，在调用程序中执行向下转换： </li>
												</ul>
												<p align="left">((AnimalImpl)ZooImpl.getAnimal()).implMethod();</p>
												<ul>
														<li>我看到的最后一种形式是一个具体的方法，该方法用来避免由一个完全不同的签名所引发的问题： </li>
												</ul>
												<p align="left">ZooImpl._getAnimal();<br /><br />　　这三种模式都有它们的问题和局限性。要么是不够整洁，要么就是暴露了不必要的实现细节。 <br /><strong><br />协变 </strong><br />　　协变返回模式就比较整洁、安全并且易于维护，它也不需要类型强制转换或特定的方法或字段： <br />public AnimalImpl getAnimal(){<br />return new AnimalImpl();<br />}<br />　　使用结果： <br />ZooImpl.getAnimal().implMethod();<br /><br /><strong>使用泛型<br />　　</strong>我们将从两个角度来了解泛型：使用泛型和构造泛型。我们不讨论List、Set和Map的显而易见的用法。知道泛型集合是强大的并且应该经常使用就足够了。 <br />　　我们将讨论泛型方法的使用以及编译器推断类型的方法。通常这些都不会出问题，但是当出问题时，错误信息会非常令人费解，所以需要了解如何修复这些问题。 </p>
												<p>
														<strong>泛型方法<br />　　</strong>除了泛型类型，Java 5还引入了泛型方法。在这个来自java.util.Collections的例子中，构造了一个单元素列表。新的List的元素类型是根据传入方法的对象的类型来推断的： </p>
												<pre class="code">static <t></t> List<t></t> Collections.singletonList(T o)
示例用法：
public List<integer></integer> getListOfOne() {
    return Collections.singletonList(1);
}</pre>
												<p>　　在示例用法中，我们传入了一个int。所以方法的返回类型就是List<integer></integer>。编译器把T推断为Integer。这和泛型类型是不同的，因为您通常不需要显式地指定类型参数。 <br />这也显示了自动装箱和泛型的相互作用。类型参数必须是引用类型：这就是为什么我们得到的是List<integer></integer>而不是List<int></int>。 </p>
												<p>
														<strong>不带参数的泛型方法<br />　　</strong>emptyList()方法与泛型一起引入，作为java.util.Collections中EMPTY_LIST字段的类型安全置换： </p>
												<pre class="code">static <t></t> List<t></t> Collections.emptyList()
示例用法： 
public List<integer></integer> getNoIntegers() {
    return Collections.emptyList();
}</pre>
												<p>　　与先前的例子不同，这个方法没有参数，那么编译器如何推断T的类型呢？基本上，它将尝试使用一次参数。如果没有起作用，它再次尝试使用返回或赋值类型。在本例中，返回的是List<integer></integer>，所以T被推断为Integer。 <br />　　如果在返回语句或赋值语句之外的位置调用泛型方法会怎么样呢？那么编译器将无法执行类型推断的第二次传送。在下面这个例子中，emptyList()是从条件运算符内部调用的： </p>
												<pre class="code">public List<integer></integer> getNoIntegers() {
    return x ? Collections.emptyList() : null;
}</pre>
												<p>　　因为编译器看不到返回上下文，也不能推断T，所以它放弃并采用Object。您将看到一个错误消息，比如：&#8220;无法将List&lt; Object &gt;转换为List<integer></integer>。&#8221; <br />为了修复这个错误，应显式地向方法调用传递类型参数。这样，编译器就不会试图推断类型参数，就可以获得正确的结果： </p>
												<pre class="code">return x ? Collections.<integer></integer>emptyList() : null;</pre>
												<p>　　这种情况经常发生的另一个地方是在方法调用中。如果一个方法带一个List<string></string>参数，并且需要为那个参数调用这个传递的emptyList()，那么也需要使用这个语法。 </p>
												<p>
														<strong>集合之外<br /></strong>　　这里有三个泛型类型的例子，它们不是集合，而是以一种新颖的方式使用泛型。这三个例子都来自标准的Java库： </p>
												<ul>
														<li>Class<t></t><br />Class在类的类型上被参数化了。这就使无需类型强制转换而构造一个newInstance成为可能。 
</li>
														<li>Comparable<t></t><br />Comparable被实际的比较类型参数化。这就在compareTo()调用时提供了更强的类型化。例如，String实现Comparable<string></string>。对除String之外的任何东西调用compareTo()，都会在编译时失败。 
</li>
														<li>Enum<e extends=""></e>&gt;<br />Enum被枚举类型参数化。一个名为Color的枚举类型将扩展Enum<color></color>。getDeclaringClass()方法返回枚举类型的类对象，在这个例子中就是一个Color对象。它与getClass()不同，后者可能返回一个无名类。 </li>
												</ul>
												<p>
														<strong>通配符<br />　　</strong>泛型最复杂的部分是对通配符的理解。我们将讨论三种类型的通配符以及它们的用途。 <br />　　首先让我们了解一下数组是如何工作的。可以从一个Integer[]为一个Number[]赋值。如果尝试把一个Float写到Number[]中，那么可以编译，但在运行时会失败，出现一个ArrayStoreException： </p>
												<pre class="code">Integer[] ia = new Integer[5];
Number[] na = ia;
na[0] = 0.5; // compiles, but fails at runtime
如果试图把该例直接转换成泛型，那么会在编译时失败，因为赋值是不被允许的：
List<integer></integer> iList = new ArrayList<integer></integer>();
List<number></number> nList = iList; // not allowed
nList.add(0.5);</pre>
												<p>　　如果使用泛型，只要代码在编译时没有出现警告，就不会遇到运行时ClassCastException。 </p>
												<p>
														<strong>上限通配符</strong>
														<br />　　我们想要的是一个确切元素类型未知的列表，这一点与数组是不同的。 <br />List<number></number>是一个列表，其元素类型是具体类型Number。 <br />List&lt;!--xtends Numb--&gt;是一个确切元素类型未知的列表。它是Number或其子类型。 </p>
												<p>
														<strong>上限<br />　　</strong>如果我们更新初始的例子，并赋值给List&lt;!--xtends Numb--&gt;，那么现在赋值就会成功了： </p>
												<pre class="code">List<integer></integer> iList = new ArrayList<integer></integer>();
List&lt;!--xtends Numb--&gt; nList = iList;
Number n = nList.get(0);
nList.add(0.5); // Not allowed</pre>
												<p>　　我们可以从列表中得到Number，因为无论列表的确切元素类型是什么（Float、Integer或Number），我们都可以把它赋值给Number。 <br />　　我们仍然不能把浮点类型插入列表中。这会在编译时失败，因为我们不能证明这是安全的。如果我们想要向列表中添加浮点类型，它将破坏iList的初始类型安全——它只存储Integer。 <br />　　通配符给了我们比数组更多的表达能力。 </p>
												<p>
														<strong>为什么使用通配符<br /></strong>　　在下面这个例子中，通配符用于向API的用户隐藏类型信息。在内部，Set被存储为CustomerImpl。而API的用户只知道他们正在获取一个Set，从中可以读取Customer。 <br />此处通配符是必需的，因为无法从Set<customerimpl></customerimpl>向Set<customer></customer>赋值： </p>
												<pre class="code">public class CustomerFactory {
    private Set<customerimpl></customerimpl> _customers;
    public Set&lt;!--xtends Custom--&gt; getCustomers() {
        return _customers;
    }
}</pre>
												<p>
														<strong>通配符和协变返回</strong>
														<br />　　通配符的另一种常见用法是和协变返回一起使用。与赋值相同的规则可以应用到协变返回上。如果希望在重写的方法中返回一个更具体的泛型类型，声明的方法必须使用通配符： </p>
												<pre class="code">public interface NumberGenerator {
    public List&lt;!--xtends Numb--&gt; generate();
}
public class FibonacciGenerator extends NumberGenerator {
    public List<integer></integer> generate() {
        ...
    }
}</pre>
												<p>　　如果要使用数组，接口可以返回Number[]，而实现可以返回Integer[]。 </p>
												<p>
														<strong>下限 </strong>
														<br />　　我们所谈的主要是关于上限通配符的。还有一个下限通配符。List&lt;!--uper Numb--&gt;是一个确切&#8220;元素类型&#8221;未知的列表，但是可能是Mnumber，或者Number的超类型。所以它可能是一个List<number></number>或一个List&lt; Object&gt;。 <br />　　下限通配符远没有上限通配符那样常见，但是当需要它们的时候，它们就是必需的。 </p>
												<p>
														<strong>下限与上限<br /></strong>
												</p>
												<pre class="code">List&lt;!--xtends Numb--&gt; readList = new ArrayList<integer></integer>();
Number n = readList.get(0);

List&lt;!--uper Numb--&gt; writeList = new ArrayList&lt; Object&gt;();
writeList.add(new Integer(5));</pre>
												<p>　　第一个是可以从中读数的列表。 <br />　　第二个是可以向其写数的列表。 </p>
												<p>
														<strong>无界通配符</strong>
														<br />　　最后，List列表的内容可以是任何类型，而且它与List&lt;!--xtends Obje--&gt;几乎相同。可以随时读取Object，但是不能向列表中写入内容。 </p>
												<p>
														<strong>公共API中的通配符 </strong>
														<br />　　总之，正如前面所说，通配符在向调用程序隐藏实现细节方面是非常重要的，但即使下限通配符看起来是提供只读访问，由于remove(int position)之类的非泛型方法，它们也并非如此。如果您想要一个真正不变的集合，可以使用java.util.Collection上的方法，比如unmodifiableList()。 <br />　　编写API的时候要记得通配符。通常，在传递泛型类型时，应该尝试使用通配符。它使更多的调用程序可以访问API。 <br />　　通过接收List&lt;!--xtends Numb--&gt;而不是List<number></number>，下面的方法可以由许多不同类型的列表调用： </p>
												<pre class="code">void removeNegatives(List&lt;!--xtends Numb--&gt; list);</pre>
												<p>
														<strong>构造泛型类型</strong>
														<br />　　现在我们将讨论构造自己的泛型类型。我们将展示一些例子，其中通过使用泛型可以提高类型安全性，我们还将讨论一些实现泛型类型时的常见问题。</p>
												<p>
														<strong>集合风格(Collection-like)的函数</strong>
														<br />　　第一个泛型类的例子是一个集合风格的例子。Pair有两个类型参数，而且字段是类型的实例： </p>
												<pre class="code">public final class Pair {
    public final A first;
    public final B second;

    public Pair(A first, B second) {
        this.first = first;
        this.second = second;
    }
}</pre>
												<p>　　这使从方法返回两个项而无需为每个两种类型的组合编写专用的类成为可能。另一种方法是返回Object[]，而这样是类型不安全或者不整洁的。 <br />在下面的用法中，我们从方法返回一个File和一个Boolean。方法的客户端可以直接使用字段而无需类型强制转换： </p>
												<pre class="code">public Pair getFileAndWriteStatus(String path){
    // create file and status
    return new Pair(file, status);
}

Pair result = getFileAndWriteStatus("...");
File f = result.first;
boolean writeable = result.second;</pre>
												<p>
														<strong>集合之外 </strong>
														<br />　　在下面这个例子中，泛型被用于附加的编译时安全性。通过把DBFactory类参数化为所创建的Peer类型，您实际上是在强制Factory子类返回一个Peer的特定子类型： </p>
												<pre class="code">public abstract class DBFactory<t extends="" dbpeer=""></t> {
    protected abstract T createEmptyPeer();
    public List<t></t> get(String constraint) {
        List<t></t> peers = new ArrayList<t></t>();
        // database magic
        return peers;
    }
}
通过实现DBFactory<customer></customer>，CustomerFactory必须从createEmptyPeer()返回一个Customer：
public class CustomerFactory extends DBFactory<customer></customer>{

    public Customer createEmptyPeer() {
        return new Customer();
    }
}</pre>
												<p>
														<strong>泛型方法<br /></strong>　　不管想要对参数之间还是参数与返回类型之间的泛型类型施加约束，都可以使用泛型方法： <br />　　例如，如果编写的反转函数是在位置上反转，那么可能不需要泛型方法。然而，如果希望反转返回一个新的List，那么可能会希望新List的元素类型与传入的List的类型相同。在这种情况下，就需要一个泛型方法： </p>
												<p>
														<br />
														<t>
														</t>List<t></t> reverse(List<t></t> list) </p>
												<p>
														<strong>具体化<br /></strong>　　当实现一个泛型类时，您可能想要构造一个数组T[]。因为泛型是通过擦除(erasure)实现的，所以这是不允许的。 <br />　　您可以尝试把Object[]强制转换为T[]。但这是不安全的。 </p>
												<p>
														<strong>具体化解决方案<br />　　</strong>按照泛型教程的惯例，解决方案使用的是&#8220;类型令牌&#8221;，通过向构造函数添加一个Class<t></t>参数，可以强制客户端为类的类型参数提供正确的类对象： </p>
												<pre class="code">public class ArrayExample<t></t> {
    private Class<t></t> clazz;

    public ArrayExample(Class<t></t> clazz) {
        this.clazz = clazz;
    }

    public T[] getArray(int size) {
        return (T[])Array.newInstance(clazz, size);
    }
}</pre>
												<p>　　为了构造ArrayExample<string></string>，客户端必须把String.class传递给构造函数，因为String.class的类型是Class<string></string>。 <br />拥有类对象使构造一个具有正确元素类型的数组成为可能。 </p>
												<p>
														<strong>结束语</strong>
														<br />　　总而言之，新的语言特性有助于从根本上改变Java。通过了解在什么场景下使用以及如何使用这些新特性，您将会编写出更好的代码。</p>
												<p>
														<strong>补充阅读 </strong>
												</p>
												<ul>
														<li>
																<a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/" target="_blank">
																		<font color="#002c99">Enhancements in JDK 5</font>
																</a>——JDK 5中新特性的官方列表 
</li>
														<li>
																<a href="http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf" target="_blank">
																		<font color="#002c99">Generics Tutorial</font>
																</a>(PDF)——Gilad Bracha的泛型教程 
</li>
														<li>dev2dev <a href="http://dev2dev.bea.com/devcenters/" target="_blank"><font color="#002c99">Developer Centers</font></a></li>
												</ul>
												<p>&#160;</p>
												<p>
														<strong>原文出处:</strong>Experiences with the New Java 5 Language Features <a href="http://dev2dev.bea.com/pub/a/2005/09/java_5_features.html" target="_blank"><font color="#002c99">http://dev2dev.bea.com/pub/a/2005/09/java_5_features.html</font></a> &lt;!--文章其他信息--&gt;</p>
												<div class="dot001">
														<img height="1" alt="" src="http://dev2dev.bea.com.cn/images/_.gif" width="100%" />
												</div>
												<p>
												</p>
												<table cellspacing="0" cellpadding="3" width="100%" border="0">
														<tbody>
																<tr valign="bottom">
																		<td colspan="2" height="20">&#160;<span class="h2b">作者简介</span></td>
																</tr>
																<tr>
																		<td valign="top" align="middle">&#160;</td>
																		<td>
																				<a href="http://dev2dev.bea.com/pub/au/333" target="_blank">
																						<font color="#002c99">Jess Garms</font>
																				</a>是BEA Systems中Javelin编译器团队的领导者。在此之前，Jess致力于BEA的 Java IDE，WebLogic Workshop。此外，他在密码学方面也具有丰富的经验。他还与他人合著了&#8220;Professional Java Security&#8221;，由Wrox出版社出版。</td>
																</tr>
																<tr>
																		<td valign="top" align="middle">&#160;</td>
																		<td>
																				<a href="http://dev2dev.bea.com/pub/au/334" target="_blank">
																						<font color="#002c99">Tim Hanson</font>
																				</a>是BEA Systems中Javelin编译器的架构师。Tim对BEA的Java编译器做了很多开发工作，该编译器是最早兼容1.5的实现之一。他曾经编写过许多其他的编译器，包括他在IBM时编写的CORBA/IDL编译器，以及XQuery编译器。</td>
																</tr>
														</tbody>
												</table>
										</td>
								</tr>
						</tbody>
				</table>
		</div>
 <img src ="http://www.blogjava.net/balajinima/aggbug/146905.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/balajinima/" target="_blank">李云泽</a> 2007-09-20 20:10 <a href="http://www.blogjava.net/balajinima/articles/146905.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>