Java静态内部类以及非静态内部类
2016-04-13 15:08
513 查看
1、静态内部类
静态内部类桶静态代码块一样,只能访问外部类的静态方法和属性。
静态代码块:1460531829594
构造代码块!
构造方法
***********
构造代码块!
构造方法
***********
如果只保留System.out.println(Myclass.date);,那么我们会发现,Myclass类被加载,并且只被加载了一次,结果如下:
静态代码块:1460531929376
构造代码块!
构造方法
***********
构造代码块!
构造方法
***********
静态内部类的静态代码块!
静态内部类1460531930377
静态内部类1460531930377
如果保留Myclass myclass = new Myclass();,那么结果为:
静态代码块:1460532065889
构造代码块!
构造方法
***********
构造代码块!
构造方法
***********
静态内部类的静态代码块!
静态内部类的构造代码块!
静态内部类的构造方法!1460532066889
静态内部类的构造代码块!
静态内部类的构造方法!1460532066889
注意黄色两部分,虽然时间戳一致,但是并不是同一个对象,可能是执行速度过快?这一点我也不是很清楚,可以在此处让线程暂停1一段时间,时间戳就不一致,并且也可以打印两个对象的hashCode(),发现并不一致,说明在堆中为两个对象,所以这两个栈中的引用指向的是两个对象。
2、非静态内部类
对于非静态内部类,他会持有一个外部类的引用,也就是说,java的非静态内部类的对象依赖于外部类的对象,并且非静态内部类可以任意的访问外部类的成员,一般用于方便上下文切换。但是在某些时候,要特别注意非静态内部类的使用。比如如下代码:
如果这个类被实例化并且调用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;
}
}
静态内部类桶静态代码块一样,只能访问外部类的静态方法和属性。
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;
}
}
相关文章推荐
- Eclipse修改字体大小
- eclipse构建及运行maven web项目
- java 杀死指定进程
- java Semaphore(信号量)
- 封装PageModel分页
- Java获取当前时间,两个时间进行比较和相减操作
- java中集中代码块的使用
- java异常处理(隐式抛出、显示抛出、直接处理)
- 栈的使用和模拟
- Spring 学习笔记
- Java——Integer和int比较
- java中Collections.sort排序详解
- Java内存溢出
- Struts2常用标签总结
- java线程池
- HibernateTemplate的一些常用方法总结
- javamail 调用office365的邮箱发送邮件----报错到成功问题记录
- eclipse 安装 TestNG插件的方法
- [Java] 读写字节数据,过滤流DataOutputStream和DataInputStream
- Ubuntu安装JAVA8