内部类简单来说就是把一个类的定义放到另一个类的定义内部

内部类分为:成员内部类、局部内部类、匿名内部类、静态内部类

成员内部类:最常见的内部类

public class Outter {
private int i = 0;
public static String name = "sam";
public Outter(int i) {
this.i = i;
}
class Inner{
public Inner() {
System.out.println("Inner Class");
}
public void add() {
System.out.println(i + " Name: " + name);
System.out.println("add()");
}
}
}

测试类:

public static void main(String[] args) {
Outter outter = new Outter(1);
Outter.Inner inner = outter.new Inner();
inner.add();
}

结果:

Inner Class
1 Name: sam
add()

成员内部类Inner看起来是外部类Outter的成员,所以以此命名

内部类可以访问外部类的所有属性和方法(包含private和static)

外部类访问内部类一般就是通过上述代码的方式

  当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同

名成员,需要以下面的形式进行访问:this表示当前对象,如果Outter方法为static,不需要this

外部类.this.成员变量
外部类.this.成员方法
public class Outter {
private int i = 0;
public static String name = "sam";
public Outter(int i) {
this.i = i;
}
private static void del() {
System.out.println("Outter del()");
}
class Inner{
private int i = 2;
public Inner() {
System.out.println("Inner Class");
}
private void del() {
System.out.println("Inner del()");
}
public void add() {
del();
Outter.del();
System.out.println("Inner Class: " + i + " Name: " + name);
System.out.println("Outter Class: " + Outter.this.i + " Name: " + name);
System.out.println("add()");
}
}
}

  内部类的修饰符可以是任意的,但是如果为private,只能在外部类的内部进行访问,其他地方不可以。这一点不同和外部类,外部类的修饰符

只能是public和默认,应该是因为此时的内部类相当于外部类的成员,而成员可以是任意的

局部内部类:

定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

为什么要使用局部内部类?

1、实现某个接口,可以创建并返回对其的作用

2、要解决一个复杂的问题,创建一个类来辅助解决,但又不希望这个类是公共可用的

内部类位于方法内:

public interface Destination {
String readLine();
}
public class Outter {
public Destination destination(String s) {
class Inner1 implements Destination {
private String label;
public Inner1(String whereTo) {
this.label = whereTo;
}
@Override
public String readLine() {
return label;
}
}
return new Inner1(s);
} public static void main(String[] args) {
Outter outter = new Outter();
Destination destination = outter.destination("aaa");
} }

Inner属于Destination,而不是Outter的一部分,所以在destination()之外无法访问Inner

也可以位于作用域内,例如if()

PS:局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的

PS:在jdk1.8之前这个参数s需要final修饰,否则会编译报错,jdk1.8不需要

匿名内部类:

public class Outter {
public Destination destination() {
return new Destination() { //插入一个类的定义
private int i = 11;
public int value() {
return i;
}
};
} public static void main(String[] args) {
Outter outter = new Outter();
Destination destination = outter.destination();
}
}

在讲接口的时候,曾经说过,接口无法被实例化,直接new只是生成一个匿名内部类而已。

这里产生一个类,这个类是匿名的。创建了一个继承自Destination的匿名类对象,返回的引用自动向上转型为对Destination的引用。

下面是简化形式:

public class Outter {
public Destination destination() {
return new MyDestination();
}
class MyDestination implements Destination {
private int i = 11;
public int value() {
return i;
}
}
}

PS:简化形式有点像成员内部类,但是这里区别就是class要实现一个接口

传递参数:

public class Outter {
public Destination destination(int i1) {
return new Destination() { //插入一个类的定义
private int i = i1;
public int value() {
return i1;
}
};
} public static void main(String[] args) {
Outter outter = new Outter();
Destination destination = outter.destination(2);
}
}

PS:在jdk1.8之前这个参数i1需要final修饰,否则会编译报错,jdk1.8不需要,和局部内部类相同

  唯一一个没有构造器的类,感觉这句话有问题,通过javap查看字节码指令,发现编译器会为匿名内部类生成类名,带有引用的构造函数

  匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类(抽象类)或是实现接口,并不需要增加额外的方法

,只是对继承方法的实现或是重写。

应用:  

Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("run()");
}
};

还有就是添加监听,进行接口回调,这个很常见,例如在rabbitMQ中使用confirm和return机制

//6 添加一个return监听
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.err.println("---------handle return----------");
System.err.println("replyCode: " + replyCode);
System.err.println("replyText: " + replyText);
System.err.println("exchange: " + exchange);
System.err.println("routingKey: " + routingKey);
System.err.println("properties: " + properties);
System.err.println("body: " + new String(body));
}
});
//6 添加一个确认监听
channel.addConfirmListener(new ConfirmListener() {
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
System.err.println("-------no ack!-----------");
} @Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
System.err.println("-------ack!-----------");
}
});

静态内部类:

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。如果不需要内部类对象和外部类对象有联系,可以使用static

普通内部类:内部类对象隐式地保存一个指向外部类对象的引用

静态内部类:创建对象,不需要依赖外部类对象,不能访问非静态的外部类变量和方法,因为非static依赖对象,而静态内部类又不依赖外部类对象

public class Outter {
private static String s1;
private String s3;
static class Inner {
private static String s = s1;
private String s2 = s3;
public static void add() {
System.out.println("add()");
}
public void del() {
System.out.println("del()");
}
}; public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
inner.del();
Outter.Inner.add();
}
}

结果:

  1、印证里上面所说,静态内部类不能引用外部类非static字段,这里s2 = s3会编译报错

  2、static方法和非static方法调用区别,要访问静态内部类的非static方法,必须通过静态内部类的实例对象去调用

命名规则:

  匿名内部类:Outter$1.class,数字依次递增

  非匿名内部类:Outter$Inner.class

除此之外还包含一个Outter.class

为什么在Java中需要内部类?

1、Java可以多实现,不能多继承,可以通过接口实现多继承,而内部类是多继承另一种实现方案。无论外部类是否继承接口,内部类都可以继承

2、方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏(可以访问外部类的private变量)

3、方便编写事件驱动程序

4、方便编写线程代码

本文参考:Java编程思想,Java内部类详解

很多内容来自海子的这篇博客,算是转载,原文也更加详细,内容更多一点,也加了一点自己的理解

Java基础(五)--内部类的更多相关文章

  1. 面渣逆袭:Java基础五十三问,快来看看有没有你不会的!

    大家好,我是老三, 面渣逆袭 系列继续.这节我们回到梦开始的地方--Java基础,其实过了萌新阶段,面试问基础就问的不多,但是保不齐突然问一下.想一下,总不能张口高并发.闭口分布式,结果什么是面向对象 ...

  2. java基础之 内部类

    Java中的内部类共分为四种: 静态内部类static inner class (also called nested class) 成员内部类member inner class 局部内部类loca ...

  3. Java基础(53):内部类(转)

    java中的内部类总结 内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类 如同一个人是由大脑.肢体.器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行 ...

  4. Java基础五(方法)

    今日内容介绍1.方法基础知识2.方法高级内容3.方法案例 ###01方法的概述 * A: 为什么要有方法 * 提高代码的复用性 * B: 什么是方法 * 完成特定功能的代码块. ###02方法的定义格 ...

  5. Java基础(五) final关键字浅析

    前面在讲解String时提到了final关键字,本文将对final关键字进行解析. static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提 ...

  6. java基础之 内部类 & 嵌套类

    参考文档: 内部类的应用场景 http://blog.csdn.net/hivon/article/details/606312 http://wwty.iteye.com/blog/338628 定 ...

  7. java基础随笔-内部类

    今天来复习下内部类的一些基础知识. 首先是内部类的分类: 1.成员内部类 2.静态内部类 3.匿名内部类 4.局部内部类 下面逐一来介绍下. 首先是成员内部类,就是将内部类作为一个成员变量来处理.具体 ...

  8. Java基础(五)-Java序列化与反序列化

    .output_wrapper pre code { font-family: Consolas, Inconsolata, Courier, monospace; display: block !i ...

  9. java基础(五)-----关键字static

    在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个“伪全局”的概念,在Java中static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,当然也可以修饰代码块. ...

随机推荐

  1. (十)Net Core项目使用Cookies (八)Net Core项目使用Controller之三-入参

    (十)Net Core项目使用Cookies 一.简介 1.Net Core可以直接使用Cookies,但是调用方式有些区别. 2.Net Core将Request和Response分开实现. 二.基 ...

  2. MySQL Study之--MySQL压力測试工具mysqlslap

    MySQL Study之--MySQL压力測试工具mysqlslap 一.Mysqlslap介绍     mysqlslap是MySQL5.1之后自带的benchmark基准測试工具,类似Apache ...

  3. 组件的使用(四)DatePickerDialog和TimePickerDialog的使用

    这两个组件的使用都须要获得当前日期或时间.实现方法是获得一个Calender实例(调用getInstance()实例化) DatePickerDialog的使用 Calendar calendar=C ...

  4. 量化分析师的Python日记【第1天:谁来给我讲讲Python?】

    量化分析师的Python日记[第1天:谁来给我讲讲Python?]薛昆Kelvin优矿 001 号员工2015-01-28 15:48 58 144克隆 ###“谁来给我讲讲Python?” 作为无基 ...

  5. python 字符编码处理问题总结 彻底击碎乱码!

    Python中常常遇到这种字符编码问题,尤其在处理网页源代码时(特别是爬虫中): UnicodeDecodeError: 'XXX' codec can't decode bytes in posit ...

  6. Tool:Adobe Photoshop

    ylbtech-Tool-Adobe:Adobe Photoshop 1.返回顶部 1. Adobe Photoshop,简称“PS”,是由Adobe Systems开发和发行的图像处理软件. Pho ...

  7. bzoj4264

    哈希 cf原题...没见过的话真想不出来 将邻接表排序哈希,判断是否相同,但是会漏掉两点相邻的情况,于是再把自己加入自己的邻接表,然后再哈希判断. #include<bits/stdc++.h& ...

  8. 【培训】MySQL

    yum安装mysql:yum -y install mysql*- 或者 yum -y install mysql* 启动数据库服务:/etc/init.d/mysqld start 或者 servi ...

  9. PCB 漏加阻抗条的臆想(转)

    阻抗条,我对你是有感情的,这你一定要相信我! 否则,不会在之前的每一次拼板,都不忘拥你入Panel之怀. 自做CAM开始,已记不清我们曾有多少次不期而遇, 我们一同迎接朝阳,送走晚霞,凝望窗外如洗的月 ...

  10. bzoj 1628: [Usaco2007 Demo]City skyline【贪心+单调栈】

    还以为是dp呢 首先默认答案是n 对于一个影子,如果前边的影子比它高则可以归进前面的影子,高处的一段单算: 和他一样高的话就不用单算了,ans--: 否则入栈 #include<iostream ...