Java学习笔记20---内部类之对成员内部类的补充说明(一)
上篇文章--笔记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---内部类之对成员内部类的补充说明(一)的更多相关文章
- Java学习笔记21---内部类之对成员内部类的补充说明(二)
上篇文章--笔记20补充说明了前四点,这里接着来说剩下的两点. 要点如下: 5.访问权限修饰符可以修饰成员内部类 1).访问权限修饰符对内部类的访问限制与外部类的一般成员遵循一样的规则,具体请参考笔记 ...
- Java学习笔记之---内部类
Java学习笔记之---内部类 (一)成员内部类 内部类在外部使用时,无法直接实例化,需要借助外部类信息才能实例化 内部类的访问修饰符可以任意,但是访问范围会受到影响 内部类可以直接访问外部类的成员, ...
- Java学习笔记19---内部类之简介成员内部类、局部内部类及匿名内部类
内部类,顾名思义,即定义在某个类内部的类,称包含该内部类的类为外部类. 从定义的位置来说,分为成员内部类和局部内部类:从类的特征来说,分为匿名内部类和静态内部类. 今天先简要介绍一下前三种内部类的定义 ...
- Java学习笔记之——内部类
内部类 形式:把一个类定义在一个类的内部. 分为:成员内部类和匿名内部类重点掌握 a) 成员内部类 b) 静态成员内部类 c) 匿名内部类 d) 局部内部类 (1)成员内部类: Java的语言是面向对 ...
- Java学习笔记:内部类/匿名内部类的全面介绍
编写java程序时,一般一个类(或者接口)都是放在一个独立的java文件中,并且类名同文件名(如果类是public的,类名必须与文件名一致:非public得,无强制要求).如果想把多个java类放在一 ...
- 3)Java学习笔记:内部类
什么是内部类 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和 ...
- 【原】Java学习笔记025 - 内部类
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 内部类(嵌套类): ...
- Java学习笔记20(String类应用、StringBuffer类、StringBuilder类)
1.获取指定字符串中大小写和数字的个数: package demo; public class StringTest { public static void main(String[] args) ...
- java学习笔记20(Arraylist复习,Collection接口方法,迭代器,增强型for循环)
集合:集合是Java提供的一种容器,可以用来存储多个数据: 集合与数组的区别:集合的长度是可变的,数组的长度是固定的 集合中存储的数据必须是引用类型数据: ArrayList回顾: public cl ...
随机推荐
- FPGA编程基础(一)--參数传递与寄存器使用
一.參数映射 參数映射的功能就是实现參数化元件.所谓的"參数化元件"就是指元件的某些參数是可调的,通过调整这些參数从而可实现一类结构类似而功能不同的电路.在应用中.非常多电路都可採 ...
- Java后台实现方法
Java后台实现方法 首先后台结构分为四个部分(以表schedule为例) entity>mapper>service>controller 1. 在entity里面写好实体,新建目 ...
- python自动化--字符串和整数的转换,while的循环体
字符串(str)和整数(int)类型变量的结合 *遵循只有同一类型的变量才可以结合. *不同类型的变量之间的转换 实例:实现打印出"192.168.100"和1的结合出" ...
- CentOS6.5安装MySQL5.6
CentOS6.5安装MySQL5.6,开放防火墙3306端口,允许其他主机使用root账户密码访问MySQL数据库 查看操作系统相关信息 ** 该查看方法只适用于CentOS6.5 (lsb_rel ...
- Intellij IDEA 使用小结
快捷键 核心快捷键 IntelliJ IDEA 作为一个以快捷键为中心的 IDE,为大多数操作建议了键盘快捷键.在这个主题中,您可以找到最不可缺少的列表,使 IntelliJ IDEA 轻松实现第一步 ...
- 「mysql优化专题」主从复制面试宝典!面试官都没你懂得多!(11)
内容较多,可先收藏,目录如下: 一.什么是主从复制 二.主从复制的作用(重点) 三.主从复制的原理(重中之重) 四.三步轻松构建主从 五.必问面试题干货分析(最最重要的点) 一.什么是主从复制(技术文 ...
- Object.assign()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign 说明 Ob ...
- 微信小程序基于最新版1.0开发者工具分享-小试牛刀(视频)+发布流程
第一章:小程序初级入门教程 小试牛刀[含视频] 视频地址:https://v.qq.com/x/page/i0554akzobq.html 这一章节中,我们尝试着写一个最简单的例子,包含 2 个静态页 ...
- JMeter获取CSV文件行数
import java.io.BufferedReader; import java.io.FileReader; BufferedReader br=new BufferedReader(new F ...
- 【ANT】时间戳
属性 说明 举例 DSTAMP 设置为当前日期,默认格式:yyyymmdd 20170309 TSTAMP 设置为当前时间,默认格式:hhmm 2007 TODAY 设置为当前日期,带完整的月份 Ma ...