内部类

来源:互联网 发布:c语言需要掌握 编辑:程序博客网 时间:2024/06/05 08:10

内部类

定义在其他类内部的类被称为内部类

  1. 内部类提供了更好的封装,不允许同一包的其他类访问
  2. 内部类成员可以访问外部的私有数据
  3. 匿名内部类适用于创建仅需要使用一次的类

定义与普通类的区别

  1. 内部类比外部类可以使用三个修饰符:private,protected,static
  2. 非静态内部类不可以有静态成员

非静态内部类

大部分内部类都被作局部内部类为成员内部类定义,而不是作为局部内部类。成员内部类与类的变量、方法、构造器相类似的类成员;局部内部类和匿名内部类不是类成员。

外部类的上一级程序单元是包,所以它只有2个作用域;而内部类的上一级程序单元是外部类所以他的作用域范围有4个

代码示例:

    public class Outer {        private int outProp=9;        //定义非静态内部类        class Inner{            private int inProp=5;            public void accessOuterProp(){                System.out.println("外部类的outProp:"+outProp);            }        }        public void accessInnerProp(){            //创建内部类实例,并访问其的内部类的属性            System.out.println("内部类的inProp:"+new Inner().inProp);        }        public static void main(String[] args) {            Outer d=new Outer();            d.accessInnerProp();        }    }

可以看出在外部类中使用非静态内部类,与平时使用普通类并没有太大的区别。编译之后产生了Outer.class和Outer$Inner.class两个字节码文件,从中可以知道内部类的class文件的形式为:OuterClass$InnerClass.class。

非静态内部类的方法访问某个变量时的顺序为:局部变量->内部类的成员变量->外部类的成员变量。

如果遇到外部类的成员变量、内部类的成员变量和内部类方法的局部变量名相同时,可以通过使用this、外部类类名.this来区分

非静态内部类的成员不能直接被外部类直接使用,只能通过实例化内部类来实现

根据静态成员不能访问非静态成员规则,外部类静态成员方法、静态代码块不能访问非静态内部类

    public class Outer{        class Inner{                private int inProp=5;                public void accessOuterProp(){                    System.out.println("外部类的outProp:"+outProp);                }        }        public static void main(String[] args) {            Demo1 d=new Demo1();            d.accessInnerProp();            //此处会发生编译错误,因为在外部静态方法中访问了非静态内部类            Inner i=new Inner();        }    }

非静态内部类不能有静态方法、静态成员变量、静态初始化块

静态内部类

如果使用static来修饰一个内部类,则这个内部类属于外部类本身,而不属于外部类的某个对象

静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。外部类依然不能直接访问静态内部类的成员

接口内部也可以定义内部类,默认使用public static修饰

使用内部类

  1. 在外部类内部使用内部类

    不要在外部类的静态成员中使用非静态内部类,因为静态成员不能访问非静态成员

  2. 在外部类以外使用非静态内部类

    在外部类以外使用内部类,内部类完整类名应该是OuterClass.InnerClass。如果外部类有包名,则应该增加包名前缀。内部类的构造器必须使用外部类对象来调用

        Out.In in=new Out().new In();
当一个SubClass类继承类Out外部类的Inner内部类
        public SubClass(Out out){            out.super();        }
  1. 在外部类以外使用静态内部类
        Out.Inner in=new Out.Inner();

外部类的子类不能够重写内部类,因为内部类的类名为外部类类名加上命名空间,所以子类定义的内部类与父类的内部类不是相同的,就不能称得上是重写

局部内部类

如果需要局部内部类定义变量、创建实例或派生子类,那么只能在局部内部类所在的方法内进行。

局部内部类很少使用

Java8改进的匿名内部类

  1. 只需要使用一次的
  2. 创建匿名内部类时会立即创建该类的实例,这个类的定义会立即消失
  3. 匿名类不能重复使用

语法格式:

    new 实现接口()|父类构造器(实参列表)    {        //匿名内部类的类体部分    }

匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口

匿名内部类的两条规则:

  1. 匿名内部类不能是抽象类。因为系统在创建一个匿名内部来时,会立即创建匿名内部类对象
  2. 匿名内部类不能定义构造器。由于匿名内部类没有类名,所以不能定义构造器

由于匿名内部类不能是抽象类,所以匿名内部类必须实现它的抽象父类或者接口里包含的所以抽象方法

如果通过继承父类来实现匿名内部类时,匿名内部类将拥有和父类相似的构造器。如果有需要也可以重写父类的普通方法

被匿名内部类访问的局部变量必须使用final关键字修饰(不写则默认),所以不能重写赋值

0 0
原创粉丝点击