Java静态内部类以及非静态内部类

来源:互联网 发布:php 数组转化为字符串 编辑:程序博客网 时间:2024/05/06 09:21

1、静态内部类

静态内部类桶静态代码块一样,只能访问外部类的静态方法和属性。

public class Test {private static long staticValue = System.currentTimeMillis();private String value = "普通属性";static{System.out.println("静态代码块:"+System.currentTimeMillis());}{System.out.println("构造代码块!");}static class Myclass{{System.out.println("静态内部类的构造代码块!");}static {System.out.println("静态内部类的静态代码块!");}public Myclass(){System.out.println("静态内部类的构造方法!"+System.currentTimeMillis());}public static String date ="静态内部类"+ System.currentTimeMillis();}public Test(){System.out.println("构造方法");}public void <span style="color:#ff0000;">getDate()</span>{//Myclass myclass = new Myclass();System.out.println(Myclass.date);}public static void staticmethod(){System.out.println("静态方法!");}public static void main(String[] args) throws InterruptedException{Test test1 = new Test();System.out.println("***********");Thread.sleep(1000);Test test2 = new Test();System.out.println("***********");test1.getDate();test2.getDate();}}
我们来分析以上代码,如果注释掉getDate()方法中的所有内容,那么Myclass不会被加载,打印结果为

静态代码块:1460531829594
构造代码块!
构造方法
***********
构造代码块!
构造方法
***********

如果只保留System.out.println(Myclass.date);,那么我们会发现,Myclass类被加载,并且只被加载了一次,结果如下:

静态代码块:1460531929376
构造代码块!
构造方法
***********
构造代码块!
构造方法
***********
静态内部类的静态代码块!
静态内部类1460531930377
静态内部类1460531930377

如果保留Myclass myclass = new Myclass();,那么结果为:

静态代码块:1460532065889
构造代码块!
构造方法
***********
构造代码块!
构造方法
***********
静态内部类的静态代码块!
静态内部类的构造代码块!
静态内部类的构造方法!1460532066889
静态内部类的构造代码块!
静态内部类的构造方法!1460532066889

注意黄色两部分,虽然时间戳一致,但是并不是同一个对象,可能是执行速度过快?这一点我也不是很清楚,可以在此处让线程暂停1一段时间,时间戳就不一致,并且也可以打印两个对象的hashCode(),发现并不一致,说明在堆中为两个对象,所以这两个栈中的引用指向的是两个对象。

2、非静态内部类

对于非静态内部类,他会持有一个外部类的引用,也就是说,java的非静态内部类的对象依赖于外部类的对象,并且非静态内部类可以任意的访问外部类的成员,一般用于方便上下文切换。但是在某些时候,要特别注意非静态内部类的使用。比如如下代码:

public class Test3 {private static String staticValue = "";private String value = "";private class MyThread implements Runnable{@Overridepublic void run() {// TODO Auto-generated method stubtry {Thread.sleep(1000*60*60);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public void method1(){Thread thread = new Thread(new MyThread());thread.start();}}

如果这个类被实例化并且调用method1,那么会导致thread对象长期持有Test3的引用,会导致内存无法被回收,造成内存泄露。在安卓中要特别注意,对于下面的匿名内部类同样如此

public class Test3 {private static String staticValue = "";private String value = "";public void method1(){Thread thread = new Thread(new Runnable() {@Overridepublic void run() {}});thread.start();}}
3、采用静态内部类实现线程安全的单例模式

public class Singleton {private static class LazyHolder{private static final Singleton instance = new Singleton();}private Singleton(){}public Singleton getInstance(){return LazyHolder.instance;}}


0 0
原创粉丝点击