Java内部类简介.
一, 什么是内部类
Java中所谓内部类, 就是定义在另1个类内的类.
例如:
class A{int a;class B{int b;}
}
上面类B就是类A的一个内部类.
但是下面的写法, B只是A的一个成员.
class A{private int a;B b;
}class B{int bb;
}
因为B的定义体在类A之外, 注意区别.
Java编译器编译后, 还是会把面的代码编译成两个class.
1个是A
另1个是 A$B
对于Jvm来讲,它们实际上还是两个单独的类.
二,内部类的好处.
的确, 内部类的写法的确会破坏Java代码的良好结构以及可读性.
但是内部类也有它存在的意义.
例如一部法拉利跑车类, 它里面包括了1个发动机, 而发动机本身也有很多方法(例如,启动, 变速等). 所以发动机本身也是1个类.
但是法拉利的发动机技术很好, 为了技术机密保护, 法拉利本身不想外部知道发动机的细节, 就可以把发动机作为1个内部类.
也就是说, 外部不能直接实例化1个法拉利发动机, 用在别的车上.
好处:
1. 限制外部世界对内部类的访问.
2. 内部类可以直接访问外部类的成员.
其中第2点很重要, 甚至比第一点还重要.
三,什么情况下需要用到内部类.
这里我举1个具体点的例子.
加入1个聊天窗口Form类.
有很多控件类对象成员(例如输入框, 显示框等).
现在要启动2个线程, 分别用于接受和发送消息.
问题来了, 启动线程必须要重写Thread类或实现Runable接口,总结要写新的类.
那么新的类写在哪里呢.
如果写在外面, 那么新的类必须写入很多控件类的成员.
如果写入在Form类里面, 就可以直接使用Form类的所有成员. 这样就方便很多.
而且这个两个类也不想被其他类使用, 所以内部类就很适合了.
四,内部类的种类.
没错, Java内部类也可以根据定义的位置和访问权限分成下面若干种内部类.
4.1 定义在另1个类的方法体外的内部类.
4.1.1 非私有内部类(非静态)
这种内部i类(B)虽然定义在另1个类(A)的内部, 但实际上它是被第三个类(C)实例化的.
不过C类想实例化类B. 则必须先实例化类A.
public class InternalClass1{public static void f(){A a = new A(3);A.B b = a.new B();b.print();A.B b2 = new A(4).new B();b2.print();}
}class A{private int i;public A(int i){this.i = i;}class B{public void print(){System.out.printf("A.i is %d\n",i);}}
}
上面的例子定义了外部类A和内部类B.
可以见到内部类B是无限制地访问A的私有成员的.
反过来, 类A也同样可以无限制的内部类B的私有成员.
而B可以被第三个类(InternalClass1)实例化.
实例化的写法上面写了两种, 但是都必须事先实例化1个A对象.
也就是说Java必须为A的1个对象分配内存, 才能为A的内部类对象分配内存.
4.1.2 私有内部类(非静态)
私有内部类指的是private 修饰的内部类(注意外部类不能被private修饰)
这样的话
内部类B不能被第三方类C直接访问和实例化
但是能通过A的封装方法访问.
例子:
public class InternalClass2{public static void f(){//A2.B2 b = new A2(3).new B2(); //errorA2 a = new A2(3);a.f();}
}class A2{private int i;public A2(int i){this.i = i;}public void f(){B2 b = new B2();System.out.println(i + b.b);}private class B2{private int b =3;public void print(){System.out.printf("A.i is %d\n",i);}}
}
4.1.3 静态内部类
跟外部类不同, 内部类可以用static关键字来修饰. 代表这个是1个静态内部类.
静态内部类跟非静态内部类有两点不同.
1. 实例化1个非静态内部类之前必须实例化其外部类. 而静态内部类不需要. 可以直接被实例化, 也就是说静态内部类不需要1个外部类对象.
2. 同样地, 内部类只能访问其外部类的静态成员. 因为外部类的非静态成员依赖于外部类对象实例化.
例子:
public class InternalClass3{public static void f(){A3.printj(3);}
}class A3{private int i;private static int j;public static void printj(int j){B3 b = new B3(j);b.print();}private static class B3{public B3(int j){//A3.i= 3;//errorA3.j = j;}public void print(){System.out.printf("A.j is %d\n",j);}}
}
4.1.4 方法体内部类
下面开始恶心了, 就是内部类可以定义在方法体内.
假如B 是 A的方法f(int a)内的1个内部类.
1. B还是无限制访问A的所有成员.
2. A只能在方法f()内访问和使用B.
假如B定义在f() 里面的if() 或 try{}字句内, 那么同样地, A只能在if,try的作用范围内使用B.
3. 在方法体f()内, 代码还是严格按照顺序执行的, 那就是说必须先定义内部体B, 再使用.
4. 假如B定义的内部使用到参数a 那么a必须用Final修饰.
例子:
public class InternalClass4{public static void f(){new A4(2).printB(3,6);}
}class A4{private int i;public A4(int i){this.i = i;}public void printB(final int x, int y){//class Bclass B4{public int getSum(){return i + x;}} System.out.println(new B4().getSum() + y);}
}
例如上面的printB方法, 有两个参数x, y 但是内部类B只访问了x, 所以x必须用final修饰, 而y不用.
可以看出, 这个种内部类已经大大影响java代码的可读性了.
幸好这种内部类不可能被其他类访问. 作用域也只在方法体内. 但是起名字还是需要避免和同包内的其它类冲突.
4.1.5 匿名内部类
所谓匿名内部类就是定义1个内部类时不指定类名字
听起来不合常理啊.
在外部类A内定义1个匿名内部类B(注意B不是类名, 只是1个代号) 有两个必要天剑.
1.内部类B只能定义在A的方法体内.
2.内部类必须是继承自另1个类Bp(Bp是类名). 或者是实现另1个接口Bi(Bi是接口名).
而Bp和Bi必须事先定义.
对于第一种, 一般用于调用1个超类的重写工公共方法.. 例如重写Thread类Run方法, 开启1个新进程.
public class InternalClass5{public static void f(){new A5().printB(3);}
}class A5{private int i = 100;public void printB(final int x){//a new internal class which inherits Thread new Thread(){public void run(){while(i > 0){System.out.println(i);i = i -x;}}}.start();}
}
对于第2种, 一般是返回1个接口的实现类对象:
例如:
public class InternalClass6{public static void f(){Ib b = new A6().GetIB(4);b.f();}
}class A6{private int i = 100;public Ib GetIB(final int x){//a new internal class which implements interface Ib return new Ib(){public void f(){System.out.println("this is a method implemented from a interface!");System.out.println(i+x);}};}
}interface Ib{void f();
}
注意这个接口必须是事先定义的.
匿名内部类的好处是随写随用, 而且无非担心命名冲突.
Java内部类简介.相关推荐
- Java 内部类简介,理解,特点,注意事项
什么是内部类 内部类,顾名思义,就是在一个类当中再定义一个类.例如在python当中的闭包函数(函数内部再定义一个函数).Python闭包函数的理解 如果在类Outer的内部再定义一个类Inner,此 ...
- 看到如此详细的Java内部类,我泪目了
Java内部类 介绍 定义 成员内部类 语法格式 使用说明 代码示例 局部内部类 语法格式 使用说明 代码示例 匿名内部类 语法格式 使用说明 代码示例 静态内部类 语法格式 使用说明 代码示例 介绍 ...
- Java EE 简介
Java EE 简介 Java EE 基本架构 JavaEE 的诞生是为了解决传统 C/S 架构的弊端:客户端臃肿庞大,扩展性差等弊端. JavaEE 将传统的两层结构细分为了四层. 这四层分别是:C ...
- java程序包不存在_第一章 Java语言简介
Java语言简介 Java之父 James Gosling(詹姆斯·高斯林) 正式诞生时间 1995年,已有二十多年历史 三大方向 JavaSE(桌面版,基础需重点掌握) JavaME(移动版,现在基 ...
- (一:NIO系列)JAVA NIO 简介
出处:JAVA NIO 简介 Java 中 New I/O类库 是由 Java 1.4 引进的异步 IO.由于之前老的I/O类库是阻塞I/O,New I/O类库的目标就是要让Java支持非阻塞I/O, ...
- ibm java_IBM i 上Java 虚拟机简介
Abstract IBM i 上Java 虚拟机简介 Body Java在IT业界有多流行?google上搜索一下java, 结果一目了然(今天早上我搜索到的记录数是840000000条).Java之 ...
- Java内部类作用全解
提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比.内部类从表面上看,就 ...
- netBeans调试时不进入java内部类(jdk源码)的方法 转载
初次使用netbeans的调试功能时,会发现调试中,进入了java的内部类运行,具体情况,如下图所示: 对于我这样的一个新手,完全弄不懂啊. 后来我去论坛问了,同时自己研究,发现经过以下设置,就可以跳 ...
- Java内部类(Inner Class)小记
一.引子 看到Trinea的博文Junit单测代码中java序列化失败的解决,让我想到Java内部类的一些小Gocha,初学Java时很迷惑.这里记录一下. 就以Trinea的博文中的序列化失败的例子 ...
最新文章
- DOS命令输出的重定向
- Redis:哨兵模式(Sentinel)原理
- 对象的克隆(clone方法)
- 创业——不可忽视的创业计划书!!!
- 1082 射击比赛 (20 分)
- 1-4 数组元素的区间删除 (20 分)
- 安全模式下修复电脑故障
- java多线程与线程间通信
- 如何禁止树莓派屏幕休眠
- spring boot-Soap协议客户端集成(根据WSDL文档调用WebService、maven的jaxb2插件)
- log4j日志配置(超详细)
- 怎么用计算机按log以2为底,log以2为底4的对数在计算器上怎么按?
- [Joy]冷笑话急转弯
- uniapp全端应用商城系统,应用市场APP,软件库APP,葫芦芥子博客
- 奥斯汀大学计算机专业怎么样,德克萨斯大学奥斯汀分校计算机工程排名
- Jaca程序基础学习笔记
- 关于中医把脉的一点想法
- USB过压过流保护芯片,可调限流4A,6V过压关闭
- 小米手机5X获得Root权限的方法
- 第一行代码天气预报接口更改后JSON键值对的问题