讨论Java中的内部类是什么?
前言
内部类,讲完前面的特性,今天就讲下内部类这个用的比较多,出现频率挺高的知识点。
what is that?
首先,顾名思义,内部类就是在类的内部,也就是类的类,嵌套在里面的。直接代码介绍,现一般分为成员内部类和局部内部类,还有一种匿名类。内部类拥有对外围对象的引用。大部分使用的都是成员内部类。成员内部类是一种与Field、方法、构造器和初始化块相似的类成员;局部内部类和匿名内部类则不是类成员。
成员内部类
定义在类里面的成员变量域的类,就是成员内部类。此时的内部类作为其外部类的成员,所以可以使用任意访问控制符如private、protected和public等修饰。
class A {
//成员内部类,这种包含类的结构
class b{}
}
成员内部类还可以分为静态内部类和非静态内部类。注意:根据静态成员不能访问非静态成员的规则,外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等。
- 静态内部类(带static)
static关键字的作用是把类的成员变成类相关,而不是实例相关,即static修饰的成员属于整个类,而不属于单个对象。静态内部类只可以访问静态的外部类的方法和对象。但是静态内部类可以有非静态成员。
/**
* 这一篇是用来测试静态内部类的使用的
* @author yhy
* @date 1/14
*/
public class StaticInner {
private int num = 7;
/**
* 定义静态常量,这个才可以被静态内部类调用
*/
private static int num2 = 6;
static class Innerclass{
private static int num3;
public void innerfangfa(){
// System.out.println("调用外部类的成员变量:"+num);,这个会报错,因为不能调用非静态的
System.out.println("调用外部类的成员变量:"+num2);
}
}
}
报错信息
外部类使用静态类的代码。
public class StaticInner {
private int num = 7;
/**
* 定义静态常量,这个才可以被静态内部类调用
*/
private static int num2 = 6;
/**
* 定义一个静态内部类
*/
static class Innerclass{
private static int num3;
private int num4 = 4;
public void innerfangfa(){
// System.out.println("调用外部类的成员变量:"+num);,这个会报错,因为不能调用非静态的
System.out.println("调用外部类的成员变量:"+num2);
}
}
/**
* 这是外部类的方法,用来验证访问内部类的方法
*/
public static void inneracess(){
// 通过类名访问静态内部类的类成员
System.out.println("访问静态内部类:"+Innerclass.num3);
// 通过实例访问静态内部类的实例成员
System.out.println("访问静态内部类:"+new Innerclass().num4);
}
}
- 非静态内部类(不带static)
内部类可以直接访问外部类的变量、方法等,而外部类只能通过显式创建类才可以。包括可以访问外部类的private。同时,在非静态内部类里不能有静态方法、静态field、静态初始化块。
/**
* 这一篇是用来讲内部类的一些定义的
* @author yhy
* @date 1/14
*/
public class InnerClass {
private int outernum = 9;
/**
* 创建内部类,同时还定义一个常量,为private
*/
class Inner{
private int innernum = 8;
// 定义内部类的方法,去调用外部类的成员常量
public void outAcess(){
System.out.println("外部类的值:"+outernum);
}
}
/**
* 这个是外部类的成员方法
* 这里直接调用内部类会报错,不可以直接innernum使用
* 要通过显式创建内部类对象才可以实现
*/
public void innerAcess(){
System.out.println("内部类的值:"+new Inner().innernum);
}
public static void main(String[] args) {
// 创建外部类对象,没创建内部类对象
InnerClass i = new InnerClass();
i.innerAcess();
}
}
//非静态内部类对象必须寄存在外部类对象里,而外部类对象则不必一定有非静态内部类对象寄存其中
非静态内部类的方法内访问某个变量时,系统优先在该方法内查找(如果存在就使用)——if not,则到该方法所在的内部类中(存在则使用)——if not,则到该内部类所在的外部类(如果存在则使用)——if not,系统将出现编译错误。
局部内部类
局部内部类是定义在类的内部方法或者其他作用域里面的内部类。
class A {
//局部内部类
public void B(){
class B{}
}
}
局部内部类的使用
package music.daima.ebook;
/**
* * 这一篇是用来观察局部内部类的定义使用等,thinking in java的练习九
* * @author yhy
* * @date 1/14
* */
interface Ex9Interface{
/**
* @param s string类型在下面给内部类调用
* 定义一个接口,同时包含一个say方法,给下面使用
*/
void say(String s);
}
public class JuBuInner {
/**
* @return Inner()返回该类对此接口的引用
* // 这是一个方法,下面在里面定义一个内部类
*/
Ex9Interface f() {
class Inner implements Ex9Interface {
@Override
public void say(String s) {
System.out.println(s);
}
}
return new Inner();
}
public static void main(String[] args) {
JuBuInner x = new JuBuInner();
// 调用局部内部类的say方法
x.f().say("hi");
}
}
- 局部内部类不可以为public 和 private来修饰。而且因为它的上一级是方法,所以用static来修饰它是没有意义的,所以也不能用static来修饰
匿名内部类
这个知识点就直接看代码,是内部类的简化写版 ,本质不是类而是匿名对象(继承该类或者实现了改接口的)。
前提
得提前存在一个类或者是接口给它用,可以是具体类也可以是抽象类。
格式
new 类名or接口名() {重写方法};
package music.daima.ebook;
/**
* thinking in java
* @author yhy
* 匿名内部类
*/
public class AnonymousInner {
public static test1 getTest(int i){
// 匿名类的结构如下,这里的i会传给基类的构造器
return new test1(i) {
{
System.out.println(22);
}
// 重写f方法
@Override
public void f() {
System.out.println("在匿名类内");
}
};//这里要注意有分号
}
public static void main(String[] args) {
test1 abc = getTest(55);
abc.f();
}
}
/**
*创建一个抽象类
*/
abstract class test1{
// 基类的构造器
public test1(int i){
System.out.println("i is :"+i);
}
public abstract void f();
}
《Java的编程思想》中的练习题答案——使用匿名内部类
interface Inner12 {
void modifyOuter();
}
public class Outer12 {
private int oi = 1;
private void hi() { System.out.println("Outer hi"); }
public Inner12 inner() {
return new Inner12() {
public void modifyOuter() {
oi *= 2;
hi();
}
};
}
public void showOi() { System.out.println(oi); }
public static void main(String[] args) {
Outer12 out = new Outer12();
out.showOi();
out.inner().modifyOuter();
out.showOi();
}
}
下面的pd.method()方法调用结果是一样的,下面用的就是匿名内部类,相对简单一点,但是不好理解。记住它是一个对象而不是类。
why use it?
内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据
内部类可以对同一个包内的其他类隐藏起来
当想要定义一个回调函数且不想编写大量代码,可以考虑使用匿名内部类比较便捷
——《Java核心技术卷一》
个人理解:
- 内部类可以将其封装起来,很好的隐藏,可以用protected 和private权限来修饰。
- 拥有访问外部类的所有元素的权限,普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象。
- 比如可以很好处理类的办法同名重叠情况,更加有效地去引用。
- 可以间接实现了多重继承,内部类继承其它类,然后实例化外部类可以实现这种间接效果
how to use?
1.在外部类以外使用静态内部类
(因为静态内部类是外部类类相关的,因此创建内部类对象时无须创建外部类对象。)
/**这是用来测试在外部类以外使用静态内部类
* @author yhy
*/
public class innerOut {
public static void main(String[] args) {
Out1.In1 abc = new Out1.In1();
}
}
/**
* 定义一个外部类
* @author yhy
*/
class Out1{
/**
* 定义一个静态内部类,静态内部类是直接与外部类相关的
*/
static class In1{
void FangFa(){
System.out.println("这是静态内部类");
}
}
}
//output:这是静态内部类
2.在外部类以外使用非静态内部类
/**
* 使用教程——外部类以外使用非静态内部类
* @author yhy
*/
public class InnerTest {
public static void main(String[] args) {
// 格式,先外部再内部 = new 外部.new 内部
Out.In test = new Out().new In();
test.inner();
}
}
/**
* 定义一个外部类
*/
class Out{
/**
* 定义一个非静态内部类
*/
class In{
void inner(){
System.out.println("打印出内部类的信息");
}
}
}
//output:打印出内部类的信息
3.在外部类内部使用内部类
总结
静态内部类和非静态内部类区别只是在创建内部类对象时,静态的只需使用外部类即可调用构造器,而非静态则一定使用外部类对象来调用里面的方法。
讨论Java中的内部类是什么?的更多相关文章
- Java中的内部类(成员内部类、静态内部类、局部内部类、匿名内部类)
Java中的内部类(成员内部类.静态内部类.局部内部类.匿名内部类) 神话丿小王子的博客主页 我们先看这样一段话:人是由大脑.肢体.器官等身体结果组成.而组成我们人体的心脏它也有自己的属性和行为(血液 ...
- Java 中的内部类
前言 在第一次把Java 编程思想中的内部类这一章撸完后,有点印象.大概知道了什么时内部类,局部内部类,匿名内部类,嵌套内部类.随着时间的推移,自己慢慢的就忘记了,总感觉自己思考的东西不多,于是 看了 ...
- Java中的 内部类(吐血总结)
1. 内部类的作用 内部类是一个独立的实体,可以用来实现闭包:能与外部类通信:内部类与接口使得多继承更完整 2. 内部类的分类 1)普通内部类 类的实例相关,可以看成是一个实例变量.内部类的类名由 “ ...
- 【转】Java中的内部类和匿名类
Java内部类(Inner Class),类似的概念在C++里也有,那就是嵌套类(Nested Class),乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的 ...
- Java学习笔记二十:Java中的内部类
Java中的内部类 一:什么是内部类: (1).什么是内部类呢? 内部类( Inner Class )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. (2).那为什么要将一个类定 ...
- Java中的内部类怎么用
一.为什么需要内部类?java内部类有什么好处?为什么需要内部类? 首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时 ...
- Java中的内部类(回调)
一.内部类的主要作用如下: 1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类 2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据 3. 内部类所 ...
- 【Java基础】4、java中的内部类
内部类的分类:常规内部类.静态内部类.私有内部类.局部内部类.匿名内部类. 实例1:常规内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 ...
- Java中的内部类————以及jdk1.8的lambda表达式
一.内部类学习导图 1>.静态内部类: 使用static修饰符来修饰内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象.因此使用static修饰的内部类被称为静态内部类. publi ...
随机推荐
- H3C 配置基本ACL
- HDU 6438"Buy and Resell"(贪心+优先级队列)
传送门 •参考资料 [1]:HDU6438(优先队列+思维) •题意 有n个城市,第 i 天你会达到第 i 个城市: 在第 i 个城市中,你可以用 ai 元购买一个物品,或者用 ai 元卖掉一个物品, ...
- 2018-8-10-WPF-可获得焦点属性
title author date CreateTime categories WPF 可获得焦点属性 lindexi 2018-08-10 19:16:53 +0800 2018-05-15 15: ...
- 【u227】BOOK
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 陈老师喜欢网购书籍,经常一次购它个百八十本,然后拿来倒卖,牟取暴利.前些天,高一的新同学来了,他便像往 ...
- 【u228】圣诞树
[问题描述] 圣诞特别礼物挂在一棵圣诞树上,这棵树有n层,每层有一件礼物,每件礼物都有一个价值,有的礼物还有一些连结线,与下层的礼物相连,领取礼物的规则如下:任选一件礼物,它的下面如果有连结线,则可以 ...
- HTML5中Js多线程编程
Web Worker Web Worker是HTML5提出的新标准,为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行.在主线程运行的同时,Work ...
- window 系统下修改`CMD`的编码格式的方法,`CHCP` 的 使用
CHCP的使用 CHCP是一个计算机指令,能够显示或设置活动代码页编号. 一般上是在命令提示框中使用,用来查询和修改命令提示框的编码格式 具体使用方法 查看活动代码页编号 方式1: >>& ...
- Codeforces Round #564 (Div. 2)
传送门 参考资料 [1]: the Chinese Editoria A. Nauuo and Votes •题意 x个人投赞同票,y人投反对票,z人不确定: 这 z 个人由你来决定是投赞同票还是反对 ...
- P1072 城市轰炸
题目描述 一个大小为N*M的城市遭到了X次轰炸,每次都炸了一个每条边都与边界平行的矩形. 在轰炸后,有Y个关键点,指挥官想知道,它们有没有受到过轰炸,如果有,被炸了几次,最后一次是第几轮. 输入格式 ...
- AMD-require.js模块加载原理
项目中使用大了require.js,功能实现,现重新学习下模块加载原理相关知识,借鉴如下博文:https://blog.csdn.net/ai52011/article/details/7711361 ...