内部类(innerclasses)

1. 为何使用内部类

内部类提供了更好的封装,只有外部类能访问内部类,内部类可以独立继承一个接口,不受外部类是否继承接口影响,内部类中的属性和方法即使是外部类也不能直接访问,相反内部类可以直接访问外部类的属性和方法,即使private

利于回调函数的编写

一个内部类的例子:

public class OuterClass {

private String outerName;

private int outerAge;

public class InnerClass{

private String innerName;

private int innerAge;

}

}

2. 内部类与外部类的联系

2.1 内部类是一个相对独立的实体,与外部类不是is-a关系

内部类是一个编译时概念,编译后外部类及其内部类会生成两个独立的class文件: OuterClass.class和OuterClass$InnerClass.class,我用javac编译器对上面的OuterClass进行编译:

D:\>javac OuterClass.class

编译后的结果:

2.2 内部类可以直接访问外部类的元素,但是外部类不可以直接访问内部类的元素

public class OuterClass {

private String outerName;

private int outerAge;

public class InnerClass{

private int innerName;

InnerClass(){

//内部类可以访问外部类的元素

outerName="I am outer class";

outerAge=23;

}

public void display(){

System.out.println(outerName+" and my age is "+outerAge);

}

}

public static void main(String[] args) {

OuterClass outerClass = new OuterClass();

        OuterClass.InnerClass innerClass = outerClass.new InnerClass();

innerClass.display();

}

}

在上面例子中我们可以看到,内部类可以直接访问外部类属性,尽管外部类属性是用private修饰的。这是因为在创建外部类时,内部类会自动捕获一个外部类的引用,所以内部类访问外部类元素,实际上是通过他所持有外部类引用访问的。在java中,我们可以通过OuterClass.this来获得外部类的引用,请看下面例子:

public class OuterClass {

public void display(){

System.out.println("this is OuterClass...");

}

public class InnerClass{

//获取外部类的引用

public OuterClass getOuterClass(){

return OuterClass.this;

}

public void innerDisplay(){

//内部类也可以通过外部类的引用访问外部元素

getOuterClass().display();

}

}

public static void main(String[] args) {

OuterClass outerClass = new OuterClass();

OuterClass.InnerClass innerClass = outerClass.new InnerClass();

innerClass.innerDisplay();

}

}

2.3 外部类可以通过内部类引用间接访问内部类元素

public class OuterClass {

public void display(){

//外部类访问内部类元素,需要通过内部类引用访问

InnerClass innerClass=new InnerClass();

innerClass.innerDisplay();

}

public class InnerClass{

public void innerDisplay(){

System.out.println("I am inner class");

}

}

public static void main(String[] args) {

OuterClass outerClass=new OuterClass();

outerClass.display();

}

}

3. 创建内部类

3.1 在外部类外面(或外部类main方法)创建内部了对象

其实上面2.2例子中我们已经看到了如何创建内部类。如果要创建一个内部类对象,必须利用outerClass.new来创建:

OuterClass outerClass = new OuterClass();

OuterClass.InnerClass innerClass = outerClass.new InnerClass();

其实我们还可以一步到位:

OuterClass.InnerClass innerClass=new OuterClass().new InnerClass();

内部类创建方法示例:

public static void main(String[] args) {

//先创建外部类对象,再创建内部类对象

OuterClass outerClass = new OuterClass();

OuterClass.InnerClass innerClass1 = outerClass.new InnerClass();

innerClass1.innerDisplay();

//一步到位创建

OuterClass.InnerClass innerClass2=new OuterClass().new InnerClass();

innerClass2.innerDisplay();

}

3.2 在外部类里面创建内部类

正如2.3代码中display()方法那样,在外部类里面创建内部类,就像创建普通对象一样直接创建:

InnerClass innerClass=new InnerClass()

  1. 内部类的种类:

在Java中内部类主要分为成员内部类、方法内部类、匿名内部类、静态内部类。

4.1 成员内部类

成员内部类也是最普通的内部类,它是外部类的一个成员,所以他是可以无限制的访问外围类的所有成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。

在成员内部类中要注意两点:

成员内部类中不能存在任何static的变量和方法

成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类

4.2 方法内部类

方法内部类定义在外部类的方法中,局部内部类和成员内部类基本一致,只是它们的作用域不同,方法内部类只能在该方法中被使用,出了该方法就会失效。 对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。

4.3 匿名内部类

匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,初次之外,还有一些地方需要注意:

匿名内部类是没有访问修饰符的。

匿名内部类必须继承一个抽象类或者实现一个接口

匿名内部类中不能存在任何静态成员或方法

匿名内部类是没有构造方法的,因为它没有类名。

一般使用匿名内部类的场景是,要继承或实现的接口只有一个抽象方法,比如添加一个监听器:

public class Button {

public void click(){

 //匿名内部类,实现的是ActionListener接口

new ActionListener(){

public void onAction(){

System.out.println("click action...");

}

}.onAction();

}

//匿名内部类必须继承或实现一个已有的接口

public interface ActionListener{

public void onAction();

}

public static void main(String[] args) {

Button button=new Button();

button.click();

}

}

4.4 静态内部类

关键字static可以修饰成员变量、方法、代码块,其实它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:

静态内部类的创建是不需要依赖于外围类,可以直接创建

静态内部类不可以使用任何外围类的非static成员变量和方法,而内部类则都可以

public class OuterClass {

private static String outerName;

public  int age;

static class InnerClass1{

/* 在静态内部类中可以存在静态成员 */

public static String _innerName = "static variable";

public void display(){

/*

* 静态内部类只能访问外部类的静态成员变量和方法

* 不能访问外部类的非静态成员变量和方法

*/

System.out.println("OutClass name :" + outerName);

}

}

class InnerClass2{

/* 非静态内部类中不能存在静态成员 */

public String _innerName = "no static variable";

/* 非静态内部类中可以调用外部类的任何成员,不管是静态的还是非静态的 */

public void display(){

System.out.println("OuterClass name:" + outerName);

System.out.println("OuterClass age:" + age);

}

}

public void display(){

/* 外部类能直接访问静态内部类静态元素 */

System.out.println(InnerClass1._innerName);

/* 静态内部类可以直接创建实例不需要依赖于外部类 */

new InnerClass1().display();

/* 非静态内部的创建需要依赖于外部类 */

OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();

/* 非静态内部类的成员需要使用非静态内部类的实例访问 */

System.out.println(inner2._innerName);

inner2.display();

}

public static void main(String[] args) {

OuterClass outer = new OuterClass();

outer.display();

}

}

一般情况,我们把类定义成独立的单元。有些情况下,我们把一个类放在另一个类的内部定义,称为内部类。

51.3 内部类的作用:

    1.    内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问。

2.    内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。 

但外部类不能访问内部类的内部属性。

       内部类的使用场合:

       由于内部类提供了更好的封装特性,并且可以很方便的访问外部类的属性。所以,通常内部类在只为所在外部类提供服务的情况下优先使用。

51.4 内部类的分类:

    1.    成员内部类(可以使用private、proteted、public任意进行修饰。 类文件:外部类$内部类.class)

    a)    非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)

i.    非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。 非静态内部类对象单独属于外部类的某个对象。

ii.    非静态内部类可以使用外部类的成员,但是外部类不能直接访问非静态内部类成员。

iii.   非静态内部类不能有静态方法、静态属性、静态初始化块

iv.    静态成员不能访问非静态成员:外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例。

v.    成员变量访问要点:

1.    内部类里方法的局部变量:变量名

2.    内部类属性:this.变量名

3.    外部类属性:外部类名.this.变量名

vi.    内部类的访问:

1.    外部类中定义内部类:  new InnerClass()

2.    外部类以外的地方使用非静态内部类:

Outer.inner  varname = OuterObject.new Inner()

Face.Nose nose =  new Face().new Nose();

Face f2 = new Face();

Face.Nose nose2 = f2.new Nose();

b) 静态内部类

i.    定义方式:

static  class   ClassName {

//类体

}

ii.    使用要点:

1.    当一个静态内部类对象存在,并不一定存在对应的外部类对象。 因此,静态内部类的实例方法不能直接访问外部类的实例方法。

2.    静态内部类看做外部类的一个静态成员。 因此,外部类的方法中可以通过:静态内部类.名字  访问静态内部类的静态成员。通过 new 静态内部类()访问静态内部类的实例。

3.    在外部类的外面创建静态内部类:

Face.TestStaticInner  aInner = new  Face.TestStaticInner();

2. 匿名内部类

适合那种只需要使用一次的类。比如:键盘监听操作等等。语法:

new  父类构造器(实参类表) 实现接口 () {

//匿名内部类类体!

}

局部内部类

定义在方法内部。作用域只限于本方法。用的非常少。

JAVA 内部类(innerclasses)相关推荐

  1. [转] Java内部类详解

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

  2. java内部类_Java内部类

    java内部类 Java inner class is defined inside the body of another class. Java inner class can be declar ...

  3. 看到如此详细的Java内部类,我泪目了

    Java内部类 介绍 定义 成员内部类 语法格式 使用说明 代码示例 局部内部类 语法格式 使用说明 代码示例 匿名内部类 语法格式 使用说明 代码示例 静态内部类 语法格式 使用说明 代码示例 介绍 ...

  4. Java内部类作用全解

    提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比.内部类从表面上看,就 ...

  5. netBeans调试时不进入java内部类(jdk源码)的方法 转载

    初次使用netbeans的调试功能时,会发现调试中,进入了java的内部类运行,具体情况,如下图所示: 对于我这样的一个新手,完全弄不懂啊. 后来我去论坛问了,同时自己研究,发现经过以下设置,就可以跳 ...

  6. Java内部类(Inner Class)小记

    一.引子 看到Trinea的博文Junit单测代码中java序列化失败的解决,让我想到Java内部类的一些小Gocha,初学Java时很迷惑.这里记录一下. 就以Trinea的博文中的序列化失败的例子 ...

  7. Java内部类简介.

    一, 什么是内部类 Java中所谓内部类, 就是定义在另1个类内的类. 例如: class A{int a;class B{int b;} } 上面类B就是类A的一个内部类. 但是下面的写法, B只是 ...

  8. java内部类文件,Java内部类学习

    Java内部类学习 1.内部类的实例与外部类的实例共享一种特殊的关系,这种特殊的关系为内部类中的代码提供对封装(外部)类成员的访问.其实,内部类就是外部类的一部分.不仅仅是"一部分" ...

  9. 在Java内部类中使用外部类的成员方法以及成员变量

    http://blog.csdn.net/zhongyili_sohu/article/details/8975947 众所周知,在定义成员方法或者成员变量的时候,可以给其加上一些权限的修饰词,以防止 ...

  10. Java内部类引用外部类中的局部变量为何必须是final问题解析

    Java内部类引用外部类中的局部变量为何必须是final问题解析 今天编写一个多线程程序,发现在方法内定义内部类时,如果内部类调用了方法中的变量,那么该变量必须申明为final类型,百思不得其解,后来 ...

最新文章

  1. 《C#精彩实例教程》小组阅读07 -- C#字符与字符串
  2. php随机跳转,Nginx实现404页面跳转到任意随机页面
  3. 数学图形(1.2)Sin曲线
  4. 【干货】SqlServer 总结几种存储过程分页的使用
  5. 头条上python广告_满大街都是Python广告,真的如广告说的那样方便吗?,学精通后真能月如过万吗?业内大佬怎么看?...
  6. Javascript eval()函数 基础回顾
  7. Go 的新关键字 any 是个啥
  8. 电子助力方向机控制模块_17款路虎揽胜:偶发性电子助力失效
  9. 通过u盘装window7
  10. 关于P,V操作理解的分析
  11. unity 创建NGUI字体
  12. 点赞 分数 20作者 陈越单位 浙江大学
  13. 东晋琴家、雕塑家、画家、哲学家戴逵
  14. CAN总线学习心得:zlg关于can帖子汇总【转】【强烈推荐】
  15. 66网整站数据Thinkphp+layui版
  16. SSM实训:11、页面插件集成
  17. 开源代码01:眼力大挑战
  18. TensorFlow SSE/AVX/FMA 指令集编译
  19. OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据
  20. 在Ubuntu中搭建tftp服务,使用X210开发板加载系统测试

热门文章

  1. JavaWeb — 请求响应流程图
  2. kafka consumer group 定义
  3. ASP.NET配置设置-关于web.config各节点的讲解
  4. MVC仓储执行存储过程报错“未提供该参数”
  5. Maven的配置和使用(三)
  6. VMware:未能将管道连接到虚拟机, 所有的管道范例都在使用中
  7. 网络工程师Day2---实验2-1:HDLC和PPP配置
  8. 基于node.js的express连接数据库
  9. IS-IS详解(七)——IS-IS LSP报文详解
  10. 杭电计算机2011年硕士研究生笔试详解