首页 > 编程语言 >Java四大内部类之局部内部类、匿名内部类

Java四大内部类之局部内部类、匿名内部类

时间:2024-12-17 16:29:22浏览次数:5  
标签:Java 内部 void public 匿名 println class

目录

一、局部内部类

二、匿名内部类

基于接口的匿名内部类

基于类的匿名内部类

三、匿名内部类的实践


类的五大成员:属性、方法、构造器、代码块、内部类

内部类的分类

定义在外部类局部位置上(比如说方法内):
  • 局部内部类(有类名)
  • 匿名内部类(没有类名)
定义在外部类的成员位置上:
  • 成员内部类(没用static修饰)
  • 静态内部类(使用static修饰)

一、局部内部类

说明:局部内部类是定义在外部类的局部位置,比如方法种,并且有类名
  1. 可以直接访问外部类的所有成员,包含私有的
  2. 不能添加访问修饰符,因为它的地位就是一个局部变量,局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
  3. 作用域:仅仅在定义它的方法或代码块中。
  4. 局部内部类---访问----》外部类的成员 【访问方式:直接访问】
  5. 外部类---访问---》局部内部类的成员
    1. 访问方式:创建对象,再访问(注意:必须再作用域内)
package com.hspedu.innerclass;
/**
 * 演示局部内部类的使用
 */
public class LocalInnerClass {
    public static void main(String[] args) {
        //演示一遍
        Outer02 outer02 = new Outer02();
        outer02.m1();
    }
}

class Outer02 {//外部类
    private int n1 = 100;
    private void m2() {
        System.out.println("Outer02 m2()");
    }//私有方法
    public void m1() {//方法
        //1.局部内部类是定义在外部类的局部位置,通常在方法
        //3.不能添加访问修饰符,但是可以使用final修饰
        //4.作用域:仅仅在定义它的方法或代码块中
        class Inner02 {//局部内部类(本质仍然是一个类)
            //2.可以直接访问外部类的所有成员,包含私有的
            public void f1() {
                //5.局部内部类可以直接访问外部类的成员,比如下面 外部类n1 和 m2()
                System.out.println("n1=" + n1);
                m2();
            }
        }
        //6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
        Inner02 inner02 = new Inner02();
        inner02.f1();
    }

}

输出结果

  1. 外部其他类---》不能访问---》局部内部类(因为 局部内部类地位是一个局部变量)
  2. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

Outer02.this 本质就是外部类的对象,即哪个对象调用了m1,Outer02.this就是哪个对象

输出结果:

二、匿名内部类

本质是类 内部类 该类没有名字 同时还是一个对象

说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

匿名内部类的基本语法

new类或接口(参数列表){

        类体

};

基于接口的匿名内部类

未使用匿名内部类简化开发之前

package com.hspedu.innerclass;

/**
 * 演示匿名内部类的使用
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}

class Outer04 {//外部类
    private int n1 = 10;//属性
    public void method() {//方法
        //基于接口的匿名内部类
        //1.需求:想使用IA接口,并创建对象
        //2.传统方式,是写一个类,实现该接口,并创建对象
        //3.需求是 Tiger/Dog 类只是使用一次,后面不使用
        //4.可以使用匿名内部类来简化开发
        IA tiger = new Tiger();
        tiger.cry();
    }
}

interface IA {//接口
    public void cry();
}
class Tiger implements IA {

    @Override
    public void cry() {
        System.out.println("老虎叫-----");
    }
}

class Dog implements IA {

    @Override
    public void cry() {
        System.out.println("小狗叫-----");
    }
}
class Father {//类
    public Father(String name) {//构造器
    }
    public void test() {//方法
    }
}

使用匿名内部类简化开发之后

package com.hspedu.innerclass;

/**
 * 演示匿名内部类的使用
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}

class Outer04 {//外部类
    private int n1 = 10;//属性
    public void method() {//方法
        //基于接口的匿名内部类
        //1.需求:想使用IA接口,并创建对象
        //2.传统方式,是写一个类,实现该接口,并创建对象
        //3.需求是 Tiger/Dog 类只是使用一次,后面不使用
        //4.可以使用匿名内部类来简化开发
        //5.tiger的编译类型 ? IA
        //6.tiger的运行类型 ? 就是匿名内部类 XXXX => Outer04$1
        /*
            我们看底层 会分配 类名 Outer04$1
            class XXXX implements IA {
                @Override
                public void cry() {
                    System.out.println("老虎叫----");
                }
            };
         */
        //7.jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1实例,并且把地址
        //  返回给 tiger
        //8.匿名内部类使用一次,就不能再使用
        IA tiger = new IA(){
            @Override
            public void cry() {
                System.out.println("老虎叫----");
            }
        };
        tiger.cry();
        System.out.println("tiger的运行类型:" + tiger.getClass());

//        IA tiger = new Tiger();
//        tiger.cry();
    }
}

interface IA {//接口
    public void cry();
}
//class Tiger implements IA {
//
//    @Override
//    public void cry() {
//        System.out.println("老虎叫-----");
//    }
//}
//
//class Dog implements IA {
//
//    @Override
//    public void cry() {
//        System.out.println("小狗叫-----");
//    }
//}
class Father {//类
    public Father(String name) {//构造器
    }
    public void test() {//方法
    }
}

要注意这段代码并不是直接创建接口的实例,而是创建了一个实现类该接口的类的实例

这个类的类名由jdk分配

匿名内部类的代码:

    IA tiger = new IA(){
            @Override
            public void cry() {
                System.out.println("老虎叫----");
            }
        };

实际上等价于下面的代码

// 显式定义一个类实现接口
class Outer04$1 implements IA {
    @Override
    public void cry() {
        System.out.println("老虎叫----");
    }
}

// 在主方法中创建 MyPrinter 的对象
IA tiger = new Outer04$1();

基于类的匿名内部类

class Father {//类
    public Father(String name) {//构造器
    }
    public void test() {//方法
    }
}
    //演示基于类的匿名内部类
    //分析
    //1.father编译类型 Father
    //2.father运行类型 Outer04$2
    //3.底层会创建匿名内部类
    /*
        class Outer04$2 extends Father{
            @Override
            public void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        }
     */
    //4.同时也直接返回了 匿名内部类 Outer04$2
    //注意("jack") 参数列表会传递给构造器
    Father father = new Father("jack"){
        @Override
        public void test() {
            System.out.println("匿名内部类重写了test方法");
        }
    };
    System.out.println("father对象的运行类型=" + father.getClass());//Outer04$2
    father.test();

Father father = new Father("jack"){
        @Override
        public void test() {
            System.out.println("匿名内部类重写了test方法");
        }
    };

等价于

    class Outer04$2 extends Father{
            @Override
            public void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        }
    Father father = new Outer04$2("jack");

基于类的匿名内部类的第二种方式,这里我调用的是Person类

//直接调用,匿名内部类本身也是返回对象
//class 匿名内部类 extends Person {}
new Person(){
    @Override
    public void hi() {
        System.out.println("匿名内部类重写了 hi方法,zzzzzz");
    }
}.hi();
package com.hspedu.innerclass;

public class AnonymousInnerClassDetail {
    public static void main(String[] args) {
        Outer05 outer05 = new Outer05();
        outer05.f1();
        //外部其他类---不能访问----》匿名内部类
        System.out.println("main hashcode=" + outer05);
    }
}

class Outer05 {
    private int n1 = 99;
    public void f1() {
        //创建一个基于类的匿名内部类
        //不能添加访问修饰符,因为它的地位就是一个局部变量
        //作用域:仅仅在定义它的方法或代码块中
        Person p = new Person(){
            private int n1 = 88;
            @Override
            public void hi() {
                //可以直接访问外部类的所有成员,包含私有的
                //如果外部类和匿名内部类的成员重名时,匿名内部类访问的话
                //默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员) 去访问
                System.out.println("匿名内部类重写了 hi方法 n1=" + n1 + "  外部内的n1=" + Outer05.this.n1);
                //Outer05.this 就是调用 f1的 对象
                System.out.println("Outer05.this hashcode=" + Outer05.this);
            }
        };
        p.hi();//动态绑定,运行类型是Outer05$1

//        //也可以直接调用,匿名内部类本身也是返回对象
//        //class 匿名内部类 extends Person {}
//        new Person(){
//            @Override
//            public void hi() {
//                System.out.println("匿名内部类重写了 hi方法,zzzzzz");
//            }
//
//            @Override
//            public void ok(String str) {
//                super.ok(str);
//            }
//        }.ok("jack");

    }
}

class Person {//类
    public void hi(){
        System.out.println("Person hi()");
    }
    public void ok(String str){
        System.out.println("Person ok()" + str);
    }
}
//抽象类/接口。。。

三、匿名内部类的实践

示例1

匿名内部类方式

public class InnerClassExercise01 {
    public static void main(String[] args) {

        //当作实参直接传递,简洁高效
        f1(new IL() {
            @Override
            public void show() {
                System.out.println("这是一幅画。。。");
            }
        }); 
    }
    //静态方法,形参是接口类型
    public static void f1(IL il){
        il.show();
    }
}
//接口
interface IL {
    void show();
}

传统方式

public class InnerClassExercise01 {
    public static void main(String[] args) {
        //传统写法
        f1(new Picture());
    }
    //静态方法,形参是接口类型
    public static void f1(IL il){
        il.show();
    }
}
//接口
interface IL {
    void show();
}

//类->实现IL =》编程领域(硬编码)
class Picture implements IL {

    @Override
    public void show() {
        System.out.println("这是一幅名画。。。。");
    }
}

示例2

package com.hspedu.innerclass;

public class InnerClassExercise02 {
    public static void main(String[] args) {
        CellPhone cellPhone = new CellPhone();
        cellPhone.alarmClock(new Bell() {//匿名内部类
            @Override
            public void ring() {
                System.out.println("懒猪起床了");
            }
        });
    }
}

interface Bell{//接口
    void ring();//方法
}

class CellPhone{//类
    public void alarmClock(Bell bell){//形参是Bell接口类型
        bell.ring();//动态绑定
    }
}

标签:Java,内部,void,public,匿名,println,class
From: https://blog.csdn.net/jlihan/article/details/144521559

相关文章

  • 精通Java:如何在Windows中配置环境变量并轻松切换版本
    文章目录引言步骤1:安装Java1.1下载java1.2安装java步骤2:配置环境变量2.1配置JAVA_HOME2.2配置Path变量步骤3:验证配置3.1.打开命令提示符CMD3.2.验证java3.3验证Javac更换Java版本引言Java环境变量的配置是Java开发中一个重要的步骤。正确配置环境变量可以......
  • 【华为OD-E卷-寻找链表的中间结点 100分(python、java、c++、js、c)】
    【华为OD-E卷-寻找链表的中间结点100分(python、java、c++、js、c)】题目给定一个单链表L,请编写程序输出L中间结点保存的数据。如果有两个中间结点,则输出第二个中间结点保存的数据。例如:给定L为1→7→5,则输出应该为7;给定L为1→2→3→4,则输出应该为3;输入描述......
  • 【华为OD-E卷-字符串重新排序 字符串重新排列 100分(python、java、c++、js、c)】
    【华为OD-E卷-字符串重新排序字符串重新排列100分(python、java、c++、js、c)】题目给定一个字符串s,s包括以空格分隔的若干个单词,请对s进行如下处理后输出:1、单词内部调整:对每个单词字母重新按字典序排序2、单词间顺序调整:1)统计每个单词出现的次数,并按次数降序排列2)次......
  • Windows和Linux系统中安装JDK(Java Development Kit)
    一、在Windows系统中安装JDK下载JDK访问Oracle官方网站(https://www.oracle.com/java/technologies/javase-downloads.html)。根据你的操作系统(32位或64位)和需求,选择合适的JDK版本进行下载。例如,对于大多数普通开发,选择JavaSE(StandardEdition)的JDK安装包。运行安装程序......
  • JDK的常用java命令有哪些?
    java命令功能:用于运行已编译的Java程序(.class文件)。它通过加载Java虚拟机(JVM),然后执行字节码。示例:假设你有一个名为HelloWorld.class的文件,在命令行中进入该文件所在目录,然后输入javaHelloWorld(这里HelloWorld是主类名),就可以运行这个Java程序。如果程序有命令行参数,还可以在......
  • java poi 限定单元格只能输入数字
    importorg.apache.poi.ss.usermodel.*;importorg.apache.poi.ss.util.*;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;publicclassEasyPoiNumberValidation{publicstaticvoidmain(String[]args){Workbookworkbook=newXSSFWorkbook();......
  • 最新工作室内部的超级链接全自动挂机项目, 单号单微信日利1张
    蜂群最新推出的超级链接项目每日完成任务获取银币即可通过各种渠道兑换宝石宝石立刻可以变现包配工作室批量完成任务的脚本脚本可以多号批量操作也可以拿去推广脚本全自动完成任务,项目热度很大,目前市场还很大,项目方资金量也很充足,抓紧进场吃肉。抓住风口,猪都可以起飞......
  • 被裁后半月面试8家公司无果,凭借这份Java面试指南成功入职阿里
     前言上个月班上的好好的突然被通知"毕业了",现在工作也确实不好找。之前近一个月面了很多大大小小的公司降薪太严重都没考虑去,最后没办法本来都打算随便去一家了却偶然得到一个阿里的面试机会,足足面了七面(我太难了)因为我的工程项目经验基本为0所以被死磕Java,下面我简单说下......
  • 程序员面试必备的Java八股文,适合所有的Java求职者!
     说明本文分享Java后端真实高频面试题,有详细答案,保你稳过面试。题目包括:Java基础、多线程、JVM、数据库、Redis、Shiro、Spring、SpringBoot、MyBatis、MQ、ELK、SpringCloud、设计模式等。包含从简单到困难、从高频到低频的题目,适合所有Java求职者,包括:应届生、转行的、三......
  • Java Web项目部署教程简单实用
    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站学习总结1、掌握JAVA入门到进阶知识(持续写作中……)2、学会Oracle数据库入门到入土用法(创作中……)3、手把手教你开发炫酷的vbs脚本制作(完善中……)4、牛逼哄哄的IDEA......