Java内部类初探

Java内部类初探

之前对内部类的概念不太清晰,在此对内部类与外部类之间的关系以及它们之间的调用方式进行一个总结。

Java内部类一般可以分为以下三种:

  • 成员内部类
  • 静态内部类
  • 匿名内部类

一、成员内部类

  • 内部类的创建:成员内部类的创建需要依赖于外部类对象,没有创建外部类实例之前无法创建成员内部类对象 若在main函数中直接创建成员内部类则会报错:
MemberInner memberInner = new MemberInner();
  • 私有属性访问:成员内部类可直接访问外部类非静态私有属性,外部类访问内部类私有属性则需要通过内部类的对象来访问 在 memberInnerTest()方法中,可以直接访问外部类中的私有 test字段,若内部类中有与外部类同名字段,调用外部类需要使用如下方法:
OuterTest.this.test
  • 创建内部类:
  • 在外部类内部创建内部类对象:使用new关键字创建内部类对象
private void createMemberInner(){
    MemberInner memberInner = new MemberInner();
    memberInner.memberInnerTest();
}
  • 在外部类外部创建内部类对象:需要先创建外部类对象,再通过外部类创建内部类
OuterTest outerTest = new OuterTest();
MemberInner memberInner = outerTest.new MemberInner();

若不需要使用外部类,可以使用如下方式创建内部类

MemberInner memberInner = new OuterTest().new MemberInner();

使用该方法创建内部类需要注意:若外部类中有多个内部类,这种方法会 new出多个外部类对象,各个类对象都是独立的,因此外部类的成员变量并不会在内部类中共享。 如下代码中,由于new出了两个 OuterVar类,所以 InnerOneInnerTwo类输出的成员变量 var均为0。若想 InnerOneInnerTwo类共享成员变量 var,则需用如下方式创建:

  OuterVar outerVar = new OuterVar();
  InnerOne innerOne = outerVar.new InnerOne();
  InnerTwo innerTwo = outerVar.new InnerTwo();
public class OuterVar {
private int var = 0;

class InnerOne{
  private void innerOnePrint(){
      System.out.println("innerOnePrint:"+var);
      var+=1;
  }
}

class InnerTwo{
  private void innerTwoPrint(){
      System.out.println("innerTwoPrint:"+var);
  }
}

public static void main(String[] args) {
  InnerOne innerOne = new OuterVar().new InnerOne();
  InnerTwo innerTwo = new OuterVar().new InnerTwo();

  innerOne.innerOnePrint();
  innerTwo.innerTwoPrint();
}
}
/* 结果
innerOnePrint:0
innerTwoPrint:0
*/
/*1、成员内部类
  2、静态内部类
  3、匿名内部类
*/
public class OuterTest {
    /*
    1、成员内部类
     */
    private String test = "OuterTest";

    private void createMemberInner(){
        MemberInner memberInner = new MemberInner();
        memberInner.memberInnerTest();
    }

    class MemberInner{
        private String test = "MemberInnerTest";

        public void memberInnerTest(){
            System.out.println("MemberInner");
            System.out.println(test);
            System.out.println(OuterTest.this.test);

        }
    }

    public static void main(String[] args) {
        // 成员内部类
        OuterTest outerTest = new OuterTest();
        MemberInner memberInner = outerTest.new MemberInner();
//        MemberInner memberInner = new OuterTest().new MemberInner();

        memberInner.memberInnerTest();
    }
}

/* 结果
   MemberInner
   MemberInnerTest
   OuterTest */

二、静态内部类

静态内部类定义在外部类的内部,使用static关键字修饰,静态内部类不需要外部类对象产生就能使用,不能访问外部类的成员域,但能访问静态域。

  • 私有属性访问:静态内部类不可直接访问外部类的非静态属性
  • 创建内部类:
  • 在外部类内部创建内部类对象:使用new关键字创建内部类对象
private void createStaticInner(){
    StaticInner staticInner = new StaticInner();
    staticInner.staticInnerTest();
}
  • 在外部类外部创建内部类对象:可以不创建外部类对象,直接创建内部类对象
StaticInner staticInner = new StaticInner();
public class OuterTest {
    /*
      2、静态内部类
     */
    private String test = "OuterTest";

    private void createStaticInner(){
        StaticInner staticInner = new StaticInner();
        staticInner.staticInnerTest();
    }

    static class StaticInner{
        private String test = "StaticInnerTest";

        public void staticInnerTest(){
            System.out.println("StaticInner");
            System.out.println(test);
        }
    }

    public static void main(String[] args) {
        // 静态内部类
        StaticInner staticInner = new StaticInner();
        staticInner.staticInnerTest();
    }
}

/* 结果
   StaticInner
   StaticInnerTest */

三、匿名内部类

使用匿名内部类的前提条件:必须继承一个父类或实现一个接口。 有以下一些特点:

  • 由于匿名内部类是没有类名,所以匿名内部类不能有构造方法
  • 匿名内部类不能定义任何静态成员、方法和类
//匿名内部类
interface Father{
    public abstract void talk();

    public abstract void eat();
}
public class Test {
    public static void main(String[] args) {
        //匿名内部类
        Father father = new Father() {
            @Override
            public void talk() {
                System.out.println("I'm Father");
            }

            @Override
            public void eat() {
                System.out.println("I'm eating");
            }
        };
        father.talk();
        father.eat();
    }
}

/* 结果
   I'm Father
   I'm eating */

Original: https://www.cnblogs.com/lovekey/p/16721034.html
Author: lovekey
Title: Java内部类初探

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/589100/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 经典实验–网络聊天室(NetChatRoom)3

    ·方法声明 Chatter package chat; import java.rmi.RemoteException; public interface Chatter exte…

    Java 2023年6月15日
    093
  • ArrayList扩容代码分析

    ArrayList扩容机制是在面试中频繁出现的问题,平时了解的比较含糊,特此记录! 注意:每次发生扩容,其容量扩充为原来的1.5倍 左右 add方法 public boolean …

    Java 2023年6月15日
    085
  • Java中Comparable讲解

    Comparable是排序接口;若一个类实现了Comparable接口,就意味着”该类支持排序”。可以使用Arrays.sort()对改类进行排序。 讲解 …

    Java 2023年5月29日
    074
  • Nginx服务加到systemctl

    当我们编译安装nginx服务后,可以用手执行启动脚本也可以作为服务的形式运行。 添加启动文件:vim /usr/lib/systemd/system/nginx.service c…

    Java 2023年5月30日
    073
  • 与socket相关的流

    我看先看一下通过socket取得的流的运行类型 InputStream inputStream = socket.getInputStream(); 可以看到是SocketInpu…

    Java 2023年6月5日
    087
  • 喜讯!云效度量能力获信通院先进级评估

    6月16日-17日,由中国信息通信研究院(以下简称”中国信通院”)主办的2022精益软件工程大会以线上形式成功举行。会上,中国信通院云大所所长何宝宏公布了软…

    Java 2023年6月8日
    089
  • 使用ImpromptuInterface反射库方便的创建自定义DfaGraphWriter

    在本文中,我为创建的自定义的 DfaGraphWriter实现奠定了基础。 DfaGraphWriter是公开的,因此您可以如上一篇文章中所示在应用程序中使用它,但它 _使用的_所…

    Java 2023年5月30日
    069
  • 我自定义的拦截器为什么会靠后执行?

    背景 模拟场景 是不是因为 order的值 找出在哪里赋予的 order值 解决办法 背景 项目中自定义了拦截器 Filter,项目中使用了 spring security,它也有…

    Java 2023年6月8日
    086
  • IntelliJ IDEA正版一年多少钱?

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年5月29日
    085
  • Spring 拦截器

    拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行 作用: 在指定的方法调用前后执行预先设定的代码 阻止原始方法的执行 总…

    Java 2023年6月7日
    074
  • Java HashMap深入理解增删改查 源码学习 学习笔记

    Java源码解读(三)— HashMap深入理解之增删查改 学习地址:[HashMap深入理解之增删查改]: https://blog.csdn.net/dongmuyang/ar…

    Java 2023年6月5日
    0121
  • 如何解决java.sql.SQLException: Column ‘ XXX ‘ not found

    在我们编写代码时,可能会遇到这种报错,报错的意思是找不到列XXX(questionId). 出现这种报错的可能原因有三个: 1.数据库表里缺少XXX(questionId)这一列….

    Java 2023年6月8日
    099
  • 配置SSH无秘钥登录

    [hadoop@hadoop01 ~]$ cd .ssh[hadoop@hadoop01 .ssh]$ ll -d ./  #查看.ssh文件夹的权限drwx——. 2 h…

    Java 2023年6月16日
    099
  • 3.MySQL常用知识

    1,基础查询 //1.group by+ 聚合函数+ HAVING条&…

    Java 2023年6月13日
    085
  • Fizz网关入门教程-路由初体验

    概念 路由就是定义网关如何处理请求,分反向代理、服务发现、服务编排三种类型。 配置 路由的定义可通过网关管理后台完成: 下面分别介绍反向代理和服务发现路由的配置,设网关部署为 1….

    Java 2023年6月9日
    081
  • (转发)Debian GNU/Linux 11.1 安装

    Debian GNU/Linux 是 Linux 发行版之一,也是众多 Linux 发行版的上游系统,下游Linux 发行版,比如 Ubuntu,可视为 Debian 的改动款。当…

    Java 2023年6月9日
    0113
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球