内部类可以是静态(static)的,可以使用 public、protected 和 private 访问控制符,而外部类只能使用 public,或者默认。
成员式内部类
在外部类内部直接定义(不在方法内部或代码块内部)的类就是成员式内部类,它可以直接使用外部类的所有变量和方法,即使是 private 的。外部类要想访问内部类的成员变量和方法,则需要通过内部类的对象来获取。
public class Outer{
private int size;
public class Inner {
public void dostuff() {
size++;
}
}
public void testTheInner() {
Inner in = new Inner();
in.dostuff();
}
}

成员式内部类如同外部类的一个普通成员。

成员式内部类可以使用各种修饰符,包括 public、protected、private、static、final 和 abstract,也可以不写。

若有 static 修饰符,就为类级,否则为对象级。类级可以通过外部类直接访问,对象级需要先生成外部的对象后才能访问。

非静态内部类中不能声明任何 static 成员。

内部类可以相互调用,例如:

class A {
// B、C 间可以互相调用
class B {}
class C {}
}

成员式内部类的访问
内部类的对象以成员变量的方式记录其所依赖的外层类对象的引用,因而可以找到该外层类对象并访问其成员。该成员变量是系统自动为非 static 的内部类添加的,名称约定为“outClassName.this”。

  1. 使用内部类中定义的非静态变量和方法时,要先创建外部类的对象,再由“outObjectName.new”操作符创建内部类的对象,再调用内部类的方法,如下所示:
public class Demo{
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.dostuff();
}
}
class Outer{
private int size;
class Inner{
public void dostuff() {
size++;
}
}
}
  1. static 内部类相当于其外部类的 static 成员,它的对象与外部类对象间不存在依赖关系,因此可直接创建。示例如下:
public class Demo{
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
inner.dostuff();
}
} class Outer{
private static int size;
static class Inner {
public void dostuff() {
size++;
System.out.println("size=" + size);
}
}
}

运行结果:

  1. 由于内部类可以直接访问其外部类的成分,因此当内部类与其外部类中存在同名属性或方法时,也将导致命名冲突。所以在多层调用时要指明,如下所示:
public class Outer{
private int size;
public class Inner{
private int size;
public void dostuff(int size){
size++; // 局部变量 size;
this.size; // 内部类的 size
Outer.this.size++; // 外部类的 size
}
}
}

局部内部类
局部内部类(Local class)是定义在代码块中的类。它们只在定义它们的代码块中是可见的。

局部类有几个重要特性:
仅在定义了它们的代码块中是可见的;
可以使用定义它们的代码块中的任何局部 final 变量;
局部类不可以是 static 的,里边也不能定义 static 成员;
局部类不可以用 public、private、protected 修饰,只能使用缺省的;
局部类可以是 abstract 的。

请看下面的代码:

public class Outer {
public static final int TOTAL_NUMBER = 5;
public int id = 123;
public void func() {
final int age = 15;
String str = "http://www.weixueyuan.net";
class Inner {
public void innerTest() {
System.out.println(TOTAL_NUMBER);
System.out.println(id);
// System.out.println(str);不合法,只能访问本地方法的final变量
System.out.println(age);
}
}
new Inner().innerTest();
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.func();
}
}

运行结果:

匿名内部类
匿名内部类是局部内部类的一种特殊形式,也就是没有变量名指向这个类的实例,而且具体的类实现会写在这个内部类里面。

注意:匿名类必须继承一个父类或实现一个接口。

不使用匿名内部类来实现抽象方法:

abstract class Person {
public abstract void eat();
} class Child extends Person {
public void eat() {
System.out.println("eat something");
}
} public class Demo {
public static void main(String[] args) {
Person p = new Child();
p.eat();
}
}

运行结果:

可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用。但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

这个时候就引入了匿名内部类。使用匿名内部类实现:

abstract class Person {
public abstract void eat();
} public class Demo {
public static void main(String[] args){ // 继承 Person 类
new Person() {
public void eat() {
System.out.println("eat something");
}
}.eat();
}
}

运行结果:

可以看到,匿名类继承了 Person 类并在大括号中实现了抽象类的方法。

内部类的语法比较复杂,实际开发中也较少用到,并不打算进行深入讲解,各位读者也不应该将内部类作为学习Java的重点。

参考:https://www.jianshu.com/p/ed3f8b0f0471

《Java基础知识》Java静态内部类、匿名内部类、成员式内部类和局部内部类的更多相关文章

  1. Java知多少(37)静态内部类、匿名内部类、成员式内部类和局部内部类

    内部类可以是静态(static)的,可以使用 public.protected 和 private 访问控制符,而外部类只能使用 public,或者默认. 成员式内部类 在外部类内部直接定义(不在方法 ...

  2. JAVA基础知识|java虚拟机(JVM)

    一.JVM简介 java语言是跨平台的,兼容各种操作系统.实现跨平台的基石就是虚拟机(JVM),虚拟机不是跨平台的,所以不同的操作系统需要安装不同的jdk版本(jre=jvm+类库:jdk=jre+开 ...

  3. java基础知识——Java的定义,特点和技术平台

    (作者声明:对于Java编程语言,很多人只知道怎么用,却对其了解甚少.我也是其中一员.所以菜鸟的我,去查询了教科书以及大神的总结,主要参考了<Java核心技术>这本神作.现在分享给大家!) ...

  4. [java基础知识]java安装步骤

    jre:  java运行环境.  jre =  java虚拟机 + 核心类库(辅助java虚拟机运行的文件).如果只是运行java程序,只需要安装jre.    jdk: java开发工具集   jd ...

  5. Java基础知识笔记第七章:内部类和异常类

    内部类 /* *Java支持在一个类中定义另一个类,这样的类称为内部类,而包含内部类的类称为内部类的外嵌类 */ 重要关系: /* *1.内部类的外嵌类在内部类中仍然有效,内部类的方法也可以外嵌类的方 ...

  6. java 基础知识(java web 方面的)

    1.java面向对象的基本特征:封装性,多态性,继承性. 2.Java的泛型:iterator接口主要有hasnext()方法,next()方法,remove()方法:collection接口继承了i ...

  7. [转] Java基础知识——Java语言基础

    http://blog.csdn.net/loneswordman/article/details/9905931 http://blog.csdn.net/wanghuan203/article/d ...

  8. 《Java基础知识》Java技术总结

    1. Java 知识点总结 Java标示符.保留字和数制:https://www.cnblogs.com/jssj/p/11114041.html Java数据类型以及变量的定义:https://ww ...

  9. java基础知识精华

    转载:https://www.jianshu.com/p/6c078abb720f java基础知识 java内存模型 java运行时数据区域 hashMap 如何解决冲突 存储方式 冲突达到一定数量 ...

随机推荐

  1. 原创|我是如何从零学习开发一款跨平台桌面软件的(Markdown编辑器)

    原始冲动 最近一直在学习 Electron 开发桌面应用程序,目的是想做一个桌面编辑器,虽然一直在使用Typore这款神器,但无奈Typore太过国际化,在国内水土不服,无法满足我的一些需求. 比如实 ...

  2. python selenium框架的Xpath定位元素

    我们工作中经常用到的定位方式有八大种:id name class_name tag_name link_text partial_link_text xpath css_selector 本篇内容主要 ...

  3. Python 并发总结,多线程,多进程,异步IO

    1 测量函数运行时间 import time def profile(func): def wrapper(*args, **kwargs): import time start = time.tim ...

  4. Linux 7开机自启项查看并设置

      在Linux6中查看及设置开机自启信息是使用chkconfig命令,Linux7中此命令已经被替代,接下来我们就来研究下Linux7中的区别所在. chkconfig --list Note: T ...

  5. vi指令详解

    ★ vi的模式(命令模式.插入模式.ex模式) 1)命令模式: 在我们刚刚通过vi新建或打开一个已经存在的文件时,首先默认被读取的模式就是“命令模式”,命令模式的特征就是,在编辑器窗口左下角的位置上没 ...

  6. python的匿名函数

    在Python,有两种函数,一种是def定义,一种是lambda函数. lambda函数是Python一种生成函数对象的表达式形式.匿名函数通常是创建了可以被调用的函数,它返回了函数,而并没有将这个函 ...

  7. .net压缩文件

    首先nuget安装DotNetZip 代码很少

  8. FaceBook的秘钥散列获取

    随笔记录 先下载OpenSSL工具 在C盘创建一个openssl,将下好的OpenSSL工具解压到这里 将你的 .keystore文件复制到JAVA JDK 文件夹的bin目录里面(C:\Progra ...

  9. Xtrabackup 全备和还原以及增量备份和还原

    目录 MySQL环境介绍 全备和还原 准备备份目录 创建测试数据 全量备份 模拟删除数据 还原数据操作 第一步 备份备份文件 第二步 关闭数据库 第三步 移除数据库的data目录 第四步 恢复前准备 ...

  10. Docker部署Mysql集群

    单节点数据库的弊病 大型互联网程序用户群体庞大,所以架构必须要特殊设计 单节点的数据库无法满足性能上的要求 单节点的数据库没有冗余设计,无法满足高可用 单节点MySQL的性能瓶领颈 2016年春节微信 ...