Java内部类(成员内部类、局部内部类、静态内部类、匿名内部类)

news2024/11/25 21:34:27

目录

①. 什么是内部类

 ②. 内部类的共性

③. 为什么需要内部类

④. 成员内部类

⑤. 局部内部类

⑥. 静态内部类(嵌套类)

⑦. 匿名内部类

①. 什么是内部类

内部类是指在一个外部类的内部再定义一个类。内部类作为外部类的一个成员,并且依附于外部类而存在的。内部类可为静态,可用protected和private修饰(而外部类只能使用public和缺省的包访问权限)。

   内部类主要有一下几种:成员内部类、局部内部类、静态内部类、匿名内部类

 ②. 内部类的共性

  1. 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
  2. 内部类不能用普通的方式访问。
  3. 内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。
  4. 外部类不能直接访问内部类的的成员,但可以通过内部类对象来访问

③. 为什么需要内部类

其主要原因有以下几点:

  1. 内部类方法可以访问该类定义所在的作用域的数据,包括私有的数据
  2. 内部类可以对同一个包中的其他类隐藏起来,一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
  3. 可以实现多重继承
  4. 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷

使用内部类最吸引人的原因是:

  每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。大家都知道Java只能继承一个类,它的多重继承在我们没有学习内部类之前是用接口来实现的。但使用接口有时候有很多不方便的地方。比如我们实现一个接口就必须实现它里面的所有方法。而有了内部类就不一样了。它可以使我们的类继承多个具体类或抽象类。

④. 成员内部类

        即在一个类中直接定义的内部类,成员内部类与普通类的成员没什么区别,可以与普通成员一样进行修饰和限制。成员内部类不能含有static的变量和方法。

package com.songqiao;
//成员内部类,在类中的类
public class MemberInnerClass {

    private Integer id=1;

    private static void staticMethod(){
        System.out.println("外部类的static方法被调用");
    }
    private void method(){
        System.out.println("外部类的普通方法被调用");
    }
    private static void staticMethodTwo(){
        //外部类静态方法访问成员内部类
        // 1、建立外部类对象
        MemberInnerClass mem=new MemberInnerClass();
        //  2、根据外部类建立内部类对象
        Inner in =mem.new Inner();
        // 1、2步简写
        // memberInner.Inner inn = new memberInner().new Inner();
        // 访问内部类方法
        in.innerMethod();
        //访问内部类字段
        System.out.println("内部类成员字段:"+in.id);
    }

    //成员内部类,可以访问外部类的所有成员
    public class Inner{
         Inner() {
            System.out.println("内部类对象被创建!");
        }
        //内部类不允许定义静态变量
        //static int demo_i = 100;
        //内部类和外部类的实例变量可以共存
        Integer id=100;
        //成员内部类中的方法定义
        void innerMethod(){
            //内部类中访问内部类自己的变量直接用变量名
            //也可以用  this.id
            System.out.println("内部类的同名变量:"+id);
            //访问同名的外部类变量
            System.out.println("外部类的同名变量:"+ MemberInnerClass.this.id);
            //内部类调用外部类方法
            staticMethod();//静态
            method();//非静态
        }
    }

    public static void main(String[] args) {
        MemberInnerClass.staticMethodTwo();
    }
}

⑤. 局部内部类

 在方法中定义的内部类称为局部内部类。与局部变量类似,局部内部类不能有访问说明符,因为它不是外围类的一部分,但是它可以访问当前代码块内的常量,和此外围类所有的成员。

需要注意的是:

  1. 局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
  2. 局部内部类对象不能使用该内部类所在方法的非final局部变量。
package com.songqiao;
//局部内部类,在方法中定义的类
public class LocalInnerClass {
    private static int number = 100;
    private int j = 20;
    private String name = "Java";

    //定义外部类方法
    public void method(int k){
        final int number=101;
        int j=50;
        //局部内部类
        class Local{
            Local(int k){
            System.out.println("有参构造创建局部内部类对象");
            localMethod();
            }
            //可以定义与外部类同名的变量
            int number=300;
            // static int j = 10;  //不可以定义静态变量
            //内部类的方法
            public void localMethod(){
                System.out.println("内部方法被调用");
                //访问外部类的变量,如果没有与内部类同名的变量,则可直接用变量名
                System.out.println(name);
                //访问外部类与内部类同名的变量
                System.out.println(LocalInnerClass.number);
                System.out.println("内部方法传入的参数为:"+k);
            }
        }
        //局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
        new Local(k);
    }

    public static void main(String[] args) {
        //访问内部类必须要先有外部类对象
        LocalInnerClass localInnerClass=new LocalInnerClass();
        localInnerClass.method(10);

    }
}

⑥. 静态内部类(嵌套类)

        如果你不需要内部类对象与其外围类对象之间有联系,那你可以将内部类声明为static。这通常称为嵌套类(nested class)。想要理解static应用于内部类时的含义,你就必须记住,普通的内部类对象隐含地保存了一个引用,指向创建它的外围类对象。然而,当内部类是static的时,就不是这样了。嵌套类意味着:

  1.  要创建嵌套类的对象,并不需要其外围类的对象
  2.  不能从嵌套类的对象中访问非静态的外围类对象。

注意:生成(new)一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成:
Outer.Inner in=new Outer.Inner();
而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类。静态内部类不可用private来进行定义。

package com.songqiao;
//静态内部类(嵌套类)
public class StaticInnerClass {
    private static int number = 100;
    private int j = 20;
    private String name = "Java";

    public static void outer_funOne(){
        System.out.println("外部类静态方法:outer_funOne");
    }

    public void outer_funTwo(){

    }
    //静态内部类可以用public、protected、private修饰
    //静态内部类可以定义静态成员、方法或非静态成员、方法
    private static class Demo{
        static int j = 100;
        String name = "C#";

        //静态内部类里的静态方法
        static void demo_funOne(){
            //静态内部类只能访问外部类的静态成员(静态变量、静态方法)
            System.out.println("静态内部类访问外部类静态变量:"+number);
            outer_funOne();//访问外部类静态方法
        }
        //静态内部类非静态方法
        void demo_funTwo(){
        }
    }
    public void outer_funThree(){
        //外部类访问内部类静态成员:内部类.静态成员
        System.out.println(Demo.j);
        //访问静态方法
        Demo.demo_funOne();
        //访问静态内部类的非静态成员,实例化内部类即可
        Demo demo = new Demo();
        //访问非静态变量
        System.out.println(demo.name);
        //访问非静态方法
        demo.demo_funTwo();
    }


    public static void main(String[] args) {
        StaticInnerClass staticInnerClass=new StaticInnerClass();
        staticInnerClass.outer_funThree();

    }

}

⑦. 匿名内部类

(1)本质是类
(2)内部类
(3)该类没有名字
(4)同时还是一个对象
说明:匿名内部类是定义在外部类
的局部位置,比如方法中,并且没有类名
1.匿名内部类的基本语法
new类或接口(参数列表){
        类体
};

①匿名内部类的语法比较奇特,请大家注意,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,,因此可以调用匿名内部类方法。
②.可以直接访问外部类的所有成员,包含私有的
③不能添加访问修饰符,因为它的地位就是一个局部变量
④作用域:仅仅在定义它的方法或代码块中。
⑤匿名内部类—访问---->外部类成员[访问方式:直接访问]
⑥外部其他类—不能访问----->匿名内部类(因为匿名内部类地位是一个局部变量)
⑦如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

 public class HelloWorldAnonymousClasses {
  
      /**
       * 包含两个方法的HelloWorld接口
       */
      interface HelloWorld {
          public void greet();
          public void greetSomeone(String someone);
      }
 
     public void sayHello() {
 
         // 1、局部类EnglishGreeting实现了HelloWorld接口
         class EnglishGreeting implements HelloWorld {
             String name = "world";
             public void greet() {
                 greetSomeone("world");
             }
             public void greetSomeone(String someone) {
                 name = someone;
                 System.out.println("Hello " + name);
             }
         }
 
         HelloWorld englishGreeting = new EnglishGreeting();
 
         // 2、匿名类实现HelloWorld接口
         HelloWorld frenchGreeting = new HelloWorld() {
             String name = "tout le monde";
             public void greet() {
                 greetSomeone("tout le monde");
             }
             public void greetSomeone(String someone) {
                 name = someone;
                 System.out.println("Salut " + name);
             }
         };
 
         // 3、匿名类实现HelloWorld接口
         HelloWorld spanishGreeting = new HelloWorld() {
             String name = "mundo";
             public void greet() {
                 greetSomeone("mundo");
             }
             public void greetSomeone(String someone) {
                 name = someone;
                 System.out.println("Hola, " + name);
             }
         };
         
         englishGreeting.greet();
         frenchGreeting.greetSomeone("Fred");
         spanishGreeting.greet();
     }
 
     public static void main(String... args) {
         HelloWorldAnonymousClasses myApp = new HelloWorldAnonymousClasses();
         myApp.sayHello();
     }
 }
运行结果:
匿名内部类访问其外部类方法
动物
布谷鸟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/566274.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++常用的支持中文的GUI库Qt 6之三: 项目的发布

C常用的支持中文的GUI库Qt 6之三: 项目的发布 本文接着上一篇“C常用的支持中文的GUI库Qt 6之二:项目的结构、资源文件的使用” https://blog.csdn.net/cnds123/article/details/130741807介绍,并使用其中的例子。 程序代码能正确编译运行&…

1. Tomcat整体架构及其设计精髓分析

MySQL性能调优 1.Tomcat的整体架构1.1 Tomcat介绍1.1.1 Servlet基础回顾 1.2 目录结构1.3 web应用部署的方式1.4 结合Server.xml理解Tomcat架构1.5 架构图 2. Tomcat核心组件详解2.1 Server 组件2.2 Service组件2.3 连接器Connector组件2.3.1 ProtocolHandler 组件2.3.1.1 EndP…

全志V3S嵌入式驱动开发(移植linux kernel和rootfs)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 除了少部分嵌入式设备使用vxworks和freertos之外,大部分嵌入式都是使用linux来做基础os来使用的。linux使用场景很多,除了大…

智慧城市同城V4小程序V2.24独立开源版 + 全插件+VUE小程序开源前端+最新用户授权接口

智慧城市同城V4小程序V2.22开源独立版本月最新版,与上一版相比修复了一些小细节,功能本身并无大的变化。新版系统包含全插件、包括很多稀缺收费的插件都在里面如括招聘、 家政等,外加小程序的VUE开源前端,整个系统全开源&#xff…

chatgpt赋能python:PythonTic:了解一种强大的测试框架

Python Tic: 了解一种强大的测试框架 当你编写代码时,测试通常是不可或缺的一部分。Python Tic是一个出色的测试框架,它可以帮助您自动化测试和验证您的代码。 简介 Python Tic是一种基于Python的测试框架,它能够测试您的代码的各个方面&a…

鹅厂程序员的9个生存法则

👉腾小云导读 本文作者在腾讯多年,主要从事的是腾讯云CDN、EdgeOne产品的后台研发工作。作者在云计算领域遇到了不少代码设计和程序设计的问题,他对于如何把项目中的代码标准化、提高开发维护的效率,做了总结梳理。本篇为各位分享…

解密Java Class文件不为人知的秘密

Java 诞生多年,因此在网络上,有关 Java Class 文件格式解析的文章有很多,但他们大多数都是在列举《Java 虚拟机》中定义的格式,通读下来,好像所有的东西都讲清楚了,但是我个人好像并没有看懂,不…

舵机云台实现体感姿态跟随功能

1. 功能说明 本文示例将实现R207样机舵机云台根据六轴陀螺仪传感器数据实现姿态跟随的功能。 2. 电子硬件 在这个示例中,我们采用了以下硬件,请大家参考: 主控板 Basra主控板(兼容Arduino Uno)‍ 扩展板 Bigfish2.1扩…

【012】C++循环控制语句 for 和 while 详解

C循环控制语句 for 和 while 详解 引言一、循环控制语句 for1.1、for 循环语句1.2、break和continue1.3、for循环的嵌套 二、循环控制语句while2.1、while循环语句2.2、break和continue2.3、do...while()循环语句 总结 引言 💡 作者简介:专注于C/C高性能…

【JavaSE】Java基础语法(九):封装

文章目录 ☔1. private关键字☔2. private关键字的使用☔3. this关键字☔4. this内存原理☔5. 封装思想 ☔1. private关键字 概述 : private是一个修饰符,可以用来修饰成员(成员变量,成员方法) 特点 : 被private修饰的成员&…

公网远程连接Redis数据库【内网穿透】

文章目录 1. Linux(centos8)安装redis数据库2. 配置redis数据库3. 内网穿透3.1 安装cpolar内网穿透3.2 创建隧道映射本地端口 4. 配置固定TCP端口地址4.1 保留一个固定tcp地址4.2 配置固定TCP地址4.3 使用固定的tcp地址连接 转发自cpolar内网穿透的文章:公网远程连接…

(El-button-group)解决:优化 el-button 实现 button 相连且动态切换的使用案例(涉及:动态绑定 class )

Ⅰ、Element-ui 提供的组件与想要目标情况的对比&#xff1a; 1、Element-ui 提供组件情况&#xff1a; 其一、Element-ui 自提供的代码情况为(示例的代码&#xff0c;例子如下)&#xff1a; // Element-ui 自提供的代码&#xff1a; <template><div><el-but…

深度解析多线程的创建方式和正确启动多线程

一、创建多线程 1. 实现多线程 java 实现多线程的方式准确来说有两种&#xff08;oracle官方文档说的&#xff09;&#xff1a; &#xff08;1&#xff09;实现 Runnable 接口&#xff0c; 重写run()函数&#xff0c;运行start()方法 代码演示&#xff1a; /*** 用Runnable…

移动端浏览器性能优化探索

在移动端的页面开发过程中&#xff0c;我们经常提及页面性能优化、消除页面卡顿的话题&#xff0c;如何确定优化策略&#xff0c;我们首先应当对页面卡顿的行为有所认知。 前言 &#xfeff; 页面的卡顿现象可以比较明确的分为三个类型&#xff0c;分别是 “画面撕裂” 、“丢帧…

让你不再好奇怎么给小说配音

你是否曾经想象过&#xff0c;当你在读小说时&#xff0c;你可以听到人物的声音&#xff0c;感受到情感和气氛的变化&#xff1f;有声书的出现已经让这一切成为可能。然而&#xff0c;如何为小说创造生动的配音效果却是一个需要仔细考虑的问题。如果你还不知道怎么给小说配音的…

酷开会员丨版权时代,酷开科技打造更多优质内容服务消费者

以版权产业为核心的文化产业&#xff0c;需要重视版权、鼓励创新&#xff0c;才能形成文化创新的环境与氛围&#xff0c;这也是版权时代的发展趋势。在版权时代&#xff0c;付费观看是基本意识&#xff0c;比如电视内容供应方提供了大量免费的资源&#xff0c;观众为观看更精良…

数据结构之二叉树的基本实现

在我们之前已经了解的堆这样的完全二叉树的实现&#xff0c;也对树型结构有了一些了解&#xff0c;那么今天我们来看看二叉树的一些性质。 因为二叉树是一种每个节点至多只有两个子树&#xff08;即二叉树的每个节点的度不大于2&#xff09;&#xff0c;并且二叉树的子树有左右…

二、Django REST Framework (DRF)序列化反序列化数据校验

参考&#xff1a; DRF 官方文档&#xff1a; Serializers - Django REST framework中文站点 为什么要学DRF和什么是REST API | 大江狗的博客 上一章&#xff1a; 一、Django REST Framework (DRF)& RESTful 风格api_做测试的喵酱的博客-CSDN博客 下一章&#xff1a;…

【C++】类和对象(中上):类的六个默认成员函数——构造函数、析构函数、拷贝构造函数!

目录 前言&#xff1a; 一、类的默认成员函数&#xff1a; 二、构造函数&#xff1a; 1.特性&#xff1a; 构造函数调用规则&#xff1a; 1.无参数的构造函数&#xff08;默认构造函数&#xff09;&#xff1a; 2.带参数的构造函数&#xff1a; 3.全缺省的构造函数&…

Qt编写视频监控系统75-计算实时码率并显示

一、前言 做监控摄像头的实时视频显示&#xff0c;一般还会要求统计实时码率显示在通道画面上&#xff0c;一个是为了测试下整个软件的性能&#xff0c;同时也看下当前到底是主码流还是子码流&#xff0c;设备到底是不是真的按照设定的码流大小来传输视频数据的。视频码率就是…