• Java内部类详解


    一、java内部类分类

    1、成员内部类

    成员内部类是最普通的内部类,定义位于另一个类内部。

    public class Outter {
        private int i =0;
         class Inner{
            public void print(){
                System.out.println(i);
            }
        }
        public void out(){
           new Inner().print();
        }
    public Inner getInner(){
    return new Inner();
    }
    }

    成员内部类可以无条件访问外部类的所有成员和方法(包括private成员和方法)。当内部类和外部类有同名变量或方法时,默认情况下是访问内部类的成员。若是要访问外部类的同名变量则要 类名.this.方法/变量。

    而外部类若要访问内部类的成员,则需要创建内部类对象。

    public class test {
        public static void main(String[] args) {
    //第一种创建方式 Outter outter
    =new Outter(); Outter.Inner inner= outter.new Inner(); inner.print();
    //第二种创建方式
            Outter.Inner inner1=new Outter().getInner();
    }
    }

    成员内部类是衣服外部类而存在的,若是要创建成员内部类的对象,前提是先要存在一个外部类的对象,再通过外部类对象创建内部类对象。

    同时:普通外部类类只有public 和 默认的包访问权限,而成员内部类可以有 private public protected default 四种权限,对比类的成员的访问权限。

    2、局部内部类

    局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于,它的访问权限仅限于这个方法或作用域的内部。

          public Outter getOutter(){
              class Inner extends Outter{
                  int a=0;
              }
              return new Inner();
          }

    局部内部李和方法里面的局部变量一样,是不能有private 、protected、static、public 修饰词的.

    3、匿名内部类

    匿名内部类大概是平时用到最多的内部类了。

    scan_bt.setOnClickListener(new OnClickListener() {
                 
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                     
                }
            });

    类似这种事件监听,或是启动线程等 使用匿名内部类是很方便的。减少了大量的冗余代码。

    匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

    4、静态内部类

    静态内部类也是定义在另一个类的里面,可以比照成员内部类,比成员内部类多了一个static 的修饰,与静态成员变量类似,它也不需要依赖于外部类,并且它不能使用外部类的非static变量或者方法。因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

    静态内部类的外部引用方式:

     Outter.Inner inner=new Outter.Inner();
            inner.print();

    二、深入理解内部类

    1、为什么成员内部类可以无条件访问外部类的成员?

    编译器编译时会将成员类和外部类编译为两个class文件。而成员内部类中默认添加了对外部类成员的应用,而虽然我们并没有定义构造器,但是编译器会默认的为构造器中添加对引用的外部成员进行赋值。这也解释了,为什么成员内部类为什么不能单独存在,如果没有创建外部类对象的话,内部类的赋值就没有数据来源。同时也说明了为什么外部类不能直接访问内部类成员,因为外部类的class文件中并没有引用内部类的成员,而且使用外部类时,也并不必须创建内部类的对象,所以如此。

    2、匿名内部类和局部内部类为什么只能访问局部final变量,而在jdk8以后又可以访问普通局部变量了

    匿名内部类或局部内部类定义在方法体中,通过调用方法来调用内部类时,当局部方法生命周期结束,而内部类的生命周期此时不一定结束,而局部变量不能脱离方法而单独存在,所以编译器会在内部类中创建一个局部变量的拷贝,所以内部类中访问的实际上是这个拷贝,而非原本的局部变量本身,但是,若在内部类中对这个变量进行重新赋值,就会导致内部类中的变量与原本的局部变量值不相符,造成数据不一致性,这样就没有达到原本的意图了,所以编译器就限定内部类访问的局部变量只能是final变量,这样就解决了这个数据的不一致问题。

    然而我今天试了一下,是可以普通变量的。这是为什么呢。

    当我在内部类中首次访问变量c时,是可以访问的,而当我在内部类的调用后再加上对c的重新赋值后,内部类便不能访问这个c了。所以实际上是编译器默认内部类访问的局部变量是final类型的,而当这个局部变量会改变时,便不能访问了。又试了一下在内部类中对c重新赋值,也是无法通过编译的。那么我们可以认为,实际上jdk8与之前并无分别,只是对内部类所访问的局部变量默认的加上了final 的修饰而已。

    三、内部类的使用场景和好处

    1、每个内部类都可以独立的继承一个借口的实现,所以无论内部类是否已经继承了某个借口的实现,对于内部类都没有影响。内部类使得多继承的方案变的完整。

    2、方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。

    3、方便编写事件驱动程序。

    4、方便编写线程代码。

    参考资料:https://www.cnblogs.com/dolphin0520/p/3811445.html

  • 相关阅读:
    html页面,左边点击链接,右边显示内容参考代码。
    下拉列表,鼠标移动上去改变颜色
    js生成验证码
    SAP MM模块之批次管理
    SAP 通过屏幕字段查看透明表
    SAP SD你要知道的透明表
    ]sap透明表、结构、簇介绍以及查找表方法
    设计模式(策略模式)
    设计模式(状态模式)
    设计模式(观察者模式)
  • 原文地址:https://www.cnblogs.com/yinjing/p/11003645.html
Copyright © 2020-2023  润新知