4内部类&Lambda 匿名内部类和Lambda表达式的区别

本文详细介绍了Java中的内部类,包括成员内部类、静态内部类、私有内部类和局部内部类,以及它们的创建和访问特点。同时,文章探讨了匿名内部类的使用场景和创建格式。此外,还讲解了Lambda表达式的概念、格式、前提条件和不同参数类型的使用实例,展示了Lambda如何简化代码。最后,对比了匿名内部类和Lambda表达式的异同,强调了它们在实际编程中的适用场景。
摘要由CSDN通过智能技术生成

JavaSE进阶-day04

一、 内部类

1.内部类-成员内部类【了解】(视频01) (7‘’)
  • 内部类概述

    在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类

    public class Outer {
    	
        //Inner 被称为内部类
        public class Inner {
        }
        
    }
    
  • 成员内部类的创建格式

    外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();

    例子:Outer.Inner i = new Outer().new Inner();

    public class Test1Inner {
        public static void main(String[] args) {
            /*
                创建内部类对象的格式:
    
                    外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();
             */
            Outer.Inner i = new Outer().new Inner();
            System.out.println(i.num);
            i.show();
        }
    }
    
    class Outer {
    
        class Inner {
            int num = 10;
    
            public void show(){
                System.out.println("Inner..show");
            }
        }
    }
    
  • 内部类的访问特点

    内部类访问外部类:内部类可以直接访问外部类的成员,包括私有

    class Outer {
    
        private int a = 10;
        
        private void method(){
            System.out.println("Outer..method");
        }
    
        class Inner {
            int num = 10;
    
            public void show(){
                System.out.println("Inner..show");
                // 内部类, 访问外部类成员, 可以直接访问, 包括私有
                System.out.println(a);
                method();
            }
        }
    }
    

    外部类访问内部类: 外部类要访问内部类的成员,必须创建对象

    class Outer {
        
        class Inner {
            int num = 10;
        }
    
        public void method2(){
    		//外部类 使用 内部类,正常创建对象即可
            Inner inner = new Inner();
            System.out.println(inner.num);
        }
    
    }
    
  • 内部类的定义位置

    成员内部类: 在类的成员位置定义

    局部内部类: 在类的局部位置定义。 如:方法中定义的类

自由练习-8分钟(成员内部类的创建格式)
2.私有成员内部类-静态内部类【了解】(视频02) (7‘’)
  • private

    私有成员内部类访问:只能在自己所在的外部类中创建对象访问。

    public class Test2Innerclass {
        /*
            私有成员内部类演示
         */
        public static void main(String[] args) {
            Outer o = new Outer();
            o.method();
        }
    }
    
    class Outer {
        private class Inner {
            public void show(){
                System.out.println("inner..show");
            }
        }
    
        public void method(){
            Inner i = new Inner();
            i.show();
        }
    }
    
  • static

    静态成员内部类访问格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();

    静态成员内部类中的静态方法:外部类名.内部类名.方法名();

    public class Test3Innerclass {
        /*
            静态成员内部类演示
         */
        public static void main(String[] args) {
            // 外部类名.内部类名 对象名 = new 外部类名.内部类名();
            Outer.Inner oi = new Outer.Inner();
            oi.show();
    		
            //静态成员内部类中的静态方法
            Outer.Inner.method();
        }
    }
    
    class Outer {
        static class Inner {
            public void show(){
                System.out.println("inner..show");
            }
    
            public static void method(){
                System.out.println("inner..method");
            }
        }
    }
    
自由练习-8分钟
3.局部内部类【了解】(视频03) (4‘’)

局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用

该类可以直接访问外部类的成员,也可以访问方法内的局部变量

public class Test4Innerclass {
    /*
        局部内部类:

            编写位置: 方法中
            访问方式: 只能在方法中, 创建对象并访问
     */
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}


class Outer {

    private int a = 10;

    public void method(){

        int b = 20;

        class Inner {
            public void show(){
                System.out.println("show...");
                
                //可以直接访问外部类的成员,也可以访问方法内的局部变量
                System.out.println(a);
                System.out.println(b);
            }
        }

        Inner i = new Inner();
        i.show();

    }

}
小结【了解】
内部类说明如果获取对象
成员内部类普通的成员内部类(定义在成员位置)Outer.Inner i = new Outer().new Inner();
静态内部类使用static修饰的成员内部类Outer.Inner oi = new Outer.Inner();
私有内部类使用private修饰的成员内部类Inner i = new Inner(); (注意:只能在本类中获取对象 )
局部内部类定义在方法中Inner i = new Inner(); (注意:只能在本方法中获取对象)
4.匿名内部类【重点】(视频04) (12‘’)

概述:匿名内部类本质上是一个特殊的局部内部类(定义在方法内部)

前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类

public class Test5Innerclass {
    /*
        匿名内部类:
        	是一个继承了该类或者实现了该接口的子类匿名对象

            前提: 需要存在类\接口
            格式:
                    new 类名 \ 接口名 (){
                        重写方法
                    }
     */
    public static void main(String[] args) {
  
        // 匿名内部类的理解: 将继承\实现, 方法重写, 创建对象, 放在了一步进行.
        // 解释: 实现了Inter接口的, 一个实现类对象.
        new Inter() {
            @Override
            public void show() {
                System.out.println("我是匿名内部类中的show方法");
            }
        }.show();
        
    }
}

interface Inter {
    void show();
}

多态的形式接收、匿名内部类对象

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

        // 情况: 接口中存在多个方法,可以使用多态的形式接收,匿名内部类的实现对象
        Inter2 i = new Inter2() {
            @Override
            public void show1() {
                System.out.println("show1...");
            }

            @Override
            public void show2() {
                System.out.println("show2...");
            }
        };

        i.show1();
        i.show2();
    }
}


interface Inter2 {
    void show1();
    void show2();
}
5.匿名内部类的使用场景【重点】(视频05) (4‘’)

使用场景:匿名内部类可以直接做为参数传递给其他方法

public class TestSwimming {
    public static void main(String[] args) {
        goSwimming(new Swimming() {
            @Override
            public void swim() {
                System.out.println("铁汁, 我们去游泳吧");
            }
        });
    }

    /**
     * 使用接口的方法
     */
    public static void goSwimming(Swimming swimming){
        swimming.swim();
    }
}

/*
    游泳接口
 */
interface Swimming {
    void swim();
}
自由练习-8分钟

二、Lambda表达式

1.Lambda初体验和函数式编程思想【】(视频06) (7‘’)
  • Lambda初体验

    public class TestSwimming {
        public static void main(String[] args) {
            goSwimming(() -> {System.out.println("铁汁, 我们去游泳吧");});
        }
    	
        /**
         * 使用接口的方法
         */
        public static void goSwimming(Swimming swimming) {
            swimming.swim();
        }
    }
    
    /*
        游泳接口
     */
    interface Swimming {
        void swim();
    }
    
  • 函数式编程思想

    面向对象编程思想强调”通过对象的形式做事情”

    函数式编程思想强调”做什么,而不是以什么形式去做

2.Lambda表达式的格式说明和前提条件【应用】(视频07) (8‘’)
  • Lambda表达式的格式

    • 组成Lambda表达式的三要素: 形式参数箭头代码块

    • 格式:(形式参数) -> {代码块}

      形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可

      ->:由英文中画线和大于符号组成,固定写法。代表指向动作

      代码块:是我们具体要做的事情,也就是以前我们写的方法体内容

  • Lambda表达式的前提条件

    1. 一个接口
    2. 接口中有且仅有一个抽象方法
  • Lambda练习-无参数无返回值

    public class TestLambda {
        /*
            Lambda表达式的使用前提
                1. 一个接口
                2. 接口中有且仅有一个抽象方法
    
            练习1:
                1. 编写一个接口(ShowHandler)
                2. 在该接口中存在一个抽象方法(show),该方法是无参数无返回值
                3. 在测试类(ShowHandlerDemo)中存在一个方法(useShowHandler)
                            方法的的参数是ShowHandler类型的
                            在方法内部调用了ShowHandler的show方法
         */
        public static void main(String[] args) {
            useShowHandler(new ShowHandler() {
                @Override
                public void show() {
                    System.out.println("我是匿名内部类中的show方法");
                }
            });
    
            // Lambda实现
            useShowHandler(() -> {System.out.println("我是Lambda中的show方法")});
        }
    
        public static void useShowHandler(ShowHandler showHandler){
            showHandler.show();
        }
    
    }
    
    interface ShowHandler {
        void show();
    }
    
3.Lambda练习-带参数无返回值【应用】(视频08) (5‘’)
public class StringHandlerDemo {
    /*
        1.首先存在一个接口(StringHandler)
        2.在该接口中存在一个抽象方法(printMessage),该方法是有参数无返回值
        3.在测试类(StringHandlerDemo)中存在一个方法(useStringHandler)
                方法的的参数是StringHandler类型的
                在方法内部调用了StringHandler的printMessage方法
     */
    public static void main(String[] args) {
        useStringHandler(new StringHandler() {
            @Override
            public void printMessage(String msg) {
                System.out.println("我是匿名内部类" + msg);
            }
        });

        // Lambda实现
        useStringHandler((msg) -> {
            System.out.println("我是Lambda表达式" + msg);
        });
    }

    public static void useStringHandler(StringHandler stringHandler) {
        stringHandler.printMessage("itheima");
    }
}

interface StringHandler {
    void printMessage(String msg);
}
自由练习-8分钟
4.Lambda练习-无参数有返回值【应用】(视频09) (5‘’)
public class RandomNumHandlerDemo {
    /*
        1. 首先存在一个接口(RandomNumHandler)
        2. 在该接口中存在一个抽象方法(getNumber),该方法是无参数但是有返回值
        3. 在测试类(RandomNumHandlerDemo)中存在一个方法(useRandomNumHandler)
                方法的的参数是RandomNumHandler类型的
                在方法内部调用了RandomNumHandler的getNumber方法
     */
    public static void main(String[] args) {
        useRandomNumHandler(new RandomNumHandler() {
            @Override
            public int getNumber() {
                Random r = new Random();
                int num = r.nextInt(10) + 1;
                return num;
            }
        });

        useRandomNumHandler( () -> {
                Random r = new Random();
                int num = r.nextInt(10) + 1;
                return num;
                // 注意: 如果lambda所操作的接口中的方法, 有返回值, 一定要通过return语句, 将结果返回
                // 否则会出现编译错误
        } );
    }

    public static void useRandomNumHandler(RandomNumHandler randomNumHandler){
        int result = randomNumHandler.getNumber();
        System.out.println(result);
    }
}

interface RandomNumHandler {
    int getNumber();
}
自由练习-8分钟
5.Lambda练习-带参数带返回值【应用】(视频10) (4‘’)
public class CalculatorDemo {
    /*
        1. 首先存在一个接口(Calculator)
        2. 在该接口中存在一个抽象方法(calc),该方法是有参数也有返回值
        3. 在测试类(CalculatorDemo)中存在一个方法(useCalculator)
            方法的的参数是Calculator类型的
            在方法内部调用了Calculator的calc方法

     */
    public static void main(String[] args) {
        useCalculator(new Calculator() {
            @Override
            public int calc(int a, int b) {
                return a + b;
            }
        });

        useCalculator((int a, int b)->{
            return a + b;
        });
    }

    public static void useCalculator(Calculator calculator) {
        int result = calculator.calc(10, 20);
        System.out.println(result);
    }
}

interface Calculator {
    int calc(int a, int b);
}
自由练习-8分钟
6.Lambda省略模式【了解】(视频11) (7‘’)

省略规则

参数类型可以省略。但是有多个参数的情况下,不能只省略一个

如果参数有且仅有一个,那么小括号可以省略

如果代码块的语句只有一条,可以省略大括号,分号,return

public class Test6 {
    public static void main(String[] args) {
        /*useInter( (double a, double b) -> {
            return a + b;
        });*/
		
        
        //参数类型可以省略。但是有多个参数的情况下,不能只省略一个
        //如果代码块的语句只有一条,可以省略大括号,分号,return
        useInter((a, b) ->a + b);
    }

    public static void useInter(Inter i) {
        double result = i.method(12.3, 22.3);
        System.out.println(result);
    }

}

interface Inter {
    // 用于计算 a + b 的结果并返回
    double method(double a, double b);
}
public class StringHandlerDemo {

    public static void main(String[] args) {
        useStringHandler(new StringHandler() {
            @Override
            public void printMessage(String msg) {
                System.out.println("我是匿名内部类" + msg);
            }
        });

        // Lambda实现 - 如果参数有且仅有一个,那么小括号可以省略
        useStringHandler(msg -> System.out.println("我是Lambda表达式" + msg));
    }

    public static void useStringHandler(StringHandler stringHandler) {
        stringHandler.printMessage("itheima");
    }
}

interface StringHandler {
    void printMessage(String msg);
}
自由练习-8分钟

三、匿名内部类和Lambda表达式的区别

1.匿名内部类和Lambda表达式的区别【了解】(视频12) (5‘’)
  • 所需类型不同

    匿名内部类:可以是接口,也可以是抽象类,还可以是具体类

    Lambda表达式:只能是接口

  • 使用限制不同

    如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类

    如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式

  • 实现原理不同

    匿名内部类:编译之后,产生一个单独的.class字节码文件

    Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

InLoadwetrust

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值