Java中内部类的介绍及其用法

简介: Java中内部类的介绍及其用法

内部类


1 内部类的概念及其分类


定义:当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服 务,那么这个内部的完整结构最好使用内部类。在 Java 中,可以将一个类定义在另一个类或者一个方法的内部, 前者称为内部类,后者称为外部类。内部类也是封装的一种体现。


分类:根据内部类定义的位置不同,一般可以分为以下几种形式:


  1. 成员内部类(实例内部类:未被static修饰的成员内部类 和 静态内部类:被static修饰的成员内部类) 。
  2. 局部内部类(不谈修饰符)、匿名内部类。


2 内部类的定义方式


class OuterClass{
  //定义一个内部类
  class InnerClass{
  }
}


当然,内部类可以进行嵌套:建议嵌套层次不要太多。


class OuterClass{
  class InnerClass{
  class InnerClass1{
    class InnerClass2{
    ......
    }
  }
  }
}


注意:


1.定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类。例如:


public class A{
}
class B{
}


此处的A和B就是两个单独的类。


2.内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件。


3 内部类的用法


3.1实例内部类


概念:未被static修饰的成员内部类。


class OuterClass{
    //外部类的成员
    int data1 =1;
    static int data2 = 2;
    class InnerClass {
        //内部类的成员
        int data3 = 3;
        static final int data4 =4;
        public void fun()
        {
            System.out.println(data3);
        }
    }
}

3.1.1 实例内部类的注意点:


1.在实例内部类中可以直接访问外部类中:任意访问限定符修饰的成员,例如:


class OuterClass{
    //外部类的成员
    private int data1 =1;//被privat修饰的成员
    static int data2 = 2;
    class InnerClass {
        //内部类的成员
        int data3 = 3;
        static final int data4 =4;
        public void fun()
        {
            System.out.println(data1);//访问外部类中被private修饰的成员
            System.out.println(data2);
        }
    }
}


2.在实例内部类中不能创建静态成员变量和静态成员方法,如果一定要创建静态成员变量的话,该成员必须要被static final修饰并且初始化。不能先定义data4再赋值,这里要同时进行。


那么这里被final修饰代表什么意思呢?其实被static修饰的变量就是常量,其值不能被更改。


当我们创建好了一个内部类时,我们在public类中如何访问这内部类中的成员呢?


3.1.12访问内部类的元素


我们这里只讲嵌套了一层内部类的情况,访问实例内部类成员的方法有两种。


方法一:


public class Test{
    public static void main(String[] args)
    {
        OuterClass outerClass = new OuterClass();
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        System.out.println(innerClass.data3);//访问内部类的成员
    }
}


下面我们将这段代码进行拆解讲解:


这段代码用于创建一个外部内的引用变量 outerClass。


OuterClass outerClass = new OuterClass();


再通过outerClass这个引用变量创建一个内部类的引用。即:


//语法格式:类型(OuterClass.InnerClass) 变量名(innerClass) = 外部类的引用(outerClass).new 内部类(InnerClass());
OuterClass.InnerClass innerClass = outerClass.new InnerClass();


注意事项:


1.当内部类和外部类的有相同变量名的成员变量时,在内部类中访问这个变量时,优先访问的是内部类的变量。例如:


class OuterClass{
    int data3 =33;
    class InnerClass {
        int data3 = 3;
        public void fun()
        {
            System.out.println(data3);
        }
    }
}
public class Test{
    public static void main(String[] args)
    {      
        OuterClass outerClass = new OuterClass();
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        innerClass.fun();
    }
}


运行结果:


d23fa414597cceac6dedcc2c16c55cd6_7a5ab7aab28d4a858d72d620d14dc00d.png


倘若我们想要访问的是外部类的那个变量,只需将


public void fun()
{
    System.out.println(data3);
}


改成


public void fun()
{
    //语法格式:外部类.this.变量名
    System.out.println(OuterClass.this.data3);
}


即可打印外部类的那个变量。


2:当我们想要在外部类中访问内部类的成员时,要先在外部类中创建实例内部类对象,例如:


class OuterClass{
    int data1 =1;
    InnerClass innerClass = new InnerClass();//在外部类中创建实例内部类对象
    public void print()
    {
        System.out.println(innerClass.data2);//访问内部类
    }
    class InnerClass {
        int data2 = 2;
    }
}
public class Test3{
    public static void main(String[] args)
    {
        OuterClass outerClass = new OuterClass();
        outerClass.print();
    }
}


运行结果:


c7c3efaf22b921176a1738f9f077b359_f60a207ffdf94afcb4e122b525d1787f.png


方法二:


public class Test{
    public static void main(String[] args)
    {
        //语法格式
        OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();//实例化内部类         
        System.out.println(innerClass.data4);//访问内部类的成员
     }
}


3.2 静态内部类


概念:被static修饰的内部成员类称为静态内部类。


定义方式(这里我们只讲嵌套了一层内部类的情况):


class OuterClass{
    //定义了一个静态内部类
    static class InnerClass{   
        ……
    }
}


  • 当我们想要获取静态内部类的成员变量时,可以不用创建外部类对象,可以直接创建内部类对象进行访问。


  • 语法格式如下:
  • //类型(OuterClass.InnerClass).变量名 = new 类型(OuterClass.InnerClass)();
  • OuterClass.InnerClass innerclass = new OuterClass.InnerClass();

class OuterClass{
    public static int data1 = 1;
    int data2 = 2;
    public static void functionA()
    {
        System.out.println("这是一个外部类中的静态方法");
    }
    public  void functionB()
    {
        System.out.println("这是一个外部类中的非静态方法");
    }
    static class InnerClass{
        int data3 = 3;
        public void fun(){
            //System.out.println(data2);//访问外部类中的非静态成员,会报错
            System.out.println(data1);//访问外部类中的实例成员,正常执行
            functionB();//调用外部类中的非静态方法,会报错
            functionA();//调用外部类中的静态方法,正常执行
        }
    }
}
public class test {
    public static void main(String[] args) {
    OuterClass.InnerClass innerclass = new OuterClass.InnerClass();//创建内部类对象
    innerclass.fun();
    OuterClass outerclass = new OuterClass();
    System.out.println(outerclass.data2);//通过创建外部类对象访问非静态成员
    }
}


若一定要访问外部类中的非静态成员,只能通过创建外部类的对象进行访问。例如上述代码的28-29行:


OuterClass outerclass = new OuterClass();
  System.out.println(outerclass.data2);//通过创建外部类对象访问非静态成员


3.3 局部内部类:


概念:定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用,一般使用的非常少,此处简单了解下语法格式。


定义方式:


public class OutClass {
    int a = 10;
    public void method(){
    int b = 10;
    // 局部内部类:定义在方法体内部
    // 不能被public、static等访问限定符修饰
      class InnerClass{
      public void methodInnerClass(){
      System.out.println(a);
      System.out.println(b);
      }
      }
    // 只能在该方法体内部使用,其他位置都不能用
    InnerClass innerClass = new InnerClass();
    innerClass.methodInnerClass();
    }
    public static void main(String[] args) {
    // OutClass.InnerClass innerClass = null; 编译失败
    }
    }

注意:


  • 局部内部类只能定义在方法内部,并且不能被访问限定修饰符修饰。
  • 局部内部类只能在方法体内部使用。


本章的内容就到这里啦,若有不足,欢迎评论区指正,最后,希望大佬们多多三连吧,下期见!


相关文章
|
4月前
|
Java
Java中的equals()与==的区别与用法
【7月更文挑战第28天】
67 12
|
23天前
|
存储 安全 Java
深入理解Java中的FutureTask:用法和原理
【10月更文挑战第28天】`FutureTask` 是 Java 中 `java.util.concurrent` 包下的一个类,实现了 `RunnableFuture` 接口,支持异步计算和结果获取。它可以作为 `Runnable` 被线程执行,同时通过 `Future` 接口获取计算结果。`FutureTask` 可以基于 `Callable` 或 `Runnable` 创建,常用于多线程环境中执行耗时任务,避免阻塞主线程。任务结果可通过 `get` 方法获取,支持阻塞和非阻塞方式。内部使用 AQS 实现同步机制,确保线程安全。
|
2月前
|
Java
Java 正则表达式高级用法
Java 中的正则表达式是强大的文本处理工具,用于搜索、匹配、替换和分割字符串。`java.util.regex` 包提供了 `Pattern` 和 `Matcher` 类来高效处理正则表达式。本文介绍了高级用法,包括使用 `Pattern` 和 `Matcher` 进行匹配、断言(如正向和负向前瞻/后顾)、捕获组与命名组、替换操作、分割字符串、修饰符(如忽略大小写和多行模式)及 Unicode 支持。通过这些功能,可以高效地处理复杂文本数据。
|
2月前
|
存储 Java 数据处理
Java 数组的高级用法
在 Java 中,数组不仅可以存储同类型的数据,还支持多种高级用法,如多维数组(常用于矩阵)、动态创建数组、克隆数组、使用 `java.util.Arrays` 进行排序和搜索、与集合相互转换、增强 for 循环遍历、匿名数组传递以及利用 `Arrays.equals()` 比较数组内容。这些技巧能提升代码的灵活性和可读性,适用于更复杂的数据处理场景。
|
1月前
|
Java 编译器
【Java】内部类
【Java】内部类
21 0
|
2月前
|
安全 Java
Java switch case隐藏用法
在 Java 中,`switch` 语句是一种多分支选择结构,常用于根据变量值执行不同代码块。除基本用法外,它还有多种进阶技巧,如使用字符串(Java 7 开始支持)、多个 `case` 共享代码块、不使用 `break` 实现 “fall-through”、使用枚举类型、使用表达式(Java 12 及以上)、组合条件以及使用标签等。这些技巧使代码更加简洁、清晰且高效。
|
3月前
|
Java 数据处理
Java IO 接口(Input)究竟隐藏着怎样的神秘用法?快来一探究竟,解锁高效编程新境界!
【8月更文挑战第22天】Java的输入输出(IO)操作至关重要,它支持从多种来源读取数据,如文件、网络等。常用输入流包括`FileInputStream`,适用于按字节读取文件;结合`BufferedInputStream`可提升读取效率。此外,通过`Socket`和相关输入流,还能实现网络数据读取。合理选用这些流能有效支持程序的数据处理需求。
46 2
|
3月前
|
Java
【Java基础面试二】、个Java文件里可以有多个类吗(不含内部类)?
这篇文章讨论了Java文件中类的定义规则,指出一个Java文件可以包含多个类(不包含内部类),但其中最多只能有一个public类,且如果有public类,它的名称必须与文件名一致。
|
3月前
|
算法 Java
12 Java常用类(一)(内部类+object类+包装类)
12 Java常用类(一)(内部类+object类+包装类)
37 5
|
4月前
|
Java
Java进阶之内部类
【7月更文挑战第13天】Java内部类增进代码组织与封装,允许直接访问外部类成员,包括私有成员。主要有四种类型:成员、静态、局部和匿名内部类。匿名内部类常用于一次性实现接口或扩展类。内部类可隐藏实现细节,减少命名冲突,并在特定上下文中定义辅助类。示例展示了静态和非静态内部类如何在Shape类中封装Circle和Rectangle。使用内部类能提升代码可读性,但可能增加复杂性。
37 6