2.内部类

一.内部类

  1. 类中定义的成员:
    字段,方法,内部类
  2. 内部类:定义在类结构中的另一个类:
    1. 增强封装,把内部类隐藏在外部类之内,不许其他类访问内部类
    2. 内部类能提高代码的可读性和可维护性,把小型类嵌入到外部类中结构上代码更靠近
    3. 内部类可以直接访问外部类的成员。
  3. 内部类根据使用不同的修饰符分类
    1. 实例内部类:内部类没有使用static修饰
    2. 静态内部类:内部类使用了static修饰
    3. 局部内部类:在方法中定义的内部类
    4. 匿名内部类适合于仅使用一次的类:属于局部内部类的特殊情况
  4. 对于内部类来说:Java编译器会生成独立的.class文件
  5. 成员内部类:外部类$内部类名字
  6. 局部内部类:外部类$数字内部类名称
  7. 匿名内部类:外部类名$数字

image

image

image

二.实例内部类

  1. 没有使用static修饰内部类,说明内部类属于外部类的对象,不属于外部类本身。
    特点:
    1. 创建实例内部类前,必须存在外部类对象,通过外部类对象创建内部类对象(当存在内部类对象
      时,一定存在外部类)
    2. 实例内部类的实例自动持有外部类的实例的引用,内部类可以直接访问外部类成员
    3. 外部类中不能直接访问内部类的成员,必须通过内部类实例去访问。
    4. 实例内部类中不能定义静态成员,只能定义实例成员。
    5. 如果实例内部类和外部类存在同名的字段或方法abc,那么在内部类中:
  2. this.abc表示访问内部类成员。
    外部类.this.abc表示访问外部类成员。

新建InstenceInnerClassDemo.java

//外部类
class Outter
{
    String name = "Outter.name";
    public void ooxx(){
        System.out.println("Outter.ooxx");
        System.out.println( new Inner().name);
    }
    //内部类
    class Inner
    {
        String name = "Inner.name";
        int age = 16;
        public void ooxx(){
            String name = "Local.name";
            System.out.println("--------");
            System.out.println( name);
            System.out.println( this.name);
            System.out.println( Outter.this.name);
            System.out.println("--------");
            System.out.println("Inner.ooxx");
        }
    }
}
class InstenceInnerClassDemo
{
    public static void main(String[] args)
    {
        Outter o = new Outter();
        o.ooxx();
        System.out.println(o.name);
        Outter.Inner i = o.new Inner();
        i.ooxx();
        System.out.println(i.name);
        new Outter().new Inner();
    }
}

三.静态内部类

  1. 使用static修饰
    特点:
    1. 静态内部类的实例不会自动持有外部类的特定实例的引用,在创建内部类的实例时,
      不必创建外部类的实例
    2. 静态内部类可以直接访问外部类的静态成员,可以通过外部类的实例访问外部类非静态成员。
    3. 在静态内部类中可以定义静态成员和实例成员
    4. 测试类可以通过完整的类名直接访问静态内部类的静态成员

新建StaticInnerClassDemo.java

//外部类
class Outter
{
    String name = "Outter.name";
    static String name2 = "Outter.name2";
    //静态内部类
    static class Inner
    {
        static int age = 17;
        public void test(){
            System.out.println(name2);
        }
    }
}
class StaticInnerClassDemo
{
    public static void main(String[] args)
    {
        Outter.Inner i = new Outter.Inner();
        i.test();
        System.out.println(Outter.Inner.age);
    }
}

四.局部内部类

  1. 在方法中定义的内部类,其可见范围是当前方法和局部变量是同一个级别。
    1. 不能使用public,private,protected,static修饰符
    2. 局部内部类只能在当前方法中使用
    3. 局部内部类和实例内部类一样,不能包含静态成员
    4. 局部内部类和实例内部类一样,可以访问外部类所有成员
    5. 局部内部类访问的局部变量必须使用final修饰(Java8中会隐式加上final,不能改变值)
  2. 原因:如果当前方法不是main方法,那么当前方法调用完毕后,当前方法的栈帧被销毁,方法内
    部的局部变量的空间全部销毁,然后局部内部类是定义在方法中,而且在方法中会创建局部内部
    类对象,而局部内部类会访问局部变量,当当前方法被销毁的时候,对象还在堆内存,依然持有
    对局部变量的引用,但是方法被销毁的时候局部变量已经被销毁了。
  3. 此时出现:在堆内存中,一个对象引用着一个不存在的数据,为了避免该问题,我们使用final修
    饰局部变量,从而变成常量,永驻内存空间,即使方法销毁之后,该局部变量也在内存中,对象
    可以继续持有。

新建LocalInnerClassDemo.java

class LocalInnerClassDemo
{
    static int ooxx = 5;
    public static void main(String[] args)
    {
        final int age = 12;
        System.out.println("Hello World!");
        class Local
        {
            void doWork(){
            System.out.println(age);
            }
        }
        new Local().doWork();
    }
}

五.匿名内部类(Anonymous)

  1. 没有名称的局部内部类,只使用一次的类。
    1. 匿名内部类本身没有构造器,但是会调用父类构造器
    2. 匿名内部类尽管没有构造器,但是可以在匿名内部类中提供一段实例初始化代码快
      JVM在调用父类构造器后,会执行该段代码
    3. 内部类处理可以继承类之外,还可以实现接口
  2. 格式:
new 父类构造器(实参列表)或接口(){
//匿名内部类的类体部分
}

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

发布了58 篇原创文章 · 获赞 0 · 访问量 729

猜你喜欢

转载自blog.csdn.net/huang_kuh/article/details/104882401
今日推荐