前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java内部类那些事

Java内部类那些事

作者头像
stringwu
发布2022-08-12 12:00:29
2190
发布2022-08-12 12:00:29
举报

Java中的内部类又分为非静态内部类(匿名内部类也是非静态的内部类)和静态内部类,两者与外部类的关系是不一样的,创建的方式也不一样。

1 非静态内部类

Java的非静态内部类在构造的时候,会将外部类的引用传递进来,并且作为内部类的一个属性,因此,内部类会隐式地持有其外部类的引用。也就是非静态内部类在构造的时候需要有一个外部类的实例传递进来进行构造,不能像普通的Java类那样直接就可以通过 new来生成;一个简单的例子如下:

代码语言:javascript
复制
 1 import java.util.ArrayList;
 2 import java.util.LinkedList;
 3 import java.util.List;
 4 import java.util.Queue;
 5 import java.util.Scanner;
 6 
 7 public class Main {
 8 
 9     /**
10      * @param args
11      */
12     public  int k=3;
13     private static String string="Java";
14     protected float j=1.5f;
15     public static void show(){
16         System.out.println("show");
17     }
18     private void add(){
19         System.out.println("add");
20     }
21     public static void main(String[] args) {
22         // TODO Auto-generated method stub
23         Main m=new Main();
24         //合法的非静态内部类的构造方式
25         Child c=m.new Child();
26         //Child c=new Child() 这是不合法的构造方式
27         c.test();
28  
29     }
30 //内部类Child
31   class Child{
32      public int i;
33      public void test(){
34          System.out.println("k=:"+k);
35          System.out.println("string:"+string);
36          add();
37          System.out.println("j=:"+j);
38          show();
39      }
40      
41  }
42 
43 }

并且非静态的内部类可以访问外部类的所有成员变量与方法,包括静态的成员变量与方法,执行内部类Child的test()方法就可以得到下面的结果:

代码语言:javascript
复制
1 k=:3
2 string:Java
3 add
4 j=:1.5
5 show

2 静态内部类

Java中的静态内部类在构造的时候并不需要外部类的引用,因此静态的内部类不会持有外部类的引用,并且静态内部类只能访问外部类的静态成员变量和方法。一个简单的例子为(上面的代码做一些简单的改动):

代码语言:javascript
复制
 1 public class Main {
 2 
 3     /**
 4      * @param args
 5      */
 6     public  int k=3;
 7     private static String string="Java";
 8     protected float j=1.5f;
 9     public static void show(){
10         System.out.println("show");
11     }
12     private void add(){
13         System.out.println("add");
14     }
15     public static void main(String[] args) {
16         // TODO Auto-generated method stub
17         Main m=new Main();
18         //Child c=m.new Childe();//非法
19         Child c=new Child();
20         c.test();
21  
22     }
23   static class Child{
24      public int i;
25     
26      public void test(){
27 //         System.out.println("k=:"+k);//不能访问外部类非静态变量
28          System.out.println("string:"+string);
29          //add(); //不能访问外部类的非静态方法
30 //         System.out.println("j=:"+j);
31          show();
32      }
33      
34  }
35 
36 }

从上面的代码可以看到,静态内部类的创建方式与普通的Java类的创建方式一样,执行第21行代码就可以得到如下结果:

代码语言:javascript
复制
1 string:Java
2 show

3 杂谈

Java的非静态内部类的这种创建方式,会隐式地持有外部类的引用,而且默认情况下这个引用是强引用,因此,如果内部类的生命周期长于外部类的生命周期,程序很容易就产生内存泄漏(你认为垃圾回收器会回收掉外部类的实例,但由于内部类持有外部类的引用,导致垃圾回收器不能正常工作)。为了避免这种情况的发生,你可以在内部类的内部显示持有一个外部类的软引用(或弱引用),并通过构造方法的方式传递进来,在内部类的使用过程中,先判断一下外部类是否被回收;

关于内存泄漏的这一点,有参考技术小黑屋的两篇文章:Android中Handler引起的内存泄露和避免Android中Context引起的内存泄露

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 stringwu的互联网杂谈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 非静态内部类
  • 2 静态内部类
  • 3 杂谈
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档