Java成员类(内部类、匿名内部类)

Java 中内部类指的是声明在一个类内部的类,它可以访问外部类的私有变量和方法,而外部类不能直接访问内部类的成员。内部类的主要作用是为外部类提供一种封装和组织代码的方式。

内部类可以解决Java类单继承的问题,因为内部类和外部类可以相互访问。


类型: 内部类分为四种类型:

  • 成员内部类(Member Inner Class): 定义在外部类内部的非静态类。它可以访问外部类的成员。
  • 静态内部类(Static Inner Class): 定义在外部类内部的静态类。它不依赖于外部类的实例,可以直接通过外部类名访问。
  • 局部内部类(Local Inner Class): 定义在方法内部的类。它只在方法的作用域内可见。
  • 匿名内部类(Anonymous Inner Class): 没有显式类名的内部类,通常用于创建实现接口或继承类的匿名对象。

访问修饰符public仅适用于顶级类和成员类 ,不适用于本地类或匿名类。访问修饰符 protected和 private 仅适用于成员类

static 修饰的类仅适用于成员类和本地类

访问方式: 访问内部类的方式取决于内部类的型。类成员内部类通过外部类的实例访问,而静态内部类通过外部类名访问。成员类属于类的成员,所以可以调用外部类的 private 成员。外部类可以访问成员类的 private 成员


在外部类中创建成员内部类的实例:

java 复制代码
public class OuterClass {
    private int x = 10;
    // 成员类
    public class InnerClass {
        public void print() {
            System.out.println("x is " + x);
        }
    }
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();
        inner.print(); // 输出:x is 10
    }
}

局部内部类的定义方式如下:

java 复制代码
class Outer {
   void print() {
      final int b = 5;
      // 局部内部类
      class Inner {
         void print() {
            System.out.println("b = " + b);
         }
      }
      Inner inner = new Inner();
      inner.print();
   }
}

匿名内部类的 定义方式如下:

匿名类不能使用修饰符,在方法的内部,对外隐藏。不能是 static ,隐式 final 类。匿
名类没有类名,没有构造方法。

java 复制代码
interface A {
   void print();
}
class Outer {
   void print() {
      // 匿名内部类
      A a = new A() {
         public void print() {
            System.out.println("匿名内部类输出");
         }
      };
      a.print();
   }
}

静态内部类的定义方式如下:

java 复制代码
class Outer {
   private static int c;
    // 静态内部类
   static class Inner {
      void print() {
         System.out.println("c = " + c);
      }
   }
}

内部类的代码演示:

java 复制代码
package com.member;

/**
 * 成员类【内部类】
 */
public class Demo {
   static int a;
   static int B = 2;
   static {
       System.out.println("demo static{}");
   }
   static class DemoInner{
       int c = 0;
       static int a;
       static int B = 4;
       static {
           System.out.println("Inner static{}");
       }
       public static void t(){
           System.out.println(123);
       }
       public void test(){
           System.out.println(Demo.B);  // 调用外部类的静态变量
           System.out.println(B);       // 调用当前内部类的静态变量
           System.out.println(this.B);  // 调用当前内部类的静态变量

           new Demo().new Demo3().test();   // 调用另一个非静态内部类的非静态方法

           Demo.test();     // 调用外部类的静态方法
       }
   }
   class Demo3{
       static int B = 6;
       static int a;
       int c =12;
       static {
           System.out.println("demo3 static{}");
       }

       public void test(){
           System.out.println(this.B);      // 调用当前非静态类的静态变量
           System.out.println(Demo.B);      //  调用外部类的静态变量
           // 在实例成员类中可以使用 外部类.this 表示外部类对象 (实例成员类是由外部类对象创建的)成员类中的 this 表示的是成员类
           System.out.println(Demo.this.B);     // 调用外部类的静态变量
       }
   }
   public static void test(){
       System.out.println(DemoInner.a);
       System.out.println(Demo3.a);
       new DemoInner().test();      // 调用静态内部类的非静态方法
   }
}
class Test{
    public static void main(String[] args) {
        Demo.DemoInner i = new Demo.DemoInner();
        System.out.println(i.c);    // 调用内部类的实例变量
        Demo.DemoInner.t();    //调用内部类的静态方法
        int a = Demo.DemoInner.a;    // 调用内部类的静态变量


        int c = new Demo().new Demo3().c;    // 调用非静态类的实例变量
        int a1 = Demo.Demo3.a;    // 调用非静态类的静态变量
        Demo.Demo3 demo3 = new Demo().new Demo3();

        Demo.test();    // 调用外部类的静态方法

    }
}

总结:内部类和外部类区别**?**

访问修饰符:
外部类只能有两种访问权限: public 以及 package - access
内部类可以有四种访问权限: public / protected / package - access / private
也就是说:访问修饰符public仅适用于顶级类和成员类,不适用于本地类或匿名类。访问修饰符 protected和 private 仅适用于成员类。
static 修饰: 外部类不可以使用 static 修饰类,内部类可以
使用:外部类可以直接被使用,内部类的使用则依赖于外部类

相关推荐
Gofarlic_oms13 分钟前
利用API实现ANSYS许可证管理自动化集成
运维·服务器·开发语言·matlab·自动化·负载均衡
AI+程序员在路上1 小时前
VS Code 完全使用指南:下载、安装、核心功能与 内置AI 编程助手实战
开发语言·人工智能·windows·开源
invicinble1 小时前
这里对java的知识体系做一个全域的介绍
java·开发语言·python
catchadmin1 小时前
使用 PHP TrueAsync 改造 Laravel 协程异步化的可行路径
开发语言·php·laravel
wbs_scy2 小时前
【Linux 线程进阶】进程 vs 线程资源划分 + 线程控制全详解
java·开发语言
ss2732 小时前
食谱推荐系统功能测试如何写?
java·数据库·spring boot·功能测试
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题】【Java基础篇】第15题:JDK1.7中HashMap扩容为什么会发生死循环?如何解决
java·开发语言·数据结构·后端·面试·哈希算法
try2find2 小时前
打印ascii码报错问题
java·linux·前端
014-code2 小时前
CompletableFuture 实战模板(超时、组合、异常链处理)
java·数据库
Nicander3 小时前
多数据源下@transcation事务踩坑
java·后端