Java 内部类

Posted 李亦华的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 内部类相关的知识,希望对你有一定的参考价值。

内部类

  1. 什么是内部类:一个类里面包含另一个类 
  2. 内部类分类:成员内部类、局部内部类(包含匿名内部类)

成员内部类的定义和使用

  1. 内部类的定义

    • package view.study.demo5;
      
      /**
       * @Author: YiHua Lee
       * 
       * 成员内部类的定义格式:
       * 修饰符 class 外部类名称 {
       *     修饰符 class 内部类名称 {
       *         // ...
       *     }
       *     // ...
       * }
       *
       * 注意:
       *      内部类调用外部类,可以随意访问。
       *      外部类调用内部类,需要借助内部类对象才可以访问内部类。
       *  
       */
      public class Body {
      
          /**
           * 内部类
           */
          public static class Heart {
      
              /**
               * 内部类方法
               */
              public void beat() {
                  System.out.println("心脏,蹦蹦跳");
      
                  System.out.println(name);   // 内部类调用外部类,可以随意访问。
                  System.out.println(Body.getName());
                  Body.setName("胃");
              }
      
          }
      
          /**
           * 外部类成员变量
           */
          private static String name;
      
          /**
           * 外部类方法
           */
          public void methodBody() {
              System.out.println("身体,哈哈哈");
          }
      
          public static String getName() {
              return name;
          }
      
          public static void setName(String name) {
              Body.name = name;
          }
      
      }
      
  2. 如何使用成员内部类

    1. 间接方式:在外部类当中使用内部类,然后main只是调用外部类方法。

      img

    2. 直接方式

      img

内部类的同名变量访问

img

局部内部类的定义

/**
 * @Author: YiHua Lee
 * 
 * 局部内部类:
 * 定义格式:
 * 修饰符 class 类名称 {
 *     修饰符 返回值类型 方法名称(参数列表) {
 *         class 局部内部类名称 {
 *             // 方法体...
 *         }
 *     }
 *     // ...
 * }
 */
public class Outer1 {

    public void method() {
        // 局部内部类
        class Inner {
            int num = 10;
            public void method() {
                System.out.println(num);
            }
        }
        new Inner().method();       // 只能在这个方法里面调用这个类
    }

}

// 如果一个类定义在方法的内部,那么这个类就是一个局部内部类。
// 且这个类只能在方法内部使用,出了该方法,就不能用了。

局部内部类的final问题

局部内部类注意事项:

局部内部类是在方法内部的嘛,如果希望所在方法的局部变量,那么这个局部变量必须有【final关键词】
备注:
从Java 8+ 开始,只要局部变量事实不变,那么可以省略关键词 final
原因:
(1)new出来的对象是在堆内存中的,
(2)局部变量是跟着方法走的,在栈内存中,
(3)而方法运行结束之后,就会立刻出栈,局部变量也就会立刻消失,
(4)但是new出来的对象会在堆内存中持续存在,知道垃圾回收消失。

匿名内部类的定义及使用

实例理解

public interface anonymousInterface01 {
    public abstract void method() ;
}
public class InterfaceImplements implements anonymousInterface01 {

    @Override
    public void method() {
        System.out.println("实现类覆盖重写接口的抽象方法");
    }

}
public class Demo01Anonymous {
    public static void main(String[] args) {
        // 多态方式创建对象
        anonymousInterface01 obj1 = new InterfaceImplements();
        // 调用实现类覆盖重写的接口的方法
        obj1.method();

        // 假如接口的实现类(或父类的子类)只需要使用唯一一次,
        // 那么这种情况下就可以省略实现类(或子类)的定义,而改为使用匿名内部类。
        anonymousInterface01 obj2 = new anonymousInterface01() {
            @Override
            public void method() {
                System.out.println("我就使用一次,就不定义实现类了哈!!!");
            }
        };
        // 调用匿名类覆盖重写的接口的方法
        obj2.method();
    }
}

匿名内部类的注意事项

对于匿名内部类

  1. 假如接口的实现类(或父类的子类)只需要使用唯一一次,那么这种情况下就可以省略实现类(或子类)的定义,而改为使用【匿名内部类】。

  2. 如果希望使用多次,那么就需要创建单独的实现类(或子类)了。

  3. 使用格式

    接口名称 对象名 = new 接口名称() {
        // ...
    }
    或
    new 父类名称(参数列表) {
        // ...
    }
    
  4. new 接口名称() {...} 的理解

    1. new 代表创建对象的动作
    2. 接口名称就是匿名内部类需要实现哪个接口
    3. {...} 是匿名内部类的内容
  5. 注意

    1. 匿名内部类只能使用唯一一次
    2. 要使用多次,请创建实现类(或子类)

类作为成员变量类型

实例理解

public class Weapon {

    /**
     * 英雄武器代号
     */
    private String code;

    public Weapon() {
    }

    public Weapon(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

}
public class Hero {

    /**
     * 英雄名字
     */
    private String name;

    /**
     * 英雄的年龄
     */
    private int age;

    /**
     * 英雄的武器
     */
    private Weapon weapon;

    public Hero() {
    }

    public Hero(String name, int age, Weapon weapon) {
        this.name = name;
        this.age = age;
        this.weapon = weapon;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Weapon getWeapon() {
        return weapon;
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    public void attack() {
        System.out.println("年龄为 " + age + " 岁的 " + name + " 正在使用 " + weapon.getCode() + " 突突突~~ " + "敌人");
    }

}
public class DemoMain {
    public static void main(String[] args) {
        // 创建英雄
        Hero hero = new Hero();

        hero.setName("斯沃特");
        hero.setAge(27);

        // 给英雄配备武器
        Weapon weapon = new Weapon();
        weapon.setCode("AK-47(火麒麟)");
        hero.setWeapon(weapon);
        
        hero.attack();
    }
}

接口作为成员变量类型

实例理解

public class Weapon {

    /**
     * 英雄武器代号
     */
    private String code;

    public Weapon() {
    }

    public Weapon(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

}
public class Hero {

    /**
     * 英雄名字
     */
    private String name;

    /**
     * 英雄的年龄
     */
    private int age;

    /**
     * 英雄的武器
     */
    private Weapon weapon;

    public Hero() {
    }

    public Hero(String name, int age, Weapon weapon) {
        this.name = name;
        this.age = age;
        this.weapon = weapon;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Weapon getWeapon() {
        return weapon;
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    public void attack() {
        System.out.println("年龄为 " + age + " 岁的 " + name + " 正在使用 " + weapon.getCode() + " 突突突~~ " + "敌人");
    }

}
public class DemoMain2 {
    public static void main(String[] args) {
        // 创建英雄
        Hero hero = new Hero();

        hero.setName("斯沃特");
        hero.setAge(27);

        // 给英雄配备武器
        Weapon weapon = new Weapon();
        weapon.setCode("AK-47(火麒麟)");
        hero.setWeapon(weapon);

        hero.attack();
    }
}

接口作为方法的参数或返回值

实例理解

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: YiHua Lee
 * @CreateTime: 2019/12/18 21:12
 */
public class DemoArrayList {

    public static void main(String[] args) {
        // ArrayList<E> 类是 List<E> 接口的实现类
        // 这里创建对象有使用多态的写法
        ArrayList<String> arrayList = new ArrayList<>();
        List<String> list = new ArrayList<>();

        // 添加内容进集合
        addList(arrayList);
        addList(list);

        // 遍历输出 arrayList
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.println(arrayList.get(i));
        }
        System.out.println("===========================");
        // 遍历输出 list
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

    public static List<String> addList(List<String> list) {
        list.add("大哥");
        list.add("二哥");
        list.add("三哥");
        list.add("四哥");
        return list;
    }

}

以上是关于Java 内部类的主要内容,如果未能解决你的问题,请参考以下文章

# Java 常用代码片段

# Java 常用代码片段

elasticsearch代码片段,及工具类SearchEsUtil.java

片段 - 全局视图变量与本地和内部类侦听器和内存泄漏

为啥片段类应该是公开的?

ForegroundService没有从片段开始?