内部类,匿名内部类

内部类应用场景

描述事物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();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容

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