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 ...
随机推荐
- Unity 3D游戏开发引擎:最火的插件推荐
摘要:为了帮助使用Unity引擎的开发人员制作更完美的游戏.我们精心挑选了十款相关开发插件和工具.它们是:2D Toolkit.NGUI.Playmaker.EasyTouch & EasyJ ...
- js通用方法检測浏览器是否已安装指定插件(IE与非IE通用)
/* * 检測是否已安装指定插件 * * pluginName 插件名称 */ function checkPlugins(pluginName) { var np = navigator.plugi ...
- UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 46:illegal multibyte sequence
一. 最近使用python写入文件时,出现了如下的错误: 但是content的内容是unicode编码,不知道怎么和gbk扯上了关系,对content使用encode()和decode(),用gbk, ...
- Mybatis(基于SqlSessionTemplate的实现) + Spring 练习实战
mybatis学习篇:上次使用映射接口实现Mybatis,有不方便指出就是需要接口,且需要保证接口上不能存在其他的代理.这次通过SqlSessionTemplate基于模板类实现Mybatis,总的来 ...
- Chef 自动化运维:初探 cookbook
cookbook 概述 Chef 意为"厨房",我们要做"菜",自然需要有"菜谱".事实上在 Chef 中分发到各服务器节点的不是" ...
- Struts配置详解
一.Stuts的元素 1 web.xml 任何一个web应用程序都是基于请求响应模式进行构建的,所以无论采用哪种MVC框架,都离不开web.xml文件的配置.换句话说,web.xml并不是Struts ...
- idea和Webstorm上使用git和github,码云
由于之前一直使用svn,现在项目使用git,顾根据网上找的学习资料,自己梳理了下,收获蛮多,这里做个记录,如果能帮助到您那是最好不过的. 1.大致步骤 使用工具:idea,github,码云 webs ...
- ext.net在使用水晶报表时页面无数据显示,并报错误Uncaught ReferenceError: bobj is not defined.
一.错误描述 在公司做项目的时候,有时会需要用到水晶报表显示数据,水晶报表在ASP.NET中使用时没有问题,winform项目开发也没有问题,但是在ext.net开发使用时却报错了,错误:Uncaug ...
- 【python】列表
>>> mix = [2,3.4,"abc",'中国',True,['ab',23]]>>> mix[2, 3.4, 'abc', '中国', ...
- JavaScript循环实例
几个经典的循环案例: 1.一张纸的厚度是0.0001米,将纸对折,对折多少次厚度超过珠峰高度8848米 var i=0; var h=0.0001; while(true){ i++; h=h*2; ...