内部类,匿名内部类

内部类应用场景

描述事物A时,发现需要在事物A内部,封装一个能访问A属性等数据的事物B来只服务于事物A。
即如果一个类附属于另一个类且只应用于这个类,则可以用内部类,比如Android的Adapter里的ViewHolder。

使用内部类的优势
  • 可以把内部类隐藏在外部类内,不允许同一个包中的其他类访问该类。

  • 内部类定义于外部类的成员变量位置,因此内部类可以使用任意访问控制符,如 public 、 protected 、 private 等,同时也可以访问外部类任意数据。

  • 内部类隐式的持有了一个外部类的引用,所能用外部类全部属性,要想打破引用就要用静态内部类。

  • 可以实现多重继承。

成员内部类
public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();
        inner.test();
}

class Outer {
    public int i = 1;

    class Inner {
        public int i = 2;

        public void test() {
            System.out.println("避免就近原则,调用外部类同名变量" + Outer.this.i);
        }
    }
}
静态内部类
public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();//注意调用方式
        inner.test();
}

class Outer {
    public static int i = 1;

    static class Inner {

        public void test() {
            System.out.println("静态内部类只能引用外部类的静态成员" + i);
        }
    }
}
局部内部类
class Outer {
    
    public void test() {    
    
        class Inner {   
        
            public void innerTest() {
                System.out.println("InnerTest" );
            }
        }

        Inner inner = new Inner();
        inner.innerTest();
    }
}
//调用内部类方式
Outer outer = new Outer();
outer.test();
局部内部类访问局部变量问题
class Outer {

    int num = 3;

    public void test() {
        //JDK低于1.8
        //final int x = 9;

       //JDK1.8
                int x = 9;

        class Inner {
            public void show() {
                System.out.println("Inner...." + x);
            }
        }
        
        Inner inner = new Inner();
        inner.show();
    }
}

如果你的JDK为1.8以下,想访问就要把局部变量声明成final,而1.8后的JDK不需要(JDK1.8帮你隐藏了,实际还是存在final)。

至于为什么访问就要把局部变量声明成fianl?
因为局部变量的生命周期是一旦出作用域就马上被释放,然而这时new Inner这个对象还在等待Java垃圾回收机制来回收并没有马上释放消失,相应的它内部访问局部变量也没有消失。
如此给人的感觉就是这个局部变量的生命周期延长了,这就违背Java的设计原则了。
所以Sun想了解决方案,如果一个局部内部类访问一个局部变量的时候,那就让该局部内部类访问该局部变量的复制品。
如此什么复制品?
完全一样的才是复制品。
为了保证值完全一样不能随意变换,所以这个变量要声明成final。


匿名内部类

  • 没有类名的类就称作匿名内部类,只是没有类名,类的其他成员都具备。

  • 匿名内部类的好处
    简化书写,能尽快的释放空间(作为实参传值,出作用域就释放)。

继承方式的匿名内部类
abstract class Demo {

    public abstract void read();

}

public class Run {
    public static void main(String[] args) {

        //注意这里创建的是继承Demo类的子类对象
        new Demo() {

            @Override
            public void read() {
                System.out.println("Read");
            }
        }.read();

    }
}
如果想通过匿名内部类实现调用多个方法,需要将返回值设为基类
abstract class Demo {

    public abstract Demo read();

    public abstract Demo write();

}

public class Run {
    public static void main(String[] args) {

        // 注意这里是继承Demo类的对象
        new Demo() {

            @Override
            public Demo read() {
                System.out.println("Read");
                return this;
            }

            @Override
            public Demo write() {
                System.out.println("Write");
                return this;
            }
        }.read().write();

    }
}

如果匿名内部类中定义了其特有的方法,想都不要想调用,不明白的去看我写的多态篇找原因。

实现方式的匿名内部类
//接口
interface Demo {
    void read();
}

//测试类
class Test {

    public void test() {
   //注意:这是匿名的接口实现类对象,不是接口new。
        new Demo() {

            @Override
            public void read() {
                System.out.println("read");
            }

        }.read();
    }
}

public class Run {
    public static void main(String[] args) {
        
        Test test = new Test();
        test.test();
    }
}

在实际开发中匿名内部类一般用于实参
  • 假设有一个函数的形参需要传一个接口类的实参,这个实参仅在用时调用。

  • 如果专门去写一个实现类是不是太low,那么这时候就可以用上匿名内部类。

interface Demo {
    void read();
}

public class Run {
    public static void main(String[] args) {

        test(new Demo() {

            @Override
            public void read() {
                System.out.println("Read");
            }
        });

    }

    public static void test(Demo demo) {
        demo.read();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java 内部类 分四种:成员内部类、局部内部类、静态内部类和匿名内部类。 1、成员内部类: 即作为外部类的一个成...
    ikaroskun阅读 1,260评论 0 13
  • #内部类的定义 Java中允许在类中定义另一个类,这个定义在其他类内部的类就是内部类(嵌套类),包含内部类的类也被...
    Enigmaaaaa阅读 577评论 0 0
  • Java允许在一个类里面定义另一个类,类里面的类就是内部类。内部类看似简单,其实里面大有乾坤,下面我们就来好好聊一...
    iDaniel阅读 2,020评论 1 9
  • 勇者无惧——孔子《论语·子罕》。 前两天,看了一部电影,名字叫做《地雷险区》,本来以为这是一部战争片或是动作片,...
    恣情饮者阅读 440评论 0 1