Java基础教程:内部类

内部类

  内部类,是指在一个类的内部定义的类。就像下面这样:

public class EnclosingClass {
  . . .
  public class NestedClass {
  . . .
 
  }
}

  内部类拥有访问外部类所有元素(包括private、static)的访问权。当某个外部类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用。然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员。

  内部类是个编译时的概念,一旦编译成功后,它就与外围类属于两个完全不同的类(当然他们之间还是有联系的)。对于一个名为OuterClass的外围类和一个名为InnerClass的内部类,在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$InnerClass.class。

  

使用.this和.new

  如果你需要在内部类中生成对外部类对象的引用,可以在外部类的名字后面紧跟圆点和this。

public class EnclosingClass {

    public class NestedClass {
EnclosingClass getOuterClass(){
return EnclosingClass.this;
}
} }

  如果我们需要创建某个内部类对象,必须要利用外部类的对象通过.new来创建内部类

public class EnclosingClass {

    public class NestedClass {
EnclosingClass getOuterClass(){
return EnclosingClass.this;
}
} public static void main(String[] args) {
EnclosingClass outerClass = new EnclosingClass();
EnclosingClass.NestedClass innerClass = outerClass.new NestedClass();
}
}

局部内部类

  局部内部类指的是在方法、构造器、初始化块中声明的类,在结构上类似一个局部变量。因此局部内部类时不能使用访问修饰符的。

public class OuterClass {
static int a = 10;
int b =10;
//静态域中的局部内部类
static {
class LocalClass1{
int val = a; //定义在静态环境中的内部类,只能访问外部类的静态成员
}
}
//实例初始化块中的局部内部类
{
class LocalClass2{
int val = a; //定义在实例环境中的内部类,可以访问外部类的所有成员
int num = b;
}
}
//构造器中的局部内部类
public OuterClass(){
class LocalClass3{ }
}
//方法中的局部内部类
public void test(){
class LocalClass4{}
}
}

匿名内部类

  匿名内部类与局部内部类很相似,只不过匿名内部类是一个没有给定名字的内部类,在创建这个匿名内部类后,便会立即用来创建并返回此内部类的一个对象引用。

  匿名内部类只能继承一个类或实现一个接口,不能再继承其他类或其他接口。只能用于创建一次对象实例。

class MyOuterClass {
private int x = 5;
void createThread() {
final int a = 10;
int b = 189;
// 匿名内部类继承Thread类,并重写Run方法
Thread thread = new Thread("thread-1") {
int c = x; //访问成员变量
int d = a; //final的局部变量
int e = b; //访问没有用final修饰的局部变量
@Override
public void run() {
System.out.println("这是线程thread-1");
}
};
// 匿名内部类实现Runnable接口
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("线程运行中");
}
};
}
}

嵌套类

  如果不需要内部类对象与其外围类对象之间有联系,可以将内部类声明为static。这通常称为嵌套类。普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象。嵌套类因为是static,所以不依赖于外围类对象实例而独立存在,嵌套类的可以访问外围类中的所有静态成员,包括private的静态成员,但是它不能使用任何外围类的非static成员变量和方法

public class EnclosingClass {
private static Integer num = 10;
private Integer num1 = 20; static class staticClass{
public void test(){
System.out.println(num); //OK
System.out.println(num1); //ERROR
}
}
  public static void main(String[] args) {
  EnclosingClass.StaticClass staticClass = new EnclosingClass.StaticClass();
  }
}

  同时,嵌套类是所有内部类中独立性最高的,其创建对象、继承(实现接口)、扩展子类等方式与外部类没有多大区别。

参考链接

Java基础教程:内部类的更多相关文章

  1. Java基础教程——内部类

    内部类 内部类(inner class)是定义在另一个类中的类 内部类的好处: |--1.隐藏机制:内部类封装性更好,隐藏在一个类之中,同一包中的其他类也不能访问 |--2.内部类可以访问外围类的私有 ...

  2. Java基础教程(12)--深入理解类

    一.方法的返回值   当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...

  3. Java基础教程(18)--继承

    一.继承的概念   继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...

  4. Java基础教程:注解

    Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...

  5. Java基础教程:网络编程

    Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...

  6. Java基础教程(5)--变量

    一.变量 1.变量的定义   正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...

  7. Java基础教程:Lambda表达式

    Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...

  8. Java基础教程:泛型基础

    Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...

  9. Java基础教程:多线程基础(1)——基础操作

    Java:多线程基础(1) 实现多线程的两种方式 1.继承Thread类 public class myThread extends Thread { /** * 继承Thread类,重写RUN方法. ...

随机推荐

  1. MySQL分区表 非分区索引 无法使用

    在<高性能Mysql>这本书的‘如何使用分区’这一小章中,列举的常见问题中,有以下一个问题: 分区列和索引列不匹配 如果定义的索引列和分区列不匹配,会导致查询无法进行分区过滤.假设在列a上 ...

  2. IntelliJ IDEA 2017 MySQL5 绿色版 Spring 4 Mybatis 3 配置步骤详解(二)

    前言    继续上一篇安装教程 首先是MySQL绿色版安装之后其他组件安装,如果篇幅较长会分为多篇深入讲解,随笔属于学习笔记诸多错误还望指出 共同学习. MySQL 5.7 绿色版   我本地安装的是 ...

  3. 模板 - 数学 - 数论 - Min_25筛

    终于知道发明者的正确的名字了,是Min_25,这个筛法速度为亚线性的\(O(\frac{n^{\frac{3}{4}}}{\log x})\),用于求解具有下面性质的积性函数的前缀和: 在 \(p\) ...

  4. Java SpringBoot 实体类数据自动验证

    package demo.dto; import org.hibernate.validator.constraints.Length; import javax.validation.constra ...

  5. js中的那些遍历

    说到遍历,首先想到的是数组的遍历,方法不要太多,比如 for, forEach,map,filter,every,some等 下面来看下,用法 首先 定义一个数组: 1. for循环,需要知道数组的长 ...

  6. 深度学习面试题09:一维卷积(Full卷积、Same卷积、Valid卷积、带深度的一维卷积)

    目录 一维Full卷积 一维Same卷积 一维Valid卷积 三种卷积类型的关系 具备深度的一维卷积 具备深度的张量与多个卷积核的卷积 参考资料 一维卷积通常有三种类型:full卷积.same卷积和v ...

  7. [转]重命名PostgreSQL数据库

    初学PostgreSQL的朋友可能会有这样的疑惑:如何重命名已经建好的数据库?因为PostgreSQL默认的客户端pgAdmin III并没有地方可以让我们去修改某个现有的数据库的名称.遇到这个情况, ...

  8. PostgreSQL 增量备份详解以及相关示例

    PostgreSQL 没有类似MySQL 的二进制日志, 但是有和MySQL 类似的REDO LOG,并且有MySQL 没有的REDO 归档功能.当然REDO 的归档已经MariaDB 和Percon ...

  9. HttpWebRequest Timeout

    随着REST风格的流行,直接通过 HttpWebRequest 进行服务调用的客户端应用越来越多.这里总结一些可能需要费时调查的经验,希望能帮助大家. 1. 用完的HttpWebRequest要Abo ...

  10. 手写HashMap实践

    1.什么是HashMap 2.源码分析 3.手写实现 4.不足 一.什么是HashMap hash散列 将一个任意长度通过某种算法(hash函数算法)换成一个固定值 map: 地图x,y 存储 总结: ...