栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

内部类使用场景,语法和原理解释

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

内部类使用场景,语法和原理解释

内部类 1 . 内部类的作用

封装-------访问权限控制:普通类访问控制符最高只能控制到同包下的,但内部类可以私有只允许外部类访问。多继承--------解决方法之一 : 之二是桥接模式匿名内部类使代码简洁 : lambda表达式, 监听器模式,等 2 . 内部类的分类

    成员内部类静态内部类局部内部类匿名内部类 ( 特殊的局部内部类 )
3 . 内部类的语法
    成员内部类

成员内部类不允许有静态属性和方法;成员内部类底层持有外部类对象的引用 , 所以内部类的初始化必须显示初始化外部类 (new OuterClass().new InnerClass()) ;成员内部类可以访问外部类的任何成员属性包括私有属性. (静态属性无法访问,无需多说);内部类和外部类变量重名,需要OuterClass.this.name指代外部类,this.name指代内部类;
ps: 至于为什么能访问外部类的私有属性,是因为编译器动了手脚.javac编译器为外部类生成了access通道方法.相当于get set方法以达到访问私有属性的目的.

  public class OuterClass {
      private static int source = 100;
    private String name = "OuterClass";
      private long birthday = 1844548484148L;   
      //成员内部类

      public static void main(String[] args){
        //初始化局部内部类必须显示初始化外部类,只有这样内部类访问外部类属性才不会有问题.  
        InnerClass innerClass = new OuterClass().new InnerClass();
        innerClass.fun();  
      }
      public class InnerClass{
          private String name = "InnerClass";
          private long birthday = 000000L;
          //成员内部类不能有静态属性和方法
          public void fun(){
              System.out.println("外部类name"+ OuterClass.this.name);
              System.out.println("内部类name"+ this.name);
          }
      }   
  }
    静态内部类

静态内部类可以拥有 静态/非静态 属性/方法; 是一个完整的类;静态内部类不持有外部类实例的引用, 实例化不需要先实例化外部类; 至于访问外部类静态属性时外部类的加载是jvm完成的;静态内部类只允许访问外部类的任何静态域(包括私有属性),不允许访问非静态域,因为没有持有引用访问不到;
ps: 综上所述 静态内部类是一个完整的类,只是借用了外部类的壳,其他的和普通类没有什么不同.

    public class OuterClass {
        private static int source = 100;
        private String name = "OuterClass";
        private long birthday = 1844548484148L;   
        //静态内部类
        public static class StaticInnerClass{
            private String name;
            private long birthday;
            private static int source = 20;
            // 静态内部类只能访问外部类的静态域. 
            public void fun(){
                System.out.println("外部类静态属性"+ OuterClass.source);
                System.out.println("内部类静态属性"+ source);
            }
        }
    }
    局部内部类

定义在方法中的内部类,作用域只在方法中;局部内部类可以和成员内部类一样只访问外部类的非静态域. 但是可以访问到局部变量;局部内部类如果要访问局部变量,则局部变量必须由final修饰; 因为局部变量分配在栈上,而内部类对象分配在堆,内部类对象的生命周期会比局部变量长 ; 当方法结束后栈帧弹出, 局部变量就会被销毁. 此时如果内部类对象再访问该局部变量就会出问题 ; JVM的实现方式是 在内部类对象内 保存局部变量的副本 ; 但是额外的,却带来了维护局部变量与其副本数据一致性的性能开销.于是干脆不允许在局部内部类中改变局部变量的值.便有了 局部内部类中访问的局部变量必须声明成final这一规定. 下面是一个例子

    public class OuterClass {
        private static int source = 100;
        private String name = "OuterClass";
        private long birthday = 1844548484148L; 
        public void fun(){
            final int  a = 0;
            //局部内部类
            class Runnable implements java.lang.Runnable {
                @Override
                public void run() {
                    birthday ++; //局部内部类也可以访问外部类的成员域
                    int b = a;
                    b ++;
                }
            }
            new Thread (new Runnable()).start(); 
        }
}
    匿名内部类

没有名字的局部内部类,可以直接new一个抽象类或接口,只需在new的时候实现其抽象方法;匿名内部类 访问的局部变量也必须用final修饰(因为其本质是局部内部类)lambda表达式是匿名内部类的语法糖,所以访问的局部变量也必须用final修饰

    public class OuterClass {
        private static int source = 100;
        private String name = "OuterClass";
        private long birthday = 1844548484148L; 
        public void fun(){
            final int  a = 0;
            new Thread (()-> {
                        birthday ++; //局部内部类也可以访问外部类的成员域
                        int b = a;
                        b ++;
            }).start(); 
        }
}

最后说明一点, 内部类是一个编译器现象,JVM虚拟机并不知道内部类与常规类有什么不同.至于这一点不理解的朋友们可以
参考博客

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/735172.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号