简介

一般来说,我们创建类和接口的时候都是一个类一个文件,一个接口一个文件,但有时候为了方便或者某些特殊的原因,java并不介意在一个文件中写多个类和多个接口,这就有了我们今天要讲的内部类和内部接口。

内部类

先讲内部类,内部类就是在类中定义的类。类中的类可以看做是类的一个属性,一个属性可以是static也可以是非static的。而内部类也可以定义在类的方法中,再加上匿名类,总共有5种内部类。

静态内部类

我们在class内部定义一个static的class,如下所示:

@Slf4j
public class StaticInnerClass { static class Inner {
void print() {
log.info("Inner class is: " + this);
}
} public static void main(String[] args) {
StaticInnerClass.Inner inner = new StaticInnerClass.Inner();
inner.print();
}
}

因为static变量可以直接根据类名来存取,所以我们使用new StaticInnerClass.Inner()来实例化内部类。

非静态内部类

class中定义的类也可以是非静态的,如下所示:

@Slf4j
public class InnerClass { class Inner {
void print() {
log.info("Inner class is: " + this);
}
} public static void main(String[] args) {
InnerClass.Inner inner = new InnerClass().new Inner();
inner.print();
}
}

要访问到类的变量,需要实例化外部内,然后再实例化内部类:new InnerClass().new Inner()。

注意这里我们需要使用到两个new。

静态方法内部类

我们可以在静态方法中定义一个类,这个类其实就相当于方法中的变量,这个变量当然不能是static的。我们看下面的例子:

@Slf4j
public class StaticMethodInnerClass { private static String x = "static x"; public static void print() {
class MyInner {
public void printOuter() {
log.info("x is " + x);
}
}
MyInner i = new MyInner();
i.printOuter();
} public static void main(String[] args) {
StaticMethodInnerClass.print();
}
}

方法中的类,我们是无法在外部实例化的。

非静态方法的内部类

同样的非静态方法也可以定义内部类:

@Slf4j
public class MethodInnerClass { private String x = "non static x"; public void print() {
class MyInner {
public void printOuter() {
log.info("x is " + x);
}
}
MyInner i = new MyInner();
i.printOuter();
} public static void main(String[] args) {
new MethodInnerClass().print();
}
}

注意,这里需要先实例化外部类才可以继续调用。

匿名类

最后一个,匿名类,直接在需要的时候实例化的类。匿名类我们遇到了很多次了,比如在构建SortedSet的时候,可以传入自定义的Comparator,我们可以用匿名类来实现,也可以直接使用lambda表达式。

public class AnonymousClass {

    public static void main(String[] args) {
SortedSet sortedSet1 = new ConcurrentSkipListSet(new Comparator(){
@Override
public int compare(Object o1, Object o2) {
return 0;
}
}); SortedSet sortedSet2 = new ConcurrentSkipListSet((o1, o2) -> 0);
}
}

内部接口

Inner Interface是指在接口中定义的接口。最常见的就是Map中的Entry了:

public interface Map<K, V> {
interface Entry<K, V> {
K getKey();
}

这里的内部接口一定是static的,因为接口是不能实例化的,所以为了访问到接口中的接口,必须定义为static。如果不指定,则默认就是static。

我们看一个该内部接口的实现:

public class MapImpl implements Map.Entry{
@Override
public Object getKey() {
return 0;
} @Override
public Object getValue() {
return null;
} @Override
public Object setValue(Object value) {
return null;
}
}

总结

本文讲解了5个内部类的实现和一个内部接口的应用。大家只要把内部的类或者接口看成一个变量,就可以很好的理解上面的内容了。

本文的例子https://github.com/ddean2009/learn-java-base-9-to-20

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/inner-class-inner-interface/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

java中的内部类内部接口详解的更多相关文章

  1. Java中「Future」接口详解

    目录 一.背景 二.Future接口 1.入门案例 2.Future接口 三.CompletableFuture类 1.基础说明 2.核心方法 2.1 实例方法 2.2 计算方法 2.3 结果获取方法 ...

  2. “全栈2019”Java第八十三章:内部类与接口详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  3. Java 中的异常和处理详解

    Java 中的异常和处理详解 原文出处: 代码钢琴家 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误 ...

  4. Java中的Iterable与Iterator详解

    在Java中,我们可以对List集合进行如下几种方式的遍历: List<Integer> list = new ArrayList<>(); list.add(5); list ...

  5. Java中23种经典设计模式详解

    Java中23种设计模式目录1. 设计模式 31.1 创建型模式 41.1.1 工厂方法 41.1.2 抽象工厂 61.1.3 建造者模式 101.1.4 单态模式 131.1.5 原型模式 151. ...

  6. Java中的多线程技术全面详解

    本文主要从整体上介绍Java中的多线程技术,对于一些重要的基础概念会进行相对详细的介绍,若有叙述不清晰或是不正确的地方,希望大家指出,谢谢大家:) 为什么使用多线程 并发与并行 我们知道,在单核机器上 ...

  7. JAVA中常见的阻塞队列详解

    在之前的线程池的介绍中我们看到了很多阻塞队列,这篇文章我们主要来说说阻塞队列的事. 阻塞队列也就是 BlockingQueue ,这个类是一个接 口,同时继承了 Queue 接口,这两个接口都是在JD ...

  8. java中ReentrantLock核心源码详解

    ReentrantLock简介 ReentrantLock是一个可重入且独占式的锁,它具有与使用synchronized监视器锁相同的基本行为和语义,但与synchronized关键字相比,它更灵活. ...

  9. java中Map及Map.Entry详解

    Map是java中的接口,Map.Entry是Map的一个内部接口. Map提供了一些常用方法,如keySet().entrySet()等方法. keySet()方法返回值是Map中key值的集合:e ...

  10. 关于Java中进程和线程的详解

    一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...

随机推荐

  1. node版本管理工具nvm的安装及使用

    一.什么是nvm nvm是一个node版本管理工具. 由于不同项目依赖的node版本可能不同,所以在维护多个项目时通常需要使用不同的node版本,这时候用nvm来切换不同的node版本就很方便. 官方 ...

  2. django学习第七天---创建多表结构,创建第三张表的三种方式,创建模型类时的一些元信息配置,多表增加

    图书管理系统作业知识点整理 知识点1: print(request.POST.dict())#dict()方法能将QueryDict类型数据转换为普通字典类型数据 传数据时,可以用**{}打散的方式来 ...

  3. go-ini解析ini文件

    文档 https://github.com/go-ini/ini https://ini.unknwon.io/docs/intro/getting_started go get -u gopkg.i ...

  4. 手动下载sdk及avd

    有时候下载sdk的时候报各种错误导致无法下载,如图 那么可以离线下载,到浏览器或IDM中下载图中提示的url链接,将第一个下载的包即sources的解压后放到SDK目录下的sources目录,并重命名 ...

  5. 『Echarts』基本使用

    一.前言 本篇文章是『Echarts』文章的第 2 篇,主要介绍『Echarts』基本使用 在『Echarts』第 1 篇文章中,我们介绍了 Echarts 的概述及其强大的数据可视化功能.本篇将继续 ...

  6. 彩虹猫IDA分析记录

    目录 彩虹猫分析 概述 无参启动 带/main参数启动 带/watchdog参数启动 MBR引导程序和动画程序 第一段 引导代码 第二段 动画代码 其他函数 扭曲桌面 扰乱鼠标 钩子函数 桌面绘制图标 ...

  7. GaussDB(DWS)运维利刃:TopSQL工具解析

    本文分享自华为云社区<GaussDB(DWS)运维利刃:TopSQL工具解析>,作者:胡辣汤. 在生产环境中,难免会面临查询语句出现异常中断.阻塞时间长等突发问题,如果没能及时记录信息,事 ...

  8. RC4Drop算法的工作原理揭秘:加密技术的进步之路

    RC4Drop算法起源: RC4Drop算法是RC4算法的一种改进版本,旨在解决RC4算法在长时间加密过程中可能出现的密钥流偏置问题.RC4算法由Ron Rivest于1987年设计,是一种流密码算法 ...

  9. powershell 输入命令 不执行 保留输入内容 Ctrl + C

    为什么 powershell 输入命令 不执行 保留输入内容 Ctrl + C 为了解释某些命令,但是不执行 比如 我说 dc命令就是 xxxxxxx 我就先输入 xxxxxxxx然后ctrl + c ...

  10. thinkphp phpstorm xdebug 环境配置

    php5.6 环境配置 phpStudy 开启 Apache 网站 的php版本选择7的 (7的可能自己需要装一下) 获取xdebug前的 检查准备 打开 http://localhost:8033/ ...