在Java的学习中,我们经常发现一个问题:
很多时候这个关键字/方法长的很相似,也能够说出之间的差异,但总是感觉很模糊,
说知道吧,又说不全面,说不知道吧,你又不服气。哈哈,学习过程遇到这个很正常;
所以这篇文章也是为了梳理一下相关的疑难杂症吧,一起学习。
1、final
final关键字主要用于三个地方:变量、方法、类
2、finally
finally是一种异常处理机制。
一般情况下,finally是都需要执行的(这里指的一般是排除了如:强制终端程序System.exit(1)等非正常的操作,这样是没有意义的)。排除这些因素之后,即使程序抛出异常,也会先执行fianlly语句块中的代码,再抛出异常。**finally可能更擅长对于维护对象的内部状态比较有意义,如关闭数据库连接这方面,**可以大大降低程序出错的几率。
如下面的程序:
try {
int i = 0;
i = i+1;
return i;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
i = 2;
return i;
}
程序返回结果:2
哪怕程序执行完try里面的语句没有异常,最终执行了finally里的语句,重新对 i 的值进行改变,并返回,这个值会被改变;注意:如果在finally里没有return语句时,对 i 的值进行改变,不会改变前面的return的值。
3、finalize
我在想:看到这个应该很熟悉,因为这个是在多线程中经常用到,下面我们就一起学习一下它的用法。
wait与notify、notifyAll是Java同步机制中重要的组成部分。结合与synchronized关键字使用,可以建立很多优秀的同步模型。
1、wait
wait()作用是使当前执行代码的线程进行等待,wait()方法是Object类的方法,该方法用来将当前线程置入“预执行队列”中,并且在wait所在的代码处停止执行,直到接到通知或被中断为止。
2、notify
package FinalTest;
/*
* 测试wait 与 notify之间的用法
*
* */
class ThreadA extends Thread {
public Object obj;
public ThreadA(Object obj) {
this.obj = obj;
}
@Override
public void run() {
synchronized (obj) {
System.out.println("ThreadA start!");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadA end!");
}
}
}
class ThreadB extends Thread {
public Object obj;
public ThreadB(Object obj) {
this.obj = obj;
}
@Override
public void run() {
synchronized (obj) {
System.out.println("ThreadB start!");
obj.notify();
System.out.println("ThreadB end!");
}
}
}
public class FinalTest2 {
public static void main(String[] args) {
Object obj = new Object();
ThreadA ta = new ThreadA(obj);
ta.start();
ThreadB tb = new ThreadB(obj);
tb.start();
}
}
运行结果:
ThreadA start!
ThreadB start!
ThreadB end!
ThreadA end!
在这段代码中,我们可以发现:当ThreadA执行wait之后,线程被阻塞,同时释放锁,ThreadB获取锁,并执行notify,此时还没有释放锁,所以ThreadA还不能继续执行,只有等ThreadB执行完毕之后,才能继续回到wait的代码块执行后面的代码。
3、notifyAll
notifyAll其实和notify之间的区别不是很大,只是调用notifyAll每次唤醒的是所有等待中的线程,不过一定要注意:唤醒不代表就能够立马执行,能不能执行,还需要共同争取同步锁的权限,谁拿到了锁,谁就可以执行;
Java中equals与“==”之间的区别可以简单分为几类:
当对象是字符串类型时,“==”比较的是两个字符串对象的内存地址;equals比较的是两个对象的内容。如:
String s1 = "123";
String s2 = "abc";
String s3 = new String("123");
String s4 = new String("123");
String s5 = "abc";
System.out.println(s1.equals(s3));//true
System.out.println(s1 == s3);//false
System.out.println(s2.equals(s5));//true
System.out.println(s3.equals(s4));//true
System.out.println(s3 == s4);//false
System.out.println(s2 == s5);//true
只要看见使用new 关键字生成的对象,“= =” 一定是不相等的!因为是在堆里面重新生成的对象;s2、s5的 “= =”之所以为true是因为,在常量池中有一个"abc"变量,只是s2和s5同时指向了该变量的地址,其实都是表示的同一个对象,所以equals与==都是true。
int i = 1;
int j = new Integer(1);
int a = new Integer(1);
System.out.println(i == j);//true
System.out.println(a == j);//true
如果对象是包装类型,情况如下:
Integer a1 = 1;
Integer a2 = new Integer(1);
int a3 = 1;
Integer a4 = new Integer(1);
System.out.println(a1.equals(a2));//true
System.out.println(a1 == a2);//false
System.out.println(a1.equals(a3));//true
System.out.println(a1==a3);//true
System.out.println(a2==a3);//true
System.out.println(a2==a4);//false
System.out.println(a2.equals(a4));//true
凡是看见StringBuffer和StringBuilder的字符串对象,它们的== 和equals都是比较地址!很特殊的两个对象。
String str = "abc";
StringBuffer sBuffer0 = new StringBuffer("abc");
StringBuffer sBuffer1 = new StringBuffer("abc");
StringBuilder sBuilder = new StringBuilder("abc");
System.out.println(sBuffer0.equals(sBuilder));//false
System.out.println(sBuffer0.equals(str));//false
System.out.println(sBuilder.equals(str));//false
System.out.println(sBuffer0==sBuffer1);//false
System.out.println(sBuffer0.equals(sBuffer1));//false
总结:在比较 == 和 equals之时,应该注意: