深入解析Java中的内部类

 更新时间:2015年07月29日 09:49:34   作者:低调小一  
这篇文章主要介绍了Java中的内部类,是Java入门学习中的基础知识,需要的朋友可以参考下

Java技术迷

概述

最近学习python,发现python是支持多继承的,这让我想起Java是通过内部类实现的这套机制。这篇文章不是讲如何通过内部类实现多继承,而是总结一下内部类的类型和使用方法。

Java内部类分为:

  •     非静态内部类
  •     静态内部类
  •     局部内部类
  •     匿名内部类

内部类在Android源码中被大量的使用,先介绍一下这四种内部类的共同点:

  •     内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
  •     内部类不能用普通的方式访问。内部类是外部类的一个成员,因为内部类可以自由的访问外部类的成员,包括private成员。
  •     内部类声明为静态的,就不能随意的访问外部类的成员变量了,此时内部类只能访问到外部类的静态成员变量。

接下来,分别介绍一下这几种内部类。
非静态内部类

当一个类作为另一个类的非静态成员时,则这个类就是一个非静态内部类。
创建非静态内部类的示例代码如下:

class OutClass {
 class InnerClass {}
}

当我们用javac去编译的时候,发现生成了两个.class文件:OutClass.class和OutClass$InnerClass.class。如下图所示:

201572994546125.jpg (603×85)

从外部类的非静态方法中实例化内部类

在外部类中访问内部类是很容易的,直接创建内部类对象,然后通过对象实例调用类内的方法即可。示例代码如下:

public class OutClass {
 private static int a = 0;

 public void makeInner() {
  InnerClass inClass = new InnerClass();
  inClass.seeOuter();
 }

 public static void main(String[] args) {
  OutClass oClass = new OutClass();
  oClass.makeInner();
 }

 class InnerClass {
  public void seeOuter() {
   System.out.println(a);
   a++;
  }
 }
}


运行结果如下:
0

从外部类的静态方法中实例化内部类

在外部类中访问内部类是比较简单的,可以直接new出内部类对象,但是如果想在外部类的外部使用内部类,接不能直接new内部类名的方式了,而是需要如下方式:

OutClass.InnerClass innerClass = new OutClass().new InnerClass();

也就是说,在外部调用非静态内部类,需要先实例化外部类,然后通过外部类对象再去实例化内部类。示例代码如下:

public class OutClass {
 private static int a = 0;

 public void makeInner() {
  InnerClass inClass = new InnerClass();
  inClass.seeOuter();
 }

 public static void main(String[] args) {
  OutClass oClass = new OutClass();
  oClass.makeInner();

  OutClass.InnerClass innerClass = new OutClass().new InnerClass();
  innerClass.seeOuter();
 }

 class InnerClass {
  public void seeOuter() {
   System.out.println(a);
   a++;
  }
 }
}

运行结果:

0
1

内部类的this引用

普通的类可以使用this引用当前的对象,内部类也是如此。但是假若内部类想引用外部类当前的对象呢?可以使用如下方式:

外部类名.this

示例代码如下:

public class OutClass {
 private static int a = 0;

 public void makeInner() {
  InnerClass inClass = new InnerClass();
  inClass.seeOuter();
 }

 public static void main(String[] args) {
  OutClass oClass = new OutClass();
  oClass.makeInner();

  OutClass.InnerClass innerClass = new OutClass().new InnerClass();
  innerClass.seeOuter();
 }

 class InnerClass {
  public void seeOuter() {
   System.out.println(this);
   System.out.println(OutClass.this);
  }
 }
}


静态内部类

上面介绍了非静态内部类,接下来我们学习神马是静态内部类。

静态内部类就是在外部类中扮演一个静态成员的角色,创建静态内部类和创建非静态内部类的形式很相似,只是class前面多了一个static修饰符。

    注意,外部类是不可能使用static修饰符进行修饰的。

示例代码如下:

class OutClass {
 static class InnerClass {
 }
}


用javac命令编译一下,可以看到一样都是有两个.class文件,如下图所示:

201572994701880.jpg (583×69)

从外部类的非静态方法中实例化静态内部类

从外部类中访问静态内部类,和在外部类中访问非静态内部类是一样的。但是,需要注意一点,此时静态内部类只能访问外部类的静态成员,无法访问非静态成员了。

示例代码如下:

public class OutClass {
 private static int a = 0;
 private int b = 1;

 public void makeInner() {
  InnerClass inClass = new InnerClass();
  inClass.seeOuter();
 }

 public static void main(String[] args) {
  OutClass oClass = new OutClass();
  oClass.makeInner();

 }

 static class InnerClass {
  public void seeOuter() {
   System.out.println(this);
   System.out.println(a);
   // System.out.println(b);
  }
 }
}


执行结果如下:

OutClass$InnerClass@79a340
0


从外部类静态方法中实例化静态内部类

    注意:
    因为静态内部类是外部类的静态成员,而静态成员是跟类绑定,而不是跟类实例化的对象绑定。所以,在外部类的静态方法中实例化内部类,是不需要先实例化外部类的。

示例代码如下:

public class OutClass {
 private static int a = 0;
 private int b = 1;

 public void makeInner() {
  InnerClass inClass = new InnerClass();
  inClass.seeOuter();
 }

 public static void main(String[] args) {
  OutClass oClass = new OutClass();
  oClass.makeInner();

  OutClass.InnerClass inClass = new OutClass.InnerClass();
  inClass.seeOuter();
 }

 static class InnerClass {
  public void seeOuter() {
   System.out.println(this);
   System.out.println(a);
   // System.out.println(b);
  }
 }
}

匿名内部类

匿名内部类在Android应用开发中简直是泛滥,各种listener对象的实现很多都是通过匿名内部类。

匿名内部类从名字上就可以知道这是代表没有类名的内部类,通常用来简化代码。

相信写Java的同学都使用过线程,那Thread的时候我们可以传一个Runnable对象,也可以传一个匿名内部类。示例代码如下:

public class OutClass {
 public void testAnonymousClass() {
  Thread t = new Thread(new Runnable() {

   @Override
   public void run() {
    for (int i = 0; i < 10; i ++) {
     System.out.println(i);
     try {
      Thread.sleep(500);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
   }
  });
  t.start();

  System.out.println("another thread is running...");
 }

 public static void main(String[] args) {
  OutClass oClass = new OutClass();
  oClass.testAnonymousClass();
 }
}

执行结果如下:

another thread is running...

蓄力AI

微信公众号搜索 “ 脚本之家 ” ,选择关注

程序猿的那些事、送书等活动等着你

相关文章

  • Graceful Response 构建 Spring Boot 响应处理的方法

    Graceful Response 构建 Spring Boot 响应

    Graceful Response是一个Spring Boot技术栈下的优雅响应处理器,提供一站式统一返回值封装、全局异常处理、自定义异常错误码等功能,本文介绍Graceful Response 构建 Spring Boot 下优雅的响应处理,感兴趣的朋友一起看看吧
    2024-01-01
  • SpringMVC配置与使用详细介绍

    SpringMVC配置与使用详细介绍

    Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内配合
    2022-07-07
  • java 线程公平锁与非公平锁详解及实例代码

    java 线程公平锁与非公平锁详解及实例代码

    这篇文章主要介绍了java 线程公平锁与非公平锁详解及实例代码的相关资料,需要的朋友可以参考下
    2017-02-02
  • Spring boot 使用JdbcTemplate访问数据库

    Spring boot 使用JdbcTemplate访问数据库

    SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物。本文重点给大家介绍spring boot 使用JdbcTemplate访问数据库,需要的朋友可以参考下
    2018-05-05
  • MyBatis中的collection两种使用方法及效率比较

    MyBatis中的collection两种使用方法及效率比较

    collection主要是应对表关系是一对多的情况,本文主要介绍了MyBatis中的collection两种使用方法及效率比较,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Spring中的自动装配机制详解

    Spring中的自动装配机制详解

    这篇文章主要介绍了Spring中的自动装配机制详解,自动装配就是会通过Spring的上下文为你找出相应依赖项的类,通俗的说就是Spring会在上下文中自动查找,并自动给Bean装配与其相关的属性,需要的朋友可以参考下
    2023-08-08
  • java中的IO流

    java中的IO流

    这篇文章主要介绍了java中的IO流的相关资料,需要的朋友可以参考下文
    2021-08-08
  • Netty与NIO超详细讲解

    Netty与NIO超详细讲解

    Netty本质上是一个NIO的框架,适用于服务器通讯相关的多种应用场景。底层是NIO,NIO底层是Java IO和网络IO,再往下是TCP/IP协议,下面我们跟随文章来详细了解
    2022-08-08
  • JDBC如何获取数据库连接

    JDBC如何获取数据库连接

    这篇文章主要为大家详细为大家详细介绍了JDBC如何获取数据库连接,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • Java协程编程之Loom

    Java协程编程之Loom

    这篇文章主要介绍了Java协程编程Loom的方法,需要的朋友请看下文
    2021-08-08

最新评论