final finally finalizefinal可以修饰类、变量、方法,修饰类表示类不可以被继承,修饰变量表示变量不可以被重新赋值,是一个常量,修饰方法表示这个方法是最终的,不能被重写。
finally代码块一般配合try-catch使用,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块 中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
finalize是一个方法,属于Object的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器调用,当我们手动启动GC(调用System.gc())时,由垃圾回收器调用finalize方法。
对象的四种引用
1.强引用(FinalReference)
强引用是Java中最为常见的一种引用方式,只要引用存在,就不会被垃圾回收器回收。Object obj = new Object();
User user = new User();
可直接通过obj取得对应的对象 如 obj.equels(new Object()); 而这样 obj 对象对后面 new Object 的一个强 引用,只有当 obj 这个引用被释放之后,对象才会被释放掉,这也是我们经常所用到的编码形式。
如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样的话,JVM在合适的时间就会回收该对象。
2.弱引用(WeakReference)//示例1
WeakReference weakBean = new WeakReference(new String[]{"a", "b", "c"});
//示例2
ReferenceQueue referenceQueue = new ReferenceQueue();
WeakReference softBean = new WeakReference(new String[]{"a", "b", "c"}, referenceQueue);
弱引用就是只要JVM垃圾回收器发现了它,就会将之回收,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
可用场景:Java源码中的java.util.WeakHashMap中的key就是使用弱引用,我的理解就是, 一旦我不需要某个引用,JVM会自动帮我处理它,这样我就不需要做其它操作。
3.软引用(SoftReference)Object obj = new Object();
SoftReference sf = new SoftReference(obj);
obj = null;
sf.get();//有时候会返回null
这时候sf是对obj的一个软引用,通过sf.get()方法可以取到这个对象,当然,当这个对象被标记为需要回收的对象 时,则返回null; 软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的 真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
软引用只有在程序内存不足时,才会被回收,软引用可用来实现内存敏感的高速缓存,软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
可用场景:创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM就会回收早先创建的对象。
虚引用(PhantomReference)
垃圾回收时回收,无法通过引用取到对象值,可以通过如下代码实现Object obj = new Object();
PhantomReference pf = new PhantomReference(obj);
obj=null;
pf.get();//永远返回null
pf.isEnQueued();//返回是否从内存中已经删除
虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引 用。虚引用主要用于检测对象是否已经从内存中删除。
“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
java反射机制
Java反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。这种在运行时动态地获取信息以及动态调用对象的方法的功能称为Java的反射机制。
Class类与Java.lang.reflect类库一起对反射的概念进行了支持,该类库包含了Field,Method,Constructor类(每个类都实现了Member接口)。这些类型的对象是由JVM在运行时创建的,用以表示未知类里的对应成员。
这样就可以使用Constructor创建新的对象,用get()和set()方法读取和修改与Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。
另外,还可以调用getField() getMethod()和getConstructor()等很便利的方法,以返回表示字段、方法、以及构造器的对象的数组,这样匿名对象的信息就能在运行时被完全确定下来,而在编译时不需要知道任何事情。import java.lang.reflect.Constructor;
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class clazz = null; clazz = Class.forName("com.jas.reflect.Fruit"); Constructor constructor1 = clazz.getConstructor();
Constructor constructor2 = clazz.getConstructor(String.class);
Fruit fruit1 = constructor1.newInstance();
Fruit fruit2 = constructor2.newInstance("Apple");
}
}
class Fruit{
public Fruit(){
System.out.println("无参构造器 Run..........."); }
public Fruit(String type){
System.out.println("有参构造器 Run..........." + type); } }
运行结果:无参构造器 Run……….. 有参构造器 Run………..Apple
wait和sleep的区别
先看看它的源码public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0) {
timeout++;
}
wait(timeout);
}public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}sleep来自Thread类,sleep方法没有释放锁,sleep可以在任何地方使用,使用范围广,但是使用 sleep必须捕获异常。
wait来自Object类,且释放了锁,使得其它线程可以同步控制块或者方法。wait、notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而且wait、notify和notifyAll不需要捕获异常。
1) sleep方法属于Thread类中的方法,表示让一个线程进入睡眠状态,等待一定时间后,自动醒来进入到可运行状态,不会马上进入运行状态,因为线程调度机制恢复线程运行也需要时间,一个线程对象调用了sleep方法之后,并不会释放它所持有的所有对象锁,所以也就不会影响其他进程对象的运行。但在sleep的过程中有可能被其它对象调用它的interrupt(),产生InterruptedExcepttion异常,如果你的程序不捕获这个异常,线程就会异常终止,进入 TERMINATED 状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语 句块(可能还有 finally 语句块)以及以后的代码。
注意 sleep() 方法是一个静态方法,也就是说他只对当前对象有效,通过 t.sleep() 让t对象进入 sleep ,这样 的做法是错误的,它只会是使当前线程被 sleep 而不是 t 线程。
2) wait属于Object 的成员方法,一旦一个对象调用了wait方法,必须要采用 notify()和notifyAll()方法 唤醒该进程;如果线程拥有某个或某些对象的同步锁,那么在调用了wait()后,这个线程就会释放它持有的所有 同步资源,而不限于这个被调用了wait()方法的对象。wait()方法也同样会在wait的过程中有可能被其他对象调用interrupt()方法而产生。