Java内部类

定义在类内部的类就称之为内部类。根据定义的不同可以分为成员内部类,局部内部类,匿名类,静态内部类。无论是哪一种内部类,我们都可以在内部类中直接存取外部类的私有成员变量。(私有成员属性&私有成员方法,因为内部类持有外部类的引用)

为什么要引入内部类

1.为了更好的封装,将内部类封装在外部类内,可以方便地访问外部类成员变量,同时,将其与其他类进行隔离,不允许同包其他类访问。
2.内部类的属性和方法即便是外部类也不能随意地访问。(可以通过在外部类实例化内部类进行访问,即使该变量是private类型)
3.有利于回调函数的编写。
3.当面向对象时,有利于我们对整体和成员的封装。

成员内部类

成员内部类的语法如下:

public class OuterClass {
    private class Inner {
        //...
    }
}

成员内部类的特性除了最开始提到的可以存取所在外部类的所有成员变量之外,成员内部类的实例必须绑定在外部类的实例上,如果我们在外部类中初始化了一个内部类对象,那么内部类对象就会绑定在外部类对象上。
举例说明:

public class OuterClass {
    InnerClass inner = new InnerClass(); //外部类中实例化内部类
    private int a = 0;

    private void take() {
        a = inner.x;  
        a = inner.y;
        //x = 1;      //错误,外部类不能直接访问内部类变量
        inner.hello();
        inner.hi();
    }

    public InnerClass getInner() {  //在外部类方法中返回内部类引用
        return new InnerClass();
    }

    class InnerClass {
        public int x = 0;   //内部类公有属性
        private int y = 0;  //内部类私有属性
        public void hello() {
            x = a;    //内部类可以直接访问外部类成员变量
        }
        private void hi() {
            take();
        }
    }
}

从上面的例子我们可以得知,内部类可以随意访问所在外部类的成员,而内部类的成员只有在内部类的范围内是可知的,不能被外部类使用,比如例子中对内部类的成员属性进行赋值将会报错,但是我们可以通过内部类对象引用成员变量。

        OuterClass outerClass = new OuterClass();
        //内部类的实例化只能在外部类或外部类的非静态方法中实现
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        OuterClass.InnerClass innerClass1 = outerClass.getInner();

另外,在上面的例子中,如果不使用getInner()方法返回内部类对象引用,可以直接使用内部类实例化内部类对象,但是由于在主方法中来实例化内部类对象,必须在new操作符之前提供一个外部类的引用。

Question

1.为什么外部类可以通过实例化内部类直接访问内部类的private成员?
首先,我们得了解访问权限(Accessibility)如何规定的?
官方定义:
If the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class that encloses the declaration of the member or constructor.
从此我们可以了解到,如果一个类的成员被声明为private类型的,那么在它的顶级类(top level class)的范围内是可以访问的。那么它又是怎么实现的呢?
2.为什么只有内部类可以被声明为private或protected访问类型?
对于顶级类而言,只能声明为public访问权限类型或者缺省类型,public类型表示对所有类可见,缺省类型则为包级访问权限,对同一个package下的类可见。如果一个顶级类被声明为private类型,那么它对于其他类都是不可见的,这样类就毫无意义。说到这,顺便复习下类成员的访问权限,如果一个类的成员被修饰为private,则该成员只能在该类内部使用,在子类中是不可见的,并且对其他包的类也是不可见的。如果一个类的成员被修饰为public,那么除了可以在本类使用使用之外,还可以在子类和其他包的类中使用。如果一个类使用protected修饰符,那么只有本包内的子类或其他类可以访问此类中的成员。

Attention:类的权限设定会约束类成员的权限设定。

局部内部类

内部类不仅可以在类中定义,还可以在类的局部位置定义,如在类的方法或任意的作用域均可以定义内部类。
举例说明:

public class OuterClass {
    public void take() {
        class InnerClass {
            //do something
        }
    }
}

Attention:局部内部类InnerClass是方法take()的一部分,不是外部类OuterClass的一部分,所以在take()的外部不能访问该内部类,而InnerClass可以访问当前代码块的成员以及外部类的所有成员。

匿名内部类

举例说明:

public class OuterClass {
    public MyInterface handle() {
        return new MyInterface() {
            @Override
            public void take() {
                //do something
            }
        };
    }
}

在handle()方法中,我们通过return后面插入一个定义内部类的代码,返回一个MyInterface接口的引用,由于这个类没有名称,所以将之称为匿名内部类。

静态内部类

在内部类前面添加static修饰符,这个内部类就变成了静态内部类,一个静态内部类中可以声明静态成员,在非静态内部类中不可以声明静态成员。静态内部类有一个最大的特点就是不可以使用外部类的非静态成员。当然,如果创建静态内部类的对象,不需要其外部类的对象。

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

推荐阅读更多精彩内容

  • Java 内部类 分四种:成员内部类、局部内部类、静态内部类和匿名内部类。 1、成员内部类: 即作为外部类的一个成...
    ikaroskun阅读 1,240评论 0 13
  • 转载:https://juejin.im/post/5a903ef96fb9a063435ef0c8 本文将会从以...
    福later阅读 406评论 0 3
  • 搞懂 JAVA 内部类 前些天写了一篇关于 2018 年奋斗计划的文章,其实做 Android 开发也有一段时间了...
    醒着的码者阅读 626评论 0 0
  • 明天我们要有一个全年级的背诗比赛,是我们整个一年级的比赛。我很想参加这次比赛,所以我利用周末的时间把书上所有的...
    M张皓轩M阅读 129评论 0 0
  • 一提到草原肯定就会想到骏马,接下来就是牛羊,新疆,手撕羊排,马奶酒等等,根本停不下来啊。一股牛奶的味道渐渐的飘来,...
    九号咖啡屋阅读 248评论 0 0