内部类可以是静态(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. python容器类型字典的操作

    字典(dict):由大括号进行描述一组键值对,其键值对之间使用冒号隔开,键值对与键值对之间使用逗号隔开: 注意:字典的key可以为数字,但是不可以重复,因为key是唯一标识符: 1.声明一个字典:语法 ...

  2. 2019-9-12:渗透测试,基础学习,Linux下用户管理笔记

    linus用户管理/etc/passwd 保存用户信息/etc/shadow 保存密码信息,第二部分 !表示密码没有设置 cat /etc/passwd | grep xxx:查看特定账户信息 use ...

  3. Stream系列(四)Sorted方法使用

    排序和反向排序 EmployeeTestCase.java package com.example.demo; import lombok.Data; import lombok.ToString; ...

  4. altium designer 20.0.8

    altium designer 20.0.8 download : http://dl3.downloadly.ir/Files/Software/Altium_Designer_20.0.8_Bet ...

  5. django-formset实现数据表的批量操作

    什么是formset 我们知道forms组件是用来做表单验证,更准确一点说,forms组件是用来做数据库表中一行记录的验证.有forms组件不同,formset是同科同时验证表中的多行记录,即form ...

  6. Linux高级知识

    Linux高级知识 十一.LAMP架构 1.LAMP架构介绍.MySQL.MariaDB介绍.MySQL安装 2.MariaDB和Apache安装 3.安装PHP5和PHP7 4.Apache和PHP ...

  7. Netty学习——Netty和Protobuf的整合(一)

    Netty学习——Netty和Protobuf的整合 Protobuf作为序列化的工具,将序列化后的数据,通过Netty来进行在网络上的传输 1.将proto文件里的java包的位置修改一下,然后再执 ...

  8. Flask开发天气查询软件,带你掌握pipenv的使用与手机Termux下的部署

    关于pipenv 昨天介绍了pipenv这个相比于virtualenv更高端大气上档次的虚拟环境管理软件,但看了下流量貌似不是很受欢迎,也许是我介绍的不够好吧.那么今天就拿它做一个例子,开发一款天气预 ...

  9. SpringBoot-自动配置原理(七)

    自动配置原理 本节内容分为三个部分 配置文件的写法 分析自动配置原理 @Conditional 一. 配置文件的写法 配置文件可以写什么? 是与/META-INF/spring.factories配置 ...

  10. cf round 598div3 D.Binary String Minimizing

    题目:https://codeforces.com/contest/1256/problem/D 题意:给你长度为n的01串,能将任意两相邻字符交换k次,求最小字典序的交换结果. 思路:贪心...甚至 ...