上篇文章--笔记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. 使用python处理excle表格

    # -*- coding: utf-8 -*- import xlrd ########################### #通用功能,读取excel表格中所有数据 #返回一个包含所有单元格名和对 ...

  2. 豌豆夹Redis解决方式Codis源代码剖析:Proxy代理

    豌豆夹Redis解决方式Codis源代码剖析:Proxy代理 1.预备知识 1.1 Codis Codis就不详细说了,摘抄一下GitHub上的一些项目描写叙述: Codis is a proxy b ...

  3. 入门Webpack

    ---恢复内容开始--- 什么是WebPack,为什么要使用它? 为什要使用WebPack 现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包.为了简化 ...

  4. JAVA入门[17]-ControllerAdvice处理exception

    1.关于@ControllerAdvice @ControllerAdvice注解本身已经使用了@Component,因此@ControllerAdvice注解所标注的类将会自动被组件扫描获取到,就像 ...

  5. iOS开发 字符串的转化 小技巧

    /字典或者数组转化为nsstring NSArray *arr = [NSArray arrayWithObject:@"1"]; NSString *str = [arr JSO ...

  6. SignalR简单Demo

    我们实现一个简单的消息通知的Demo 在NuGet中添加SignalR引用 install-package Microsoft.AspNet.SignalR 然后我们创建一个类来引用Hub类 name ...

  7. acffo的开源项目汇总

    1. XWaveView, 流动波浪效果                      2.LogRecordHelper, logcat日志记录存储到文件 可以指定TAG , 将logcat日志写入文件 ...

  8. 《TCP-IP详解卷2:实现》【PDF】下载

    <TCP-IP详解卷2:实现>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062539 内容简介 <TCP/IP详解·卷2 ...

  9. ext.net在使用水晶报表时页面无数据显示,并报错误Uncaught ReferenceError: bobj is not defined.

    一.错误描述 在公司做项目的时候,有时会需要用到水晶报表显示数据,水晶报表在ASP.NET中使用时没有问题,winform项目开发也没有问题,但是在ext.net开发使用时却报错了,错误:Uncaug ...

  10. Hive实际应用小结

    1.简介 Hive是数据仓库平台,构建在Hadoop之上用来处理结构化数据.Hive是一个SQL解析引擎,能够将SQL语句转化成MapReduce作业并在Hadoop上执行,从而使得查询和分析更加方便 ...