Java中 == 和 equals() 有何区别
==
- 概念:== 等于比较运算符,如果进行比较的两个操作数都是数值类型,即使他们的数据类型不相同,只要他们的值相等,也都将返回true.如果两个操作数都是引用类型,那么只有当两个引用变量的类型具有父子关系时才可以比较,而且这两个引用必须指向同一个对象,才会返回true
- 对于基本数据类型,比较值是否相等;对于引用数据类型,比较两个变量的内存地址是否相等
equals()
- 概念:equals()方法是Object类的方法,在Object类中的equals()方法体内实际上返回的就是使用==进行比较的结果
- 比较最终指向的值的内存地址,而非直接比较变量的内存地址
重写equals()方法
- 所有的类都继承至Object类,而且Object中的equals()方法没有使用final关键字修饰,如果我们需要使用equals()方法进行比较,需要关注是否重写了equals()方法,例如下方代码块
class User {
String name;
int age;
//重写其equals()
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof User) {
User u = (User) obj;
return this.age == u.age && this.name.equals(u.name);
}
return false;
}
}
Java垃圾回收机制
- 垃圾回收机制只回收JVM堆内存里的对象空间,对其他物理连接,例如数据库连接、I/O流、Socket连接无能为力
- 垃圾回收的发生具有不可预知性,程序无法精确控制垃圾回收机制执行
- 可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否立即进行垃圾回收依然是不确定的
- 垃圾回收机制回收任何对象之前,会先调用它的finalize()方法,如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活该对象
- 可以将对象的引用变量设置为null,暗示垃圾回收机制可以对该对象进行回收
- 不要主动调用某个对象的finalize()方法,应该交给垃圾回收机制调用
- 现在的JVM有多种垃圾回收实现算法,表现各异,有兴趣可深入了解
finally代码块执行情况
try-catch-finally代码块的执行顺序
- 通常情况下,finally代码块会在try代码块的return之前执行
- catch到异常时,finally代码块会在catch代码块return或结束之前执行
- 当finally代码块中对变量值进行修改而无return时,对象的值仍会返回未修改前的值
- 当finally代码块中对变量值进行修改且包含return时,try或catch的return语句不会执行,变量的值修改成功(避免在finally代码块里出现return语句)
finally代码块不执行的情况
- 不进入try代码块,finally代码块自然不会被执行
- 在进入try或catch代码块时调用System.exit()强制终止虚拟机
- 非守护线程被中止时。Java线程分为守护线程和非守护线程两类,当所有的非守护线程中止时,不论是否还有非守护线程未结束,Java虚拟机都会kill掉守护线程中止程序。例如,main方法线程是一个非守护线程,而垃圾回收机制是一个守护线程,main方法执行结束,程序就中止了,不管垃圾回收机制是否中止都会被kill。因此如果守护线程中存在finally代码块,而所有的非守护线程都结束时,守护线程被kill,finally代码块就不会被执行到,如下方代码demo
public class Test {
public static void main(String[] args) {
Thread t = new Thread(new Task());
t.setDaemon(true); //置为守护线程
t.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException("the " + Thread.currentThread().getName() + " has been interrupted", e);
}
}
}
class Task implements Runnable {
@Override
public void run() {
System.out.println("enter run()");
try {
System.out.println("enter try block");
TimeUnit.SECONDS.sleep(5); //阻塞5s
} catch (InterruptedException e) {
System.out.println("enter catch block");
throw new RuntimeException("the " + Thread.currentThread().getName() + " has been interrupted", e);
} finally {
System.out.println("enter finally block");
}
}
}
/**
* 控制台打印如下
* enter run()
* enter try block
*/
finally代码块存在的意义就是一定会被执行的代码块,因此只需知道finally代码块何时不会被执行,尽量避免该类操作