什么是内部类?内部类的作用

1.什么是内部类?
  将一个类定义在另一个类里面或者一个方法里面,这样的类被称为内部类。

2.内部类的分类:

  • 成员内部类
  • 局部内部类
  • 匿名内部类
  • 静态内部类

  各个内部类作用:

  1. 成员内部类: 定义在类的内部的成员位置上,但是和外部类不是继承关系,它能访问外部类的一切成员,创建方法上有点特殊,需要先创建外部成员类,之后再创建内部成员类

    public class MemberInner {
        int memberData = 1;
        private int memberPrivateData = 2;
        private static int memberPrivateStaticData = 3;
        class InnerClass{
            int memberInnerData = 2;
    
            public void innerFunction(){
                System.out.println("memberData  ========"+memberData);
                System.out.println("memberPrivateData  ========"+memberPrivateData);
                System.out.println("memberPrivateStaticData  ========"+memberPrivateStaticData);
    
                System.out.println("memberInnerData  ========"+memberInnerData);
            }
    	 }
    }
    public class Main {
    
        public static void main(String[] args) {
            MemberInner.InnerClass inner= new MemberInner().new InnerClass();
            inner.innerFunction();
        }
    }
    

    打印结果为:

    	memberData  ========1
    	memberPrivateData  ========2
    	memberPrivateStaticData  ========3
    	memberInnerData  ========2
    
  2. 局部内部类: 和成员内部类不同的是,局部内部类定义在方法体内的位置,所以内部类不能被public、private、static修饰;

    /**
     * 局部内部类
     * */
    public class PartInner {
        private String outMember1 = "outMember1";
        private String outMethod(){
            return "this is outMethod";
        }
        public void functionData(){
            String innerMember1 = "innerMember1";
            final String innerMember2 = "innerMember2";
    
            class InnerClass{
                private String partInnerMember = "partInnerMember";
                public void innerFunction(){
    
                    System.out.println("partInnerMember======"+partInnerMember);
    
                    System.out.println("innerMember1======"+innerMember1);//这个没被final修饰,为什么也能过?一会儿解答
                    System.out.println("innerMember2======"+innerMember2); // 内部类访问外部方法的变量,需要有final修饰
                }
            }
    
    	  InnerClass innerClass = new InnerClass();
    	  innerClass.innerFunction();
    	  }
    }
    
    public class Main {
        public static void main(String[] args) {
    //        MemberInner.InnerClass inner= new MemberInner().new InnerClass();
    //        inner.innerFunction();
    
            PartInner partInner = new PartInner();
            partInner.functionData();
        }
    }
    

    打印结果

    partInnerMember======partInnerMember
    innerMember1======innerMember1
    innerMember2======innerMember2
    

    对了,这个测试环境是jdk1.8
    先说为什么访问内部成员必须要用final修饰? 内部类对象的生命周期会超过局部变量的生命周期,所以会出现访问的局部变量已经消亡,匿名内部类却还在活着,定义final后,修饰的局部变量会被拷贝一份,所访问的也是拷贝的内容,所以即使原来的局部变量已经被销毁,因为拷贝了一份与原来局部变量相同的值得数据,所以依然可以被调用。还有就是,正因为是被拷贝了,所以final修饰的数据是不允许做更改的。上面测试环境jdk1.8下,默认给局部变量添加了final修饰,修改是会报错的,也就是说,在jdk1.8的情况下,所访问局部变量依然是被final修饰的。代码如下:
    在这里插入图片描述
    明显可以看出,即使不被final修饰,在修改时也是被编辑器报错的。

  3. 匿名内部类: 正如其名,没有名字,且在内部呈现的特殊的类。一般适用于只需要使用一次,代码更简洁。
    匿名内部类一般的写法有两种,1.继承父类,2.实现某一个接口,后者实际使用的比较多。还是用代码说话吧。
    1.继承方式

    public class AnonymousClass {
        private final String SCHOOL = "中心学校";
        public void accessTest(){
            System.out.println("匿名内部类访问外部类的方法");
        }
        class SCHOOL{
            private String className ;
            public SCHOOL(String className){
                this.className = className;
            }
            public void printClassName(){
                System.out.println(school.className);
            }
        }
        SCHOOL school = new SCHOOL("二年级"){
            @Override
            public void printClassName() {
                accessTest();
                System.out.println(SCHOOL);
                super.printClassName();
            }
        };
    
        public void print(){
            school.printClassName();
        }
    }
    public class Main {
        public static void main(String[] args) {
    //        MemberInner.InnerClass inner= new MemberInner().new InnerClass();
    //        inner.innerFunction();
    
    //        PartInner partInner = new PartInner();
    //        partInner.functionData();
    
            AnonymousClass anonymousClass = new AnonymousClass();
            anonymousClass.print();
        }
    }
    

    输出结果:

    匿名内部类访问外部类的方法
    中心学校
    二年级
    

    2.实现接口方式(常用)

    public class AnonymousInter {
        interface AnnoymousInterface{
            void printData();
        }
        public void method(){
            //匿名内部类实现接口
            AnnoymousInterface annoymousInterface = new AnnoymousInterface() {
                @Override
                public void printData() {
                    System.out.println("匿名内部类实现接口");
                }
            };
    
            annoymousInterface.printData();
        }
    }
    ----------------------------------------------------
    public class Main {
    
        public static void main(String[] args) {
    //        MemberInner.InnerClass inner= new MemberInner().new InnerClass();
    //        inner.innerFunction();
    
    //        PartInner partInner = new PartInner();
    //        partInner.functionData();
    
    //        AnonymousClass anonymousClass = new AnonymousClass();
    //        anonymousClass.print();
    
            AnonymousInter anonymousInter = new AnonymousInter();
            anonymousInter.method();
        }
    }
    

    输出结果:

    匿名内部类实现接口
    

    匿名内部类可以访问外部的所有成员,但不能访问未加final(jdk1.8的除外,上面已经说过),另外,匿名内部类中不能定义静态的属性和方法

  4. 静态内部类: 和成员内部类不同的是,静态内部类最大的特点就是内部类用static修饰, 这也就限定了它的访问权限,只能访问外部被static修饰的属性和成员,也是和生命周期有关,static修饰的是早于它所属的非静态修饰的对象的。

    public class StaticInner {
        private int memberData = 1;
    	    private static int staticMemberData = 2;
    	    public static class StaticInnerClass{
    	        private int memberData = 3;
    	        private static int staticMemberData = 4;
    	        public void printData(){
    	            System.out.println("memberData========"+memberData);
    	            System.out.println("staticMemberData========"+staticMemberData);
    	            System.out.println("StaticInner.staticMemberData========"+StaticInner.staticMemberData);
    	
    	        }
    	  }
    }
    --------------------------
    	public class Main {
    
        public static void main(String[] args) {
    //        MemberInner.InnerClass inner= new MemberInner().new InnerClass();
    //        inner.innerFunction();
    
    //        PartInner partInner = new PartInner();
    //        partInner.functionData();
    
    //        AnonymousClass anonymousClass = new AnonymousClass();
    //        anonymousClass.print();
    
    //        AnonymousInter anonymousInter = new AnonymousInter();
    //        anonymousInter.method();
            StaticInner.StaticInnerClass staticInnerClass = new StaticInner.StaticInnerClass();
            staticInnerClass.printData();
        }
    }
    

    输出结果:

    memberData========3
    staticMemberData========4
    StaticInner.staticMemberData========2
    
    

可以看到很明显的区别在于,静态内部类的生成方式是

StaticInner.StaticInnerClass staticInnerClass = new StaticInner.StaticInnerClass();
staticInnerClass.printData();`

这不同于其他的,先new 出对象后,在进行内部类对象的创建,这也就是说 静态内部类属于外部类,而不是属于外部类的对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值