【JavaSE】内部类

这篇具有很好参考价值的文章主要介绍了【JavaSE】内部类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

内部类概念

可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现。内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件。

public class OutClass {//外部类
	class InnerClass{ //内部类
	}
}

上面的代码中,OutClass是外部类,InnerClass就是内部类。它与普通外部类最大的不同,在于其实例对象不能单独存在,必须依附于一个外部类的实例对象。

局部内部类

局部内部类是定义在外部类的局部位置,通常在方法里。它拥有外部类中所有元素的访问权限。不能添加访问修饰符,因为它就相当于是一个局部变量,但是可以使用final修饰。作用域仅仅只能在定义它的方法或代码块中。

class Outer{ //外部类
    private int a = 1;//私有属性
    private void fun2(){ //私有方法
        System.out.println("Outer fun2()");
    }
    
    public void fun1(){ 
        System.out.println("Outer fun1()");
        
        final class Inner{ //局部内部类
            private int a = 2;
            public void funInner(){
                System.out.println(a); // 1 外部变量名重名 就近原则
                //Outer.this本质上就是外部类的对象,即哪个对象调用了fun1,Outer.this就指向哪个对象
                System.out.println(Outer.this.a); // 2
                fun2();
            }
        }
        Inner inner = new Inner();
        inner.funInner();
    }
}
public class InnerClass {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.fun1();
    }
}

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

匿名内部类(重点重点!!! )

匿名内部类就是指没有类名的内部类,必须在创建时使用 new 语句来声明。通常情况下,如果一个方法的参数是接口类型,且该接口只需要实现一次,那么我们就可以通过匿名内部类的形式来进行定义。

基于接口的匿名内部类实例:

class Outer1 {
    private int a = 10;

    public void method() {
        //基于接口的匿名内部类
        IA person = new IA() {
            @Override
            public void eat() {
                System.out.println("正在吃大餐");
            }
        };
        //查看person的运行类型
        System.out.println("person的运行类型:" + person.getClass()); // Outer1$1
        person.eat();
    }
}
//接口
interface IA {
    void eat();
}

class Person implements IA {
    @Override
    public void eat() {
        System.out.println("吃");
    }
}

public class AnonInter {
    public static void main(String[] args) {
        Outer1 outer1 = new Outer1();
        outer1.method();
    }
}
IA person = new IA() {
	@Override
	public void eat() {
		System.out.println("正在吃大餐");
	}
};

//上面这段代码其实就相当于
class Outer1$1 implements IA {
	@Override
	public void eat() {
		System.out.println("正在吃大餐");
	}
}

jdk底层在创建匿名内部类 Outer1$1 时,立即创建了 Outer1$1 实例,并且把地址返回给了person,匿名内部类只能使用一次就不能再使用了。

基于类的匿名内部类抽象内部类实例:

class Outer2 {
    public void method() {
        //编译类型:Animal
        //运行类型:Outer2$1
        Animal animal = new Animal("小白"){ //基于类的匿名内部类
            @Override
            public void eat() {
                System.out.println("匿名内部类重写了eat()");;
            }
        };
        animal.eat();
        System.out.println(animal.getClass()); //animal的运行类型 Outer2$1
        
        //编译类型:Robot
        //运行类型:Outer2$2
        Robot robot = new Robot(){ //基于抽象类的匿名内部类
            @Override
            void run() {
                System.out.println("正在奔跑");
            }
        };
        robot.run();
        System.out.println(robot.getClass());// robot的运行类型 Outer2$2
    }
}

class Animal implements IC {
    String name;

    public Animal(String name) {
        this.name = name;
    }
    public void eat(){
        System.out.println("Animal 在吃东西");
    }

    @Override
    public void run() {
        System.out.println("重写的run()");
    }
}

abstract class Robot { //抽象类
    abstract void run();
}

interface IC { //接口
    void run();
}

//测试
public class InterClass {
    public static void main(String[] args) {
        Outer2 outer2 = new Outer2();
        outer2.method();
    }
}

匿名内部类细节
匿名内部类既是一个类的定义,同时也是一个对象,从语法上看,它即有定义类的特征,也有创建对象的特征。

public class AnonClassDatil {
    public static void main(String[] args) {
        Outer3 outer3 = new Outer3();
        outer3.fun();
    }
}

class Outer3 {

    public void fun(){
        Car car = new Car(){ // 运行类型 Outer3$1
            @Override
            public void speed() {
                System.out.println("重写了speed()");;
            }
        };
        car.speed(); //动态绑定

        //也可以直接调用
        new Car(){
            @Override
            public void speed() {
                System.out.println("直接调用speed()");
            }
        }.speed();
    }
}

class Car {
    public void speed() {
        System.out.println("Car speed()");
    }
}

请看下面的代码

public class InnerExcise {
    public static void main(String[] args) {
        fun(new IQ() { //当做实参直接传递 简洁高效
            @Override
            public void show() {
                System.out.println("正在学习Java内部类");
            }
        });
    }
    public static void fun(IQ iq) { //静态方法 形参是接口类型
        iq.show();
    }
}



interface IQ {
    void show();
}

练习:
有一个铃声接口Bell,里面有一个ring方法,有一个手机类 CellPhone,具有闹钟的功能alarmClock,参数是Bell类型,测试手机类的闹钟功能,通过匿名内部类作为参数,打印 “起床了要迟到了”,再传入另一个匿名内部类,打印 “已经迟到了”。

public class InnerExcise1 {
    public static void main(String[] args) {
        CallPhone callPhone = new CallPhone();
        callPhone.alarmClock(new Bell() { //传递的是实现了Bell接口的匿名内部类
            @Override
            public void ring() {
                System.out.println("起床了要迟到了");
            }
        });

        callPhone.alarmClock(new Bell() {
            @Override
            public void ring() {
                System.out.println("已经迟到了");
            }
        });
    }
}

interface Bell {
    void ring();
}

class CallPhone {
    public void alarmClock(Bell bell) {
        bell.ring(); // 动态绑定
    }
}

成员内部类

成员内部类是定义在外部类的成员位置,并且没有static修饰,可以访问外部类的所以成员,包括私有成员。可以添加任意访问修饰符,因为它本质上就是一个成员。简而言之,成员内部类就是指没有被static修饰的内部类,也可以称为非静态内部类。

public class InnerExcise2 {
    public static void main(String[] args) {
        Outer5 outer5 = new Outer5();
        outer5.fun();
    }
}

class Outer5 {
    private int a = 10;
    private class Inner { // 可以添加任意访问修饰符
        public void say() {
            System.out.println(a); //可以访问外部类的所有成员,包括私有成员
        }
    }
    public void fun() {
        Inner inner = new Inner();
        inner.say();
    }
}
public class InnerExcise2 {
    public static void main(String[] args) {
        Outer5 outer5 = new Outer5();
        outer5.fun();
        //外部其他类 使用成员内部类的几种方式
        // 第一种 outer5.new Inner() 相当于是把new Inner()当成一个成员
        Outer5.Inner outer51 = outer5.new Inner(); 
        outer51.say();

        Outer5.Inner outer52 = outer5.shawOuter5();
        outer52.say();
    }
}

class Outer5 {
    private int a = 10;
    public class Inner { // 可以添加任意访问修饰符
        public void say() {
            System.out.println(a); //可以访问外部类的所有成员,包括私有成员
        }
    }

    //第二种 定义一个方法 返回一个Inner对象
    public Inner shawOuter5() {
        return new Inner();
    }
    public void fun() {
        Inner inner = new Inner();
        inner.say();
    }
}

如果有重名的成员,会遵守就近原则,如果要访问外部类成员,访问方法和上面的一样,外部类名.this.成员名。

静态内部类

静态内部类和成员内部类的定义类似,但要使用static修饰,所以称为静态内部类。静态内部类不再依附于Outer的实例,而是一个完全独立的类,因此无法引用Outer.this的方式调用。但它可以访问Outer类的private静态字段和静态方法,如果我们把静态内部类移到Outer类之外,就失去了访问private的权限。

public class StaticInnerClass {
    public static void main(String[] args) {
        Outer6 outer6 = new Outer6();
        outer6.fun1();

        //外部其他类访问静态内部类
        //静态内部类可以直接通过类名访问
        Outer6.Fun fun1 = new Outer6.Fun();
        fun1.show();

        //通过定义一个方法返回静态内部类
        Outer6.Fun fun2 = outer6.getFun();
        fun2.show();
    }
}

class Outer6 {
    private static int a = 99;
    private static String str = "java";
    
    static class Fun {
        public static int a = 999;
        public void show() {
            System.out.println(str);
            System.out.println(a); //同名成员遵循就近原则
            System.out.println(Outer6.a); //通过 外部类名.成员名访问
        }
    }

    public void fun1() {
        Fun fun = new Fun();
        fun.show();
    }
    public Fun getFun() {
        return new Fun();
    }
}

静态内部类中只能访问静态外部类的静态属性和方法文章来源地址https://www.toymoban.com/news/detail-693337.html

到了这里,关于【JavaSE】内部类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaSE——初始java

    目录 一.Java是什么 二.Java语言的特性 1. 简单性 2. 面相对象 3. 分布式(微服务) 4. 健壮性 5. 安全性 6. 体系结构中立 7. 可移植性 8. 解释性 9. 高性能 10. 多线程 11. 动态性 三.JDK环境配置 1.简介 2.安装  3.配置 4.检验 四.第一个Java程序 1.初始程序 2.运行程序 3.JDK、JRE、JVM三者之间的

    2023年04月08日
    浏览(38)
  • 【JavaSE】初识java

    目录 Java语言概述 Java是什么 Java语言重要性 语言广泛使用程度 工作领域 在校招中的岗位需求​编辑 Java语言发展简史 Java语言特性 ​编辑Java开发环境安装 初识Java的main方法 main方法示例 运行Java程序 JDK、JRE、JVM之间的关系 注释 基本规则 注释规范 标识符 ​编辑 总结

    2024年02月16日
    浏览(37)
  • 【JavaSE】Java的反射机制

    1.java反射机制 1.1简介 被视为动态语言的关键,允许程序在执行期间,借助于RefectionAPI取得任何类的内部信息。在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个类对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方

    2024年04月26日
    浏览(36)
  • 【JavaSE】第一个Java程序

    在JavaSE的系列中,将从第一个Java程序开始叙述,系统的把JavaSE的内容总结一次。毕竟这是第二次学习JavaSE的内容,因此感触也相对比较深一些。在JavaSE的初步计划中,大概有十一到十三篇文章,大致有:第一个Java程序、变量与运算符、流程控制、面向对象(封装、继承、多

    2024年01月22日
    浏览(38)
  • 【JavaSE】java刷题--数组练习

    本篇讲解了一些数组相关题目(主要以代码的形式呈现),主要目的在于巩固数组相关知识。 上一篇 数组 讲解了一维数组和二维数组的基础知识~ 欢迎关注个人主页:逸狼 创造不易,可以点点赞吗~ 如有错误,欢迎指出~ 思路 首先要判断 空指针和空数组 的情况,利用 字符

    2024年04月10日
    浏览(43)
  • 【JavaSE】Java方法的使用

    【本节目标】 1. 掌握方法的定义以及使用 2. 掌握方法传参 3. 掌握方法重载 4. 掌握递归 目录 1.方法概念及使用 1.1什么是方法(method) 1.2 方法定义 1.3 方法调用的执行过程 1.4 实参和形参的关系 2. 方法重载 2.1 为什么需要方法重载 2.2 方法重载概念 3. 递归 3.1 生活中的故事 3.2 递

    2024年02月12日
    浏览(38)
  • Java面试整理(二)《JavaSE》

    说明:我会根据我自己的经验,给每个内容标注重要程度,共有三个等级:低、中、高。仅个人参考意见。 JVM是Java Virtual Machine的缩写,是用于运行Java字节码的虚拟机,JVM是运行在操作系统之上,这也是Java程序为什么能够运行在不同的平台或操作系统的原因。 JVM是Java语言

    2024年02月09日
    浏览(32)
  • 【JavaSE】Java基础语法(十三):Java 中的集合(十分全面)

    List (对付顺序的好帮⼿): 存储的元素是有序的、可重复的。 Set (注重独⼀⽆⼆的性质): 存储的元素是⽆序的、不可重复的。 Queue (实现排队功能的叫号机): 按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的。 Map (⽤ key 来搜索的专家): 使⽤键值对(key-value)存

    2024年02月10日
    浏览(41)
  • 【JavaSE】Java基础语法(十八):接口

    接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。 Java中接口存在的两个意义 用来定义规范 用来做功能的拓展 接口用interface修饰 类实现接口用implements表示 接口不能实例化 我们可以创建接口的实现类对象使用 接口的子类 要么重写接口中的所有抽

    2024年02月06日
    浏览(56)
  • 【JavaSE】Java入门九(异常详解)

    目录 异常  1.Java中异常的体系结构 2.异常的处理 3.自定义异常类        在Java中,将程序执行过程中发生的不正常行为称为异常,C语言中没有这个概念,接下来我们重点需要掌握异常处理体系(try, catch, throw, finally)以及如何自定义异常类。 异常的种类繁多,Java内部维护了

    2024年02月03日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包