深入了解Java内部类的用法

 更新时间:2022年07月18日 10:44:41   作者:世界尽头与你  
java类的五大成员:属性,方法,构造器(构造方法),代码块,内部类。本文就来和大家详细讲讲ava内部类的用法,需要的小伙伴可以参考一下

1.内部类分类和概念

java类的五大成员:属性,方法,构造器(构造方法),代码块,内部类

内部类的分类:

定义在外部类局部的位置(比如方法内):

  • 局部内部类(有类名)
  • 匿名内部类(无类名)

定义在外部类成员位置上:

  • 成员内部类(没有static修饰)
  • 静态内部类(有static修饰)

概念:在一个类的内部再定义一个完整的类,也会生成一个class文件

代码示例:

/**
 * 内部类
 */
public class InnerClass {
    private int n = 521;

    public InnerClass(int n) {
        this.n = n;
    }

    class Inner { // 内部类

    }
}

谨记:内部类很重要,java底层源码内部类使用场景很多!

2.局部内部类

class Outer001 { // 外部类
    private int n = 521;
    private void kaka() {
        System.out.println("我是外部类的方法!");
    }
    public void show() {
        // 局部内部类定义在外部类的局部位置,通常在方法中
        class Inner001 {
            // 局部内部类
            public void f() {
                // 可以直接访问外部类的所有成员,包含私有的
                System.out.println(n);
            }
        }
    }
}

不能添加访问修饰符,但是可以添加final

局部内部类的作用域只在定义它的方法或者代码块中

外部类使用内部类的方法,直接new即可:

public void show() {
    // 局部内部类定义在外部类的局部位置,通常在方法中
    final class Inner001 {
        // 局部内部类
        public void f() {
            // 可以直接访问外部类的所有成员,包含私有的
            System.out.println(n);
            kaka();
        }
    }
    // 外部类使用内部类的方法
    Inner001 inner001 = new Inner001();
    inner001.f();
}

外部其他类不能访问局部内部类!

外部类和局部内部类的成员重名时,默认遵循就近原则,如果想要访问外部类的成员,使用外部类名.this.成员进行访问

3.匿名内部类(重要)

匿名内部类其实有名字,它的名字是底层的JDK给分配的~系统分配该类名的时候会在外部类的基础上加上$1,存在多个内部类的,$后面的值进行递增

基于接口的匿名内部类

/**
 * 匿名内部类
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer002 outer002 = new Outer002();
        outer002.method();
    }
}

class Outer002 {
    private int n = 521;

    public void method() {
        // 基于接口的匿名内部类
        // tiger的编译类型是IA,运行类型就是匿名内部类!
        // 系统分配该类名的时候会在外部类的基础上加上$1,此处是Outer002$1
        // JDK底层在创建了匿名内部类之后,立即创建了一个实例,并且把地址返回给tiger
        IA tiger = new IA() {
            @Override
            public void cry() {
                System.out.println("我是一只小老虎🐅");
            }
        };
        tiger.cry();
        System.out.println(tiger.getClass());
    }
}

interface IA {
    public void cry();
}

输出:

我是一只小老虎🐅
class seniorobject.innerclass.Outer002$1

注意:匿名内部类使用一次就不能再使用了!

基于类的匿名内部类

基于类的匿名内部类和基于接口的差不太多

Father类:

class Father {
    private String name;

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

    }
}

匿名内部类:

// 基于类的匿名内部类,加入大括号就摇身一变变成内部类了
Father jack = new Father("jack"){
    @Override
    public void test() {
        super.test();
        System.out.println("♪(^∇^*)");
    }
};
System.out.println(jack.getClass());

输出:

class seniorobject.innerclass.Outer002$2

一些细节

匿名内部类是类,同时,它也可以理解为是一个对象

匿名内部类可以访问外部类的所有成员,包括私有的

不能添加访问修饰符

定义域在定义它的方法或者代码块中,转瞬即逝!

外部其他类不能访问匿名内部类

外部类和匿名内部类成员重名时,参照局部内部类的方式即可

匿名内部类的最佳实践

当作实参直接传递,简洁高效

/**
 * 匿名内部类的最佳实践
 * 当作实参直接传递,简洁高效
 */
public class AnonymousInnerClassPractice {
    public static void main(String[] args) {
        f(new IL() {
            @Override
            public void show() {
                System.out.println("你好啊");
            }
        });
    }

    public static void f(IL il) {
        il.show();
    }
}

interface IL {
    void show();
}

4.成员内部类

定义在外部类的成员位置上:

实例:

/**
 * 成员内部类
 */
public class MemberInnerClass {
    public static void main(String[] args) {
        Outer003 outer003 = new Outer003();
        outer003.t();
    }
}

class Outer003 {
    private int n = 521;
    public String name = "dahe";

    class Inner003 { // 成员内部类
        public void say() {
            System.out.println(n + name);
        }
    }

    public void t() {
        // 使用成员内部类
        Inner003 inner003 = new Inner003();
        inner003.say();
    }
}

输出:

521dahe

可以访问外部类的所有成员,包括私有的

可以添加任意的访问修饰符

作用域为整个类体中

外部类想要使用成员内部类,创建对象调用即可!

外部其他类想要访问成员内部类,存在两种方式:

// 直接创建对象
Outer003.Inner003 inner003 = outer003.new Inner003();
// 注意:这里的outer003是外部类的对象实例
// 成员内部类的外部类创建一个返回内部类对象的公有方法
public Inner003 getInner003Instance() {
    return new Inner003();
}

// 外部其他类进行调用该共有方法
Outer003.Inner003 inner0031 = outer003.getInner003Instance();
inner0031.say();

外部类和成员内部类的成员重名时,参考局部内部类和匿名内部类即可

5.静态内部类

可以直接访问外部类的静态成员

可以添加任意的访问修饰符

作用域为整个类体

外部类想要访问静态内部类依然是创建对象访问

外部其他类想要访问静态内部类:

// 通过类名直接访问
Outer004.Inner004 inner004 = new Outer004.Inner004();
inner004.say();
// 静态内部类的外部类创建一个返回内部类对象的公有方法
// 返回静态内部类的对象实例
public Inner004 getInner004() {
    return new Inner004();
}

Outer004.Inner004 inner0041 = outer004.getInner004();
inner0041.say();
// 返回静态内部类的对象实例,但是是静态方法
public static Inner004 getInner004_() {
    return new Inner004();
}

// 静态内部类的外部类创建一个返回内部类对象的公有静态方法
Outer004.Inner004 inner0042 = Outer004.getInner004_();
inner0042.say();

整体代码示例:

/**
 * 静态内部类
 */
public class StaticInnerClass {
    public static void main(String[] args) {
        Outer004 outer004 = new Outer004();
        // 通过类名直接访问
        Outer004.Inner004 inner004 = new Outer004.Inner004();
        inner004.say();
        // 静态内部类的外部类创建一个返回内部类对象的公有方法
        Outer004.Inner004 inner0041 = outer004.getInner004();
        inner0041.say();
        // 静态内部类的外部类创建一个返回内部类对象的公有静态方法
        Outer004.Inner004 inner0042 = Outer004.getInner004_();
        inner0042.say();
    }
}

class Outer004 {
    private int n = 521;
    private static String name = "dahe";
    public static class Inner004 {
        public void say() {
            // 可以直接访问外部类的静态成员
            System.out.println(name);
        }
    }

    // 返回静态内部类的对象实例
    public Inner004 getInner004() {
        return new Inner004();
    }

    // 返回静态内部类的对象实例,但是是静态方法
    public static Inner004 getInner004_() {
        return new Inner004();
    }
}

外部类和成员内部类的成员重名时,遵循就近原则,如果想要访问外部类的成员,使用外部类名.成员即可

以上就是深入了解Java内部类的用法的详细内容,更多关于Java内部类的资料请关注脚本之家其它相关文章!

相关文章

  • spring在IoC容器中装配Bean详解

    spring在IoC容器中装配Bean详解

    这篇文章主要介绍了spring在IoC容器中装配Bean详解,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • Java中的字符串常量池详细介绍

    Java中的字符串常量池详细介绍

    这篇文章主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池,需要的朋友可以参考下
    2015-01-01
  • Netty网络编程实战之开发聊天室功能

    Netty网络编程实战之开发聊天室功能

    这篇文章主要为大家详细介绍了如何利用Netty实现聊天室功能,文中的示例代码讲解详细,对我们学习Netty网络编程有一定帮助,需要的可以参考一下
    2022-10-10
  • 分享java中设置代理的两种方式

    分享java中设置代理的两种方式

    有时候我们的程序中要提供可以使用代理访问网络,代理的方式包括http、https、ftp、socks代理。比如在IE浏览器设置代理,这里简单介绍下,需要的朋友可以参考下
    2015-12-12
  • 看动画学算法之Java实现doublyLinkedList

    看动画学算法之Java实现doublyLinkedList

    这篇文章主要介绍Java实现doublyLinkedList,LinkedList:doublyLinkedList相对比较复杂,今天就来简单学习一下doublyLinkedList的基本操作和概,感兴趣的小伙伴可以参考下面具体文章内容
    2021-10-10
  • this关键字详解

    this关键字详解

    这篇文章主要介绍了this关键字,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java中TCP通信的实现方法详解

    Java中TCP通信的实现方法详解

    这篇文章主要给大家介绍了关于Java中TCP通信的实现方法,TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server),需要的朋友可以参考下
    2023-09-09
  • Java 数据结构之时间复杂度与空间复杂度详解

    Java 数据结构之时间复杂度与空间复杂度详解

    算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是度量算法执行的时间长短;而空间复杂度是度量算法所需存储空间的大小
    2021-11-11
  • Java实现Huffman编码的示例代码

    Java实现Huffman编码的示例代码

    Huffman编码是一种编码方式,本文主要介绍了Java实现Huffman编码的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • Spring项目中使用Cache Redis实现数据缓存

    Spring项目中使用Cache Redis实现数据缓存

    这篇文章主要为大家介绍了项目中使用Spring Cache Redis实现数据缓存,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06

最新评论