??xml version="1.0" encoding="utf-8" standalone="yes"?>
与拆׃是把基本的数据cd自动的{为封装类型?/span>
如:自动装箱Q它可以直接把基本类型赋值给装cd
Integer num = 10 ;
Double d = 2d ;
自动拆箱Q它可以把封装类型赋值给基本cd
int num = new Integer(10);
double d = new Double(2d);
自动装箱与拆q功能事实上是~译器来帮您的忙Q编译器在编译时期依您所~写的语法,军_是否q行装箱或拆动作。在自动装箱时对于g-128?27之间的|它们被装׃ؓInteger对象后,会存在内存中被重用,所以范?.6中?=q行比较Ӟi1 ?i2实际上参考至同一个对象。如果超q了?128?27之间的|被装后的Integer对象q不会被重用Q即相当于每ơ装时都新Z个Integer对象Q所以范?.7使用==q行比较Ӟi1与i2参考的是不同的对象。所以不要过分依赖自动装׃拆箱Q您q是必须知道基本数据cd与对象的差异?/span>
public void testBoxingUnboxing() {
int i = 10;
Integer inta = i;
inta++;
inta += 1;
int j = inta;
assertTrue(j == inta);l果是:true//junit里面的方?/span>
assertTrue(j == new Integer(j)); l果是:true
assertTrue(10000 == new Integer(10000)); l果是:true
}
Integer i = 100.相当于编译器自动为您作以下的语法~译Q?/span>
Integer i = new Integer(100).所以自动装׃拆箱的功能是所谓的“~译器蜜p?#8221;(Compiler Sugar)Q虽然用这个功能很方便Q但在程序运行阶D|得了解Java的语义。例如下面的E序是可以通过~译的:
Integer i = null.int j = i.q样的语法在~译时期是合法的Q但是在q行时期会有错误Q因U写法相当于Q?/span>
Integer i = null.int j = i.intValue().null表示i没有参考至M的对象实体,它可以合法地指定l对象参考名U。由于实际上iq没有参考至M的对象,所以也׃可能操作intValue()ҎQ这样上面的写法在运行时会出现NullPointerException错误?/span>
自动装箱、拆q功能提供了方便性,但隐藏了一些细节,所以必d心。再来看范例4.6Q您认ؓl果是什么呢Q?/span>
Ü. 范例4.6 AutoBoxDemo2.java
public class AutoBoxDemo2 {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
if (i1 == i2)
System.out.println("i1 == i2");
else
System.out.println("i1 != i2").
}
}
从自动装׃拆箱的机制来看,可能会觉得结果是昄i1 == i2Q您是对的。那么范?.7的这个程序,您觉得结果是什么?
Ü. 范例4.7 AutoBoxDemo3.java
public class AutoBoxDemo3 {
public static void main(String[] args) {
Integer i1 = 200;
Integer i2 = 200;
if (i1 == i2)
System.out.println("i1 == i2");
else
System.out.println("i1 != i2");
}
}
l果是显C?/span>i1 != i2Q?/span>q有些o人惊Ӟ两个范例语法完全一P只不q改个数D已Q结果却相反?/span>
其实q与==q算W的比较有关Q在W?章中介绍q?=是用来比较两个基本数据类型的变量值是否相{,事实?=也用于判断两个对象引用名U是否参考至同一个对象?/span>
在自动装时对于g–128?/span>127之间的|它们被装׃ؓInteger对象后,会存在内存中被重用,所以范?/span>4.6中?/span>==q行比较Ӟi1 ?/span> i2实际上参考至同一个对象。如果超q了?/span>–128?/span>127之间的|被装后?/span>Integer对象q不会被重用Q即相当于每ơ装时都新Z?/span>Integer对象Q所以范?/span>4.7使用==q行比较Ӟi1?/span>i2参考的是不同的对象?/span>
所以不要过分依赖自动装׃拆箱Q您q是必须知道基本数据cd与对象的差异。范?.7最好还是依正规的方式来写,而不是依赖编译器蜜糖(Compiler Sugar)。例如范?.7必须改写?.8才是正确的?/span>
Ü. 范例4.8 AutoBoxDemo4.java
public class AutoBoxDemo4 {
public static void main(String[] args) {
Integer i1 = 200;
Integer i2 = 200;
if (i1.equals(i2))
System.out.println("i1 == i2");
else
System.out.println("i1 != i2");
}
}
l果q次是显C?span style="color: red">i1 == i2?/strong>使用q样的写法,怿也会比较攑ֿ一些,对于q些方便但隐藏细节的功能到底要不要用呢?基本上只有一个原则:如果您不定׃要用?/span>
脏读?TRANSACTION_READ_UNCOMMITTE):
Q允许的操作 ??nbsp; ????nbsp; Q脏数据Q不可重复读Q虚读) Q?/span>
表示,q个事务U别
允许d脏数?什么是脏数?是指还没有提交的数?
因ؓq个U别,是允怸个事?A)d另一个事?B)
q没有提交的数据.一旦事务B发生异常退?而修改了的数?br />
却还没提?或者新插入的数据和删除了的数据都还没有
提交,D事务A拿到了一些脏数据,或者错误数?
因此在这个事务别里是会发生脏读,重复?错误d;
止脏读(TRANSACTION_READ_COMMITTED):
Q允许的操作 ??nbsp; ??Q不可重复读Q虚读)Q?/span>
在这个别中,事务A
只能d一些提交的数据,如事务Bd了一条记?但是
如果事务B没有提交,那么事务A是读不到?所以该事务U别,
把脏ȝ屏蔽掉了.---却允讔R复读?和错误读?
什么是重复d?譬如,事务Ad了一个数?q个数据
的gؓ"helloworld",事务A准备利用q个数据来更C?br />
其他数据,但这个时候事务B开始对q个数据q行修改,q且
提交---"hello 无名?,׃是已l提交了,所以事务A是可?br />
看到q个数据?当事务A在没提交事务之前,它想看下数据
是否正确,q个时候它发现,新读出的数据已经和原来的数据
不一样了(q就是重复读?;
允许重复d(TRANSACTION_REPEATABLE_READ):
Q允许的操作 ??nbsp; ?写(仅允许插入,不允许删除和修改Q(虚读Q)
在这个别中,
是禁止了脏读,和取消了不可重复d,但是没有止错误d;
q个U别的事务比较严?当一个事务A在读取一个值的时?br />
是不允许另一个事务对该D行修改的;
Z允许重复d,可以选用该?因ؓTRANSACTION_READ_
COMMITEDq个事务U别,是允讔R复读取提交的数据?如果
事务A在读取一个数值的时?gؓ"Hello World!",但这个时
候事务B?Hello World"D行修改了,改ؓ"Hello EveryOne"
然后提交,当事务A再次去读取这个值的时?d现原来读?br />
的值改变了,变成?Hello EveryOne",Z防止出现q种情况
可以止重复提交,目的是ؓ了重复读取不会出?那么q个
时候就可以选择
TRANSACTION_REPEATABLE_READq个U别,
q个U别是用来止重复提交?
Q实际上是加了行锁,锁定了选中的数据,不允怿改,但是允许插入新的数据Q?br />
虽然q个时候是止了重复提?但却可以d删除,
比如事务A,作了个查询语?select * from 无名?"; q个时候是允许事务B做这L操作?
"insert into 无名?values(2,'aaa')"; q个时?
事务A再次做读取操作的时?却发现数据莫名其妙的
多了一?q就是所谓的---qdd;
止q读(TRANSACTION_SERIALIZABLE):
事务的最高?span style="color: #ff0000">(串行?nbsp; 操作)事务U别最?所耗费的性能也越?
止q读止了脏?止了重复提交和q读.
也就是当事务A在按条g查询的时?事务A一旦没有提
?M事务都不能对事务A的资源进行操?-- 保证
事务A的操作真正的原子?
注意:在Oracle中只支持两种U别:
TRANSACTION_READ_COMMITTED(默认的?(只有提交?br /> 才可以读?而每一个终端进行自qDML操作 都自动开启了一个事?/p>
TRANSACTION_SERIALIZABLE(H行化操?
public String intern()
一个初始ؓI的字符串池Q它q String
U有地维护?
当调?intern ҎӞ如果池已l包含一个等于此 String
对象的字W串Q用 equals(Object)
Ҏ定Q,则返回池中的字符丌Ӏ否则,此 String
对象d到池中,q返回此 String
对象的引用?
它遵循以下规则:对于L两个字符?s
?t
Q当且仅?s.equals(t)
?true
Ӟs.intern() == t.intern()
才ؓ true
?
String.intern();
再补充介l一点:存在?class文g中的帔R池,在运行期间被jvm装蝲Qƈ且可以扩充。String的intern()Ҏ是扩充帔R池的一个方法;当一个String实例str调用intern()ҎӞjava查找帔R池中是否有相同unicode的字W串帔RQ如果有Q则q回其引用,如果没有Q则在常量池中增加一个unicode{于str的字W串q返回它的引用?
?Q?
String s0=”kvill”;
String s1=new String(“kvill”);
String s2=new String(“kvill”);
System.out.println(s0==s1);
S1.intern();
S2=s2.intern();
System.out.println(s0==s1);
System.out.prntln(s0==s1.intern());
System.out.println(s0==s2);
l果为:
False
False //虽然执行了s1.intern()Q但它的q回值没有赋ls1
True
True
最后再破除一个错误的理解Q?
有h_“使用String.intern()Ҏ可以一个StringcM存到一个全局的String表中Q如果具有相同值的unicode字符串已l在q个表中Q那么该Ҏq回表中已有字符串的地址Q如果在表中没有相同值的字符Ԍ则将自己的地址注册到表?#8221;如果把这个全局的String表理解ؓ帔R吃的话,最后一句话“如果在表中没有相同值的字符Ԍ则将自己的地址注册到表?#8221;是错的?
?Q?
String s1=new String(“kvill”);
String s2=s1.intern();
System.out.println(s1==s1.intern());
System.out.println(s1+” ”+s2);
System.out.println(s2==s1.intern());
l果是:
False
Kvill kvill
True
我们没有声明一?#8221;kvill”帔RQ所以常量池中一开始没?#8221;kvill”的,当我们调用s1.intern()后就在常量池中新d了一?#8221;kvill”帔RQ原来的不在帔R池中?#8221;kvill”仍然存在Q也׃?#8220;把自q地址注册到常量池?#8221;了?
?Q?
String str1=”java”;
String str2=”blog”;
String s=str1+str2;
System.out.println(s==”javablog”);
l果是false。Jvm实对型如String str1=”java”;的String对象攑֜帔R池里Q但是它是在~译旉么做的,而String s=str1+str2;是在q行时刻才能知道Q也是说str1+str2是在堆里创徏的,所以结果ؓfalse了?
比较两个已经存在于字W串池中字符串对象可以用"=="q行Q拥有比equals操作W更快的速度
q是抛出已存在标准的异常Q步骤ؓQ?br />
1.扑ֈ一个合适的异常c?br />
2.创徏该类的对?br />
3.异常抛?br />
一旦抛出异常,该方法就不可能返回到调用者,q就意味着不必回的默认值或错误代码担忧了?br />
在程序中可能会遇CQ何标准异帔R无法正确描述清楚的问题,q时候就需要定义自q异常c,定义自己的异常类需要承自Exception 或者其子类Q如l承自IOException 一般要定义的Exception定义两个构造函敎ͼ一个是默认的无参的构造函敎ͼ另一个是带一个描q详l错误信息String的构造函敎ͼ类的toStringQ)Ҏ会打印出q些详细信息?/p>
现在可以像使用标准ExceptioncM样用自定义的ExceptioncM
可以用超cThrowablecȝgetMessageҎ得到详细的错误描qC息。或者toString()Ҏ打印该信息?br />
捕获异常Q?br />
如果语句exp1有可能抛Z个异常,或者说是调用了能够抛出一个异常的ҎQ那么我们可以在E序中捕莯异常
或者是q不捕获Q再ơ抛异常
再次抛出异常Q异帔RQ?br />
可以在catch块中再次抛出新的异常Q这样可以隐藏原始的错误l节
另一U更好的Ҏ
既抛出高U的异常Q又不会丢失原始的异怿息?/p>
finally子句Q发生三U情冉|Q会执行finally子句
1.try代码正常执行
2.try代码抛出一个在catch子句中捕L异常
3.try代码抛出一个未在catch子句中捕L异常
是说无论异常如何,finally子句中的代码都会执行
一般把一些资源回收的工作交给finally子句
最好把try-catch块和try-finally块分开Q这样可以提高代码的清晰?/p>
q样的另外一个好处是Q可以catch到finally子句中抛出的异常。这也就引发了另外一个问题,如果在try和finally中都抛出了异常,而且是不同类型的Q那么最后返回的是那一个呢Q答案是finally中抛出的异常会覆盖try中抛出的异常。从而丢׃try当中抛出的异怿息,让抛Ҏ的用者不能跟t异怿息。所以,在finally中执行的语句最好是不要抛出异常Q但是不q的是我们有时候不得不在finally中执行一些清楚操作如Q关闭输入流InputStream,但是InputStreamcȝ设计者ƈ没有q么设计Q将会抛出异常)?br />
׃finally子句L会执行,所以在finally中包含return值时Q是很危险的。假设我们利用return语句从try中返回,在方法返回之前finally子句的内容将会被执行。如果finally子句当中也包含一个return 语句Q那么这个return语句所q回的|会覆盖原先return的倹{?/p>
在这里如果调用i=f(2);那么i的值将会是2而不是期望的2*2=4
最后最重要的一点,关于一个方法是捕获一个异常还是抛出给调用他的Ҏ
有一点规?nbsp;
早抛出,晚捕P量把异常抛出给调用它的函数
实际上StringcM集成了Charset对象的用,StringcL两个用于~码和解码的函数
在输入输出流中有两个用于字节流转化为指定编码格式的字符的c?nbsp; InputStreamReader/OutputStreamReader
q两个类是读写流和读写器的桥?用法如下
该用法在我的另外一socket备忘的里面体CQ可网l传q来的utf-8格式~码的字节流正确的解码,以至于显C的时候不会出Cؕ?br />
//整数到字节数l的转换
public byte[] intToByte(int intValue) {
byte[] result = new byte[4];
result[0] = (byte) ( (intValue & 0xFF000000) >> 24);
result[1] = (byte) ( (intValue & 0x00FF0000) >> 16);
result[2] = (byte) ( (intValue & 0x0000FF00) >> 8);
result[3] = (byte) ( (intValue & 0x000000FF));
return result;
}
//字节数组到整数的转换
public static int byteToInt(byte[] b) {
public static int byteToInt(byte[] byteVal) {
int result = 0;
for (int i = 0; i < byteVal.length; i++) {
int tmpVal = (byteVal[i] << (8 * (3 - i)));
switch (i) {
case 0:
tmpVal = tmpVal & 0xFF000000;
break;
case 1:
tmpVal = tmpVal & 0x00FF0000;
break;
case 2:
tmpVal = tmpVal & 0x0000FF00;
break;
case 3:
tmpVal = tmpVal & 0x000000FF;
break;
}
result = result | tmpVal;
}
return result;
}
//字符到字节{?
public static byte[] charToByte(char ch){
int temp=(int)ch;
byte[] b=new byte[2];
for (int i=b.length-1;i>-1;i--){
b = new Integer(temp&0xff).byteValue(); //最高位保存在最低位
temp = temp >> 8; //向右U??
}
return b;
}
//字节到字W{?
public static char byteToChar(byte[] b){
int s=0;
if(b[0]>0)
s+=b[0];
else
s+=256+b[0];
s*=256;
if(b[1]>0)
s+=b[1];
else
s+=256+b[1];
char ch=(char)s;
return ch;
}
//点到字节{?
public static byte[] doubleToByte(double d){
byte[] b=new byte[8];
long l=Double.doubleToLongBits(d);
for(int i=0;i<b.length;i++){
b=new Long(l).byteValue();
l=l>>8;
}
return b;
}
//字节到Q点{?
public static double byteToDouble(byte[] b){
long l;
l=b[0];
l&=0xff;
l|=((long)b[1]<<8);
l&=0xffff;
l|=((long)b[2]<<16);
l&=0xffffff;
l|=((long)b[3]<<24);
l&=0xffffffffl;
l|=((long)b[4]<<32);
l&=0xffffffffffl;
l|=((long)b[5]<<40);
l&=0xffffffffffffl;
l|=((long)b[6]<<48);
l&=0xffffffffffffffl;
l|=((long)b[7]<<56);
return Double.longBitsToDouble(l);
}