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

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

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

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. android application类简单介绍(一)

    每次应用程序执行时.应用程序的application类保持实例化的状态. 通过扩展applicaiton类,能够完毕下面3项工作: 1.对android执行时广播的应用程序级事件如低低内做出响应. 2 ...

  2. struts2学习笔记(8)-------struts2的ajax支持

    struts2支持一种stream类型的Result,这样的类型的Result能够直接向client浏览器响应二进制,文本等. 我们能够再action里面生成文本响应,然后在client页面动态载入该 ...

  3. C中多线程开发

    1 引言  线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期.solaris是这方面的佼佼者.传统的 Unix也支持线程的概念,可是在一个进程(proce ...

  4. C# TextBox改变高度的方法(转载)

    最近在做C# Winform项目,需要有一个能动态调整大小的Textbox,并且要是单行的.试了几次,单行模式的Textbox不能直接改高度.于是搜索了一下,整理出几个改变高度的方法. 1.将Text ...

  5. 通过shell脚本批处理es数据

    #!/bin/sh [按照指定的域名-website集合,遍历各个域名,处理url] #指定待删除的变量集合 arr=(6.0) cur="`date +%Y%m%d%H%M%S`" ...

  6. bootrap 手风琴Collapse源码分析

    /* ======================================================================== * Bootstrap: collapse.js ...

  7. go13---反射reflection

    package main /** 反射reflection 反射可大大提高程序的灵活性,使得 interface{} 有更大的发挥余地 反射使用 TypeOf 和 ValueOf 函数从接口中获取目标 ...

  8. Linux/Android——usb触摸屏驱动 - usbtouchscreen (一)【转】

    本文转载自:http://blog.csdn.net/jscese/article/details/41827495 最近需要往TV上装一个触摸屏设备,现在比较常见的就是使用usb接口的触摸框,适用于 ...

  9. PSAM卡之常用APDU指令错误码【转】

    本文转载自:http://blog.csdn.net/lvxiangan/article/details/53933714 PSAM卡的内容交互,是通过APDU指令完成的,常见的APDU报文格式如下: ...

  10. Navicat for MySQL 激活方法

    Navicat for MySQL 激活方法: 首先下载 PatchNavicat.exe ,不知道在哪儿下的可以直接拿走: 链接:https://pan.baidu.com/s/1yy4M8IDx8 ...