您的位置:首页 > 编程语言 > Java开发

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

2016-04-13 15:08 513 查看
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{
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(1000*60*60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.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() {
@Override
public 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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: