上篇文章--笔记19简要介绍了成员内部类、局部内部类和匿名内部类,下面对成员内部类再补充一些内容。

主要有以下6点:

1.成员内部类不可以有静态成员,成员变量为static final时除外

2.外部类不可以直接访问成员内部类的成员变量或调用成员内部类的成员方法

3.成员内部类可以无限制的访问外部类的成员变量、调用外部类的成员方法

4.成员内部类的成员与外部类成员同名时,内部类成员会屏蔽外部类的同名成员

5.成员内部类本身可以由访问权限修饰符修饰

6.成员内部类的成员变量和成员方法也可以由访问权限修饰符修饰

(注:时间有点晚了,5、6条下篇再写吧)

作者: 蝉蝉

请尊重作者劳动成果,转载请在标题注明“转载”字样,并标明原文链接:

http://www.cnblogs.com/chanchan/p/8254124.html

下面分别展开说明:

1.成员内部类不可以有静态成员,成员变量为static final除外

示例:

     //笔记19:内部类--成员内部类--不能有静态成员,成员变量为static final时除外
class InnerClass {
String name = "li";
String inname;
static String ingender = "female"; //不能有静态成员,除非声明为static final
void testStFi() {
System.out.println("ingender:" + ingender);
} //不能有静态成员方法
static void testStFiMeth() {
System.out.println("成员内部类的静态成员方法");
}
} public static void main(String[] args) { Person per = new Person();
Person.InnerClass inC = per.new InnerClass(); //笔记19:内部类--成员内部类--4不能有静态成员,除非声明为static final
inC.testStFi();
}

编译时会报出下面的错误:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
The field ingender cannot be declared static in a non-static inner type, unless initialized with a constant expression
The method testStFiMeth cannot be declared static; static methods can only be declared in a static or top level type

分析:

(1).根据错误提示,成员内部类不能有静态成员变量,除非该成员由常量表达式初始化;

大家知道,由static final修饰的成员变量其值不可改变,是编译时常量,所以把

        static String ingender = "female";

改为:

        static final String ingender = "female";

再编译就可以通过了。

(2).成员内部类为什么不可以有静态成员变量呢?

1).对于外部类来说,当类尚未加载时,访问静态成员变量或创建一个对象都可以引起类的加载,而类加载时就会为静态成员变量分配空间。

访问外部类静态成员变量时,如果类尚未加载,则会先加载类,并为静态成员变量分配空间,然后就可以访问了;如果类已经加载过了,说明静态成员变量已经分配过内存了,直接访问就可以了。所以,外部类不论什么情况下都可以正确的访问其静态成员变量。(参考笔记11

2).而对于成员内部类来说,外部类加载时,并不会被自动加载;只有外部类的一个对象在首次创建成员内部类的对象时,才会引起成员内部类的加载。假设成员内部类有静态成员变量,如果在成员内部类加载之前就需要访问其静态成员变量呢?很显然,在类加载之前,其静态成员变量是未分配内存的,这时候要访问的是一个并不存在的变量,就会出错。所以,成员内部类是不能有静态成员变量及静态成员方法的(道理类似)。

参考图片更直观:

(3).延伸:外部类与成员内部类的加载方式 和 父类与子类之间的加载方式是不一样的

1).成员内部类与外部类是附属与被附属的关系,必须通过外部类对象来创建成员内部类的对象,所以可以先加载外部类,等需要的时候再加载成员内部类。且一个外部类对象可以创建多个内部类对象,是一对多的关系。最近每天睡觉前小姑娘都要听“泥娃娃”,“泥娃娃,泥娃娃,一个泥娃娃,也有那眉毛,也有那眼睛,眼睛不会眨...”。泥娃娃像人一样,但又比人少了点什么,就把人看成外部类,泥娃娃就是人的成员内部类,哈哈,人创造了泥娃娃,而且可以创造多种多样的泥娃娃。

2).而子类与父类是is-a的关系,两个类相互独立,但可以看成子类对象里隐含了一个父类对象。首次使用子类时,要先加载父类并为其静态成员变量分配内存,再加载子类并为其静态成员变量分配内存,然后依次初始化成员变量,调用构造方法等等(可参考笔记11)。所以这里父类、子类都要加载。

几者的关系见下图:

2.外部类不可以直接访问成员内部类的成员变量或调用成员内部类的成员方法

示例:

类Person中定义了一个成员内部类InnerClass,Person的成员方法outerCAccessinC访问InnerClass的成员变量inname。

     //成员内部类
class InnerClass {
String name = "li";
String inname;    void printInC() {
System.out.println("inner class");
}
} //笔记19:内部类--成员内部类--外部类能访问内部类成员变量、调用成员方法吗?
public void outerCAccessinC() {
System.out.println("inname:" + inname);
} public static void main(String[] args) { Person per = new Person(); //笔记19:内部类--成员内部类--外部类不能访问内部类成员变量或调用成员方法
per.outerCAccessinC();
per.printInC();
}

结果出现下述错误:

第13行提示如下的错误:

  inname cannot be resolved to a variable

22行提示如下的错误:

  The method printInC() is undefined for the type Person

这说明外部类是无法直接访问成员内部类的成员变量或成员方法的。

反面来看,假如外部类可以直接访问成员内部类的成员,还以上面的程序为例,创建一个Person类对象per,per调用方法outerCAccessinC,由于这时尚未创建成员内部类的对象,其成员变量当然也没有分配空间,这时per将访问一个不存在的变量inname,这是不允许的。

所以成员内部类的成员对外部类是不可见的,外部类是无法直接访问成员内部类的成员的。

3.成员内部类可以无限制访问外部类的成员变量及调用外部类的成员方法

示例:

类Person定义了若干个成员变量及一个成员内部类InnerClass。成员内部类InnerClass中定义了成员方法testVarMeth,testVarMeth访问及调用了外部类Person的多个成员变量和成员方法。

    String name;
int age;
String gender; public String education; //防问权限修饰符
private String hobby;
protected String residence; static String citizenship = "Chinese"; class InnerClass { void testVarMeth() {
System.out.println("name:" + name);
System.out.println("education:" + education);
System.out.println("hobby:" + hobby);
System.out.println("residence:" + residence);
System.out.println("citizenship:" + citizenship);
System.out.println("age:" + getAge());
System.out.println("gender:" + getGender());
}
} public static void main(String[] args) { Person per = new Person();
Person.InnerClass inC = per.new InnerClass(); //笔记19:内部类--成员内部类--内部类访问外部类成员变量、调用成员方法
inC.testVarMeth();
}

输出结果为:

name:null
education:null
hobby:null
residence:null
citizenship:Chinese
age:0
gender:null

从结果可以看出,成员内部类可以随意访问或调用外部类的成员变量或成员方法,与访问权限及类型等都没有关系。

4.成员内部类的成员与外部类成员同名时,内部类成员会屏蔽外部类的同名成员

示例:

对2中的程序稍加修改,为成员内部类InnerClass添加一个与Person同名的成员变量name:

String name = "li";

再执行程序的话,输出结果变为:

name:li
education:null
hobby:null
residence:null
citizenship:Chinese
age:0
gender:null

可以看出,如果成员内部类与外部类有同名的成员的话,成员内部类内部会屏蔽掉外部类的同名成员,也即,外部类的同名成员对成员内部类是不可见的。

如果一定要在内部类中使用外部类的同名成员变量的话,可以使用下面的语句:

System.out.println("name:" + Person.this.name);

即,用 外部类.this.同名成员变量名 即可访问了。

Java学习笔记20---内部类之对成员内部类的补充说明(一)的更多相关文章

  1. Java学习笔记21---内部类之对成员内部类的补充说明(二)

    上篇文章--笔记20补充说明了前四点,这里接着来说剩下的两点. 要点如下: 5.访问权限修饰符可以修饰成员内部类 1).访问权限修饰符对内部类的访问限制与外部类的一般成员遵循一样的规则,具体请参考笔记 ...

  2. Java学习笔记之---内部类

    Java学习笔记之---内部类 (一)成员内部类 内部类在外部使用时,无法直接实例化,需要借助外部类信息才能实例化 内部类的访问修饰符可以任意,但是访问范围会受到影响 内部类可以直接访问外部类的成员, ...

  3. Java学习笔记19---内部类之简介成员内部类、局部内部类及匿名内部类

    内部类,顾名思义,即定义在某个类内部的类,称包含该内部类的类为外部类. 从定义的位置来说,分为成员内部类和局部内部类:从类的特征来说,分为匿名内部类和静态内部类. 今天先简要介绍一下前三种内部类的定义 ...

  4. Java学习笔记之——内部类

    内部类 形式:把一个类定义在一个类的内部. 分为:成员内部类和匿名内部类重点掌握 a) 成员内部类 b) 静态成员内部类 c) 匿名内部类 d) 局部内部类 (1)成员内部类: Java的语言是面向对 ...

  5. Java学习笔记:内部类/匿名内部类的全面介绍

    编写java程序时,一般一个类(或者接口)都是放在一个独立的java文件中,并且类名同文件名(如果类是public的,类名必须与文件名一致:非public得,无强制要求).如果想把多个java类放在一 ...

  6. 3)Java学习笔记:内部类

    什么是内部类 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和 ...

  7. 【原】Java学习笔记025 - 内部类

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 内部类(嵌套类): ...

  8. Java学习笔记20(String类应用、StringBuffer类、StringBuilder类)

    1.获取指定字符串中大小写和数字的个数: package demo; public class StringTest { public static void main(String[] args) ...

  9. java学习笔记20(Arraylist复习,Collection接口方法,迭代器,增强型for循环)

    集合:集合是Java提供的一种容器,可以用来存储多个数据: 集合与数组的区别:集合的长度是可变的,数组的长度是固定的 集合中存储的数据必须是引用类型数据: ArrayList回顾: public cl ...

随机推荐

  1. UGUI表情系统&超链接解决方案

    最近帮一个同事解决图文混排的问题,发现了一种犀利的UGUI表情系统的解决方案 https://blog.uwa4d.com/archives/Sparkle_UGUI.html 使用重新生成UGUI文 ...

  2. 关于myeclipse8.6的优化设置

    1.设置一些类型文件的编码格式: >preferences>General>Content  Types>Text>javaScript sourcefile 相同的操作 ...

  3. Shuttle ESB(一)——入门实例

    下载Shuttle ESB 从GitHub项目公布页,下载最新的公布版本号. Shuttle-ESB源代码包列表:http://www.nuget.org/packages?q=shuttle-esb ...

  4. 多域名环境,页面获取url的一种方案

    因为系统是分布式部署的.而且有多个域名,所以常常涉及到获取url的问题. 这是系统框架层面须要提供的能力.否则每一个模块都须要自己去想办法获取ip,就会非常混乱.上线也easy发生bug 主要须要解决 ...

  5. 原来你是这样的JAVA[01]-基础一瞥

    1.Java是什么呢? Java不仅是一门语言,而且是一个完整的平台,有一个庞大的库,其中包含了很多可重用的代码和一个提供安全性.跨操作系统的可移植性以及自动垃圾收集等服务的执行环境. 2.JDK 和 ...

  6. JAVA入门[21]-Jedis操作redis示例

    本节目标 通过JedisPool获取Jedis示例,并完成对redis 简单的Key-value读写操作. 完整代码结构如下: redis服务端 在本地运行redis-server.exe,然后在re ...

  7. TableML Excel编译/解析工具

    TableML TableML, Table Markup Language, 基于电子表格的标记语言, 类似JSON, XML, INI,TableML可以作为软件项目的配置标记语言, 与之不同的是 ...

  8. mysql主从备份+keepalived自动切换

    数据库这一层需要做到避免单点故障可以是主从备份和主主备份,主主备份可能有性能损耗和数据同步的问题.这里记录下主从备份, mysql进行备份之前确保mysql的版本是一样的,我这里用的都是mysql5. ...

  9. JavaScript--AJAX页面传值

    1.首先 闲话不说 直接代码走起,都是我工作闲事的积累干货 //重要 js 运行 $(function (){ 代码 }); 2.ajax 传值 //第一种 输入框 <input type=&q ...

  10. 【CSS3】颜色表示方式

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...