java程序员分水岭,内部类详解

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


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());  // class seniorobject.innerclass.Outer002$1
    }
}
interface IA {
    public void cry();
}


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


基于类的匿名内部类


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

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();
    }
}


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


6.OOP结束之际


到现在java的oop阶段就已经结束啦~


送给大家一句话:


学习切勿操之过急,特别是编程,不要一味追求广度,要有一定的深度,基础一定要好!✨我亦无他,唯手熟尔

目录
相关文章
|
29天前
|
Java
java中,剩下的这两个内部类不太好理解!
java中,剩下的这两个内部类不太好理解!
12 0
|
29天前
|
Java 编译器
java中常见的几种内部类,你会几个?(未完)
java中常见的几种内部类,你会几个?(未完)
14 1
|
1月前
|
存储 安全 Java
Java 程序员极速上手 go
Java 程序员极速上手 go
28 0
|
2月前
|
设计模式 缓存 分布式计算
|
3月前
|
人工智能 Java 大数据
Java程序员真的还有未来吗?如何备战2024春招?并狂拿大厂offer?
Java程序员还有未来吗? 嘿,小伙伴们,你们有没有想过Java程序员还有没有未来? 哈哈,别担心,我这就来给你们答疑解惑! 首先,让我们来看看Java的发展历程。自从Java诞生以来,它就一直是编程界的一颗璀璨明星。从Web应用到企业级应用,再到移动应用,Java无处不在。那么,现在呢?现在,随着人工智能、大数据和云计算的兴起,Java依然发挥着重要的作用。这些领域都需要大量的Java程序员来支持它们的发展。 那么,有人会说:“哎呀,现在出现了那么多新的编程语言和框架,Java程序员会不会被淘汰啊?”哈哈,别担心,Java程序员们!这些新语言和框架的出现并不会让Java消失。相反,它们
77 0
|
3月前
|
算法 架构师 安全
10年Java面试总结:Java程序员面试必备的面试技巧
作为一名资深10年Java技术专家,我参与了无数次的面试,无论是作为面试者还是面试官。在这里,我将分享我的一些面试经历和面试技巧,希望能帮助即将面临面试的Java程序员们。回顾我的Java职业生涯,我清晰地记得一次特别的面试经历。那是我申请一家知名科技公司的Java开发岗位。为了这次面试,我花了几周的时间准备,这不仅包括Java的基础和高级知识,还有关于公司产品的研究。
134 0
|
7天前
|
安全 Java 编译器
接口之美,内部之妙:深入解析Java的接口与内部类
接口之美,内部之妙:深入解析Java的接口与内部类
25 0
接口之美,内部之妙:深入解析Java的接口与内部类
|
9天前
|
Java API
Java基础—笔记—内部类、枚举、泛型篇
本文介绍了Java编程中的内部类、枚举和泛型概念。匿名内部类用于简化类的创建,常作为方法参数,其原理是生成一个隐含的子类。枚举用于表示有限的固定数量的值,常用于系统配置或switch语句中。泛型则用来在编译时增强类型安全性,接收特定数据类型,包括泛型类、泛型接口和泛型方法。
9 0
|
9天前
|
存储 Java
java接口和内部类
java接口和内部类
|
17天前
|
XML Java 程序员
作为Java程序员还不知道Spring中Bean创建过程和作用?
作为Java程序员还不知道Spring中Bean创建过程和作用?
12 0