北京尚学堂-cctv央视网广告合作伙伴,专业IT培训机构,口碑最好的java培训、,iOS培训,android培训,hadoop大数据培训,web前端,0元入学,先就业后付款,平均就业薪水9500以上北京尚学堂提供在Java编程中,有些知识并不能仅通过语言规范或者标准API文档就能学到的。在本文中,我会尽量收集一些最常用的习惯用法,特别是很难猜到的用法。(JoshuaBloch的《EffectiveJava》对这个话题给出了更详尽的论述,可以从这本书里学习更多的用法。)我把本文的所有代码都放在公共场所里。你可以根据自己的喜好去复制和修改任意的代码片段,不需要任何的凭证。目录实现:oequals()ohashCode()ocompareTo()oclone()应用:oStringBuilder/StringBufferoRandom.nextInt(int)oIterator.remove()oStringBuilder.reverse()oThread/Runnableotry-finally输入/输出:o从输入流里读取字节数据o从输入流里读取块数据o从文件里读取文本o向文件里写文本预防性检测:o数值o对象o数组索引o数组区间数组:o填充元素o复制一个范围内的数组元素o调整数组大小包装o个字节包装成一个into分解成4个字节实现equals()北京尚学堂-cctv央视网广告合作伙伴,专业IT培训机构,口碑最好的java培训、,iOS培训,android培训,hadoop大数据培训,web前端,0元入学,先就业后付款,平均就业薪水9500以上1234567891011121314151617classPerson{Stringname;intbirthYear;byte[]raw;publicbooleanequals(Objectobj){if(!objinstanceofPerson)returnfalse;Personother=(Person)obj;returnname.equals(other.name)&&birthYear==other.birthYear&&Arrays.equals(raw,other.raw);}publicinthashCode(){...}}参数必须是Object类型,不能是外围类。foo.equals(null)必须返回false,不能抛NullPointerException。(注意,nullinstanceof任意类总是返回false,因此上面的代码可以运行。)基本类型域(比如,int)的比较使用==,基本类型数组域的比较使用Arrays.equals()。覆盖equals()时,记得要相应地覆盖hashCode(),与equals()保持一致。参考:java.lang.Object.equals(Object)。实现hashCode()123456789101112classPerson{Stringa;Objectb;bytec;int[]d;publicinthashCode(){returna.hashCode()+b.hashCode()+c+Arrays.hashCode(d);}publicbooleanequals(Objecto){...}}当x和y两个对象具有x.equals(y)==true,你必须要确保x.hashCode()==y.hashCode()。根据逆反命题,如果x.hashCode()!=y.hashCode(),那么x.equals(y)==false必定成立。你不需要保证,当x.equals(y)==false时,x.hashCode()!=y.hashCode()。但是,如果你可以尽可能地使它成立的话,这会提高哈希表的性能。北京尚学堂-cctv央视网广告合作伙伴,专业IT培训机构,口碑最好的java培训、,iOS培训,android培训,hadoop大数据培训,web前端,0元入学,先就业后付款,平均就业薪水9500以上hashCode()最简单的合法实现就是简单地return0;虽然这个实现是正确的,但是这会导致HashMap这些数据结构运行得很慢。参考:java.lang.Object.hashCode()。实现compareTo()12345678910111213141516171819classPersonimplementsComparablePerson{StringfirstName;StringlastName;intbirthdate;//ComparebyfirstName,breaktiesbylastName,finallybreaktiesbybirthdatepublicintcompareTo(Personother){if(firstName.compareTo(other.firstName)!=0)returnfirstName.compareTo(other.firstName);elseif(lastName.compareTo(other.lastName)!=0)returnlastName.compareTo(other.lastName);elseif(birthdateother.birthdate)return-1;elseif(birthdateother.birthdate)return1;elsereturn0;}}总是实现泛型版本Comparable而不是实现原始类型Comparable。因为这样可以节省代码量和减少不必要的麻烦。只关心返回结果的正负号(负/零/正),它们的大小不重要。Comparator.compare()的实现与这个类似。参考:java.lang.Comparable。实现clone()12345678classValuesimplementsCloneable{Stringabc;doublefoo;int[]bars;Datehired;publicValuesclone(){try{北京尚学堂-cctv央视网广告合作伙伴,专业IT培训机构,口碑最好的java培训、,iOS培训,android培训,hadoop大数据培训,web前端,0元入学,先就业后付款,平均就业薪水9500以上91011121314151617Valuesresult=(Values)super.clone();result.bars=result.bars.clone();result.hired=result.hired.clone();returnresult;}catch(CloneNotSupportedExceptione){//ImpossiblethrownewAssertionError(e);}}}使用super.clone()让Object类负责创建新的对象。基本类型域都已经被正确地复制了。同样,我们不需要去克隆String和BigInteger等不可变类型。手动对所有的非基本类型域(对象和数组)进行深度复制(deepcopy)。实现了Cloneable的类,clone()方法永远不要抛CloneNotSupportedException。因此,需要捕获这个异常并忽略它,或者使用不受检异常(uncheckedexception)包装它。不使用Object.clone()方法而是手动地实现clone()方法是可以的也是合法的。参考:java.lang.Object.clone()、java.lang.Cloneable()。使用StringBuilder或StringBuffer1234567891011//join([a,b,c])-aandbandcStringjoin(ListStringstrs){StringBuildersb=newStringBuilder();booleanfirst=true;for(Strings:strs){if(first)first=false;elsesb.append(and);sb.append(s);}returnsb.toString();}不要像这样使用重复的字符串连接:s+=item,因为它的时间效率是O(n^2)。使用StringBuilder或者StringBuffer时,可以使用append()方法添加文本和使用toString()方法去获取连接起来的整个文本。优先使用StringBuilder,因为它更快。StringBuffer的所有方法都是同步的,而你通常不需要同步的方法。参考java.lang.StringBuilder、java.lang.StringBuffer。生成一个范围内的随机整数北京尚学堂-cctv央视网广告合作伙伴,专业IT培训机构,口碑最好的java培训、,iOS培训,android培训,hadoop大数据培训,web前端,0元入学,先就业后付款,平均就业薪水9500以上123456Randomrand=newRandom();//Between1and6,inclusiveintdiceRoll(){returnrand.nextInt(6)+1;}总是使用JavaAPI方法去生成一个整数范围内的随机数。不要试图去使用Math.abs(rand.nextInt())%n这些不确定的用法,因为它的结果是有偏差的。此外,它的结果值有可能是负数,比如当rand.nextInt()==Integer.MIN_VALUE时就会如此。参考:java.util.Random.nextInt(int)。使用Iterator.remove()1234567voidfilter(ListStringlist){for(IteratorStringiter=list.iterator();iter.hasNext();){Stringitem=iter.next();if(...)iter.remove();}}remove()方法作用在next()方法最近返回的条目上。每个条目只能使用一次remove()方法。参考:java.util.Iterator.remove()。返转字符串123Stringreverse(Strings){returnnewStringBuilder(s).reverse().toString();}这个方法可能应该加入Java标准库。参考:java.lang.StringBuilder.reverse()。启动一条线程下面的三个例子使用了不同的方式完成了同样的事情。实现Runnnable的方式:12345voidstartAThread0(){newThread(newMyRunnable()).start();}classMyRunnableimplementsRunnable{北京尚学堂-cctv央视网广告合作伙伴,专业IT培训机构,口碑最好的java培训、,iOS培训,android培训,hadoop大数据培训,web前端,0元入学,先就业后付款,平均就业薪水9500以上6789publicvoidrun(){...}}继承Thread的方式:123456789voidstartAThread1(){newMyThread().start();}classMyThreadextendsThread{publicvoidrun(){...}}匿名继承Thread的方式:1234567voidstartAThread2(){newThread(){publicvoidrun(){...}}.start();}不要直接调用run()方法。总是调用Thread.start()方法,这个方法会创建一条新的线程并使新建的线程调用run()。参考:java.lang.Thread,java.lang.Runnable。使用try-finallyI/O流例子:123