JAVA 基础进阶 内部类 函数式编程思想

2 今日内容

1、内部类(重点)

2、lambda表达式(重点)

3 内部类

3.1 内部类入门

概述

概述:就是把一个类定义到了另外一个类的内部,那么这个类就被称之为内部类。比如: 把A定义到了B中,那么A就是内部类,B被称之为外部类

示例代码:

public class B {	// 外部类
    
    class A {		// 内部类
        
    }
    
}

编译完毕以后的字节码文件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VWuyvy9a-1619333391481)(images/image-20210421095139804.png)]

访问特点
  • 内部类和外部类之间:内部类可以直接去使用外部类的成员,包含私有的。但是外部类要想访问内部类的成员就需要创建对象。
  • 其他的类访问内部类:创建内部类的对象

创建格式:

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

按照定义位置的不同可以分为两种:

1、局部内部类:就是把这个内部类定义在外部类的局部位置(方法中)

2、成员内部类:就是把这个内部类定义在外部类的成员位置(类中访问外)

3.2 成员内部类

常见的修饰符:

1、private:其他类无法进行访问

2、static:其他类是可以进行访问的,但是创建的对象格式和之前不同

示例代码:

public class Outer {			// 外部类
    
    static class Inner {		// 被static修饰的内部类
        
    }
    
}

// 其他类
public class OuterDemo {
    
    public static void main(String[] args) {
        
        // 创建Inner的对象
        Outer.Inner oi = new Outer.Inner() ;
        
    }
    
}

创建对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();

3.3 局部内部类

概述:就是把一个类定义在了另外一个类的方法中

特点:只能在这个方法中去使用这个内部类

示例代码:

public class Outer {
    
    public void show() {
        
        // 局部内部类
        class Inner {
            
            public void method() {
                System.out.println("Inner....method......") ;
            }
            
        }
        
        // 创建Inner对象
        Inner i = new Inner();
        i.method();
        
    }
    
}

3.4 面试题

public class Outer {

    int number = 45 ;

    class Inner {

        int number = 10 ;

        public void show(){
            int number = 23 ;
            System.out.println(number);                         // 在这里输出23
            System.out.println(this.number);                    // 这里输出10
            // System.out.println(new Outer().number);              // 这里输出45
            System.out.println(Outer.this.number);
        }

    }

    public static void main(String[] args) {

        Outer.Inner oi = new Outer().new Inner() ;
        oi.show();

    }

}

3.5 匿名内部类(重点)

概述:是一种特殊的内部类

前提: 存在一个类或者接口

格式:

new 类名/接口名() {
  重写方法  
};

本质:是继承某一个类或者实现了某一个接口的子类对象

示例代码:

public interface Inter {
    public abstract void show();
}

// 实现了Inter接口的子类对象
new Inter(){
    public  void show() {
        System.out.println("Inter...show.....");
    }
};

// 使用匿名内部类调用方法
new Inter(){
    public  void show() {
        System.out.println("Inter...show.....");
    }
}.show();

// 把匿名内部类赋值给一个Inter类型的变量
Inter inter = new Inter(){
    public  void show() {
        System.out.println("Inter...show.....");
    }
};
inter.show();

使用场景:就是把匿名内部类作为方法参数传递

示例代码:

public class InterDemo01 {

    /*
        new 类名/接口名() {
          重写方法
        };
     */
    public static void main(String[] args) {

        // 传递一个Inter的实现类对象
        method(new InterImpl());

        System.out.println("---------------------------------------");

        // 传递一个Inter的匿名内部类
        method(new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类作为方法参数传递");
            }
        });

    }

    // method方法需要一个Inter类型的参数
    public static void method(Inter inter) {
        inter.show();
    }

}

4 lambda表达式

4.1 函数式编程思想

为什么要存在lambda表达式?

使用匿名内部类作为方法参数传递的时候,代码看起来还是相对比较繁琐的!为了简化我们开发,JDK1.8以后就提供了一种匿名内部类的简化格式就是lambda表达式。

匿名内部类和lambda表达式到底有什么样的区别?

1、语法不同

2、编程思想不同

  • 匿名内部类使用的思想: 面向对象思想
  • lambda表达式的编程思想:函数式编程思想

3、前提不同

  • 匿名内部类:前提是存在一个接口或者类(可以是抽象类也可以非抽象类),并且接口中可以存在多个抽象方法
  • lambda表达式:必须存在一个接口,并且这个接口中除了Object类中的方法的抽象表示形式以外,有且仅有一个抽象方法。

4、原理不同

  • 匿名内部类: 编译完毕以后可以生成一个.class文件
  • lambda表达式: 编译完毕以后不存在对应的.class文件

面向对象思想:关注点是谁来做某一件事情,做某一件事情之前,首先需要找到做这件事情的人(对象)。

函数式编程思想:关注点是做什么,关注的是结果,直接谁来做这件事情无所谓。

初体验

public class InterDemo01 {

    public static void main(String[] args) {

        // 传递一个Inter的匿名内部类
        method(new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类作为方法参数传递");
            }
        });
        
        System.out.println("---------------------------------------");
		
        // 通过lambda表达式进行调用
		method( () -> { System.out.println("匿名内部类作为方法参数传递"); });

    }

    // method方法需要一个Inter类型的参数
    public static void method(Inter inter) {
        inter.show();
    }

}

4.2 语法规则

Lambda表达式是Jdk1.8提出了一种新的表达式语法。Lambda表达式的格式如下所示:

(参数类型 参数名称) -> { 方法体代码 }

格式由3个部分组成:

组成部分说明信息
(参数类型 参数名称)小括号内的语法与接口中所定义的方法参数列表一致:如果接口方法无参数则留空;多个参数则用","分隔
->是新引入的语法格式,代表指向动作
{ }大括号内的语法与传统方法体要求基本一致

前提:必须存在一个接口,并且这个接口中除了Object类中的方法的抽象表示形式以外,有且仅有一个抽象方法。这样的接口,我们常常将其称之为函数式接口

代码演示:

public interface Inter {							// 接口

    public abstract void show();					// 自定义的抽象方法
    public abstract boolean equals(Object obj) ;	// Object类中equals方法的抽象表示形式

}

public class InterDemo01 {

    public static void main(String[] args) {
        show(() -> { System.out.println("haha....."); });		// 调用show方法传递了一个lambda表达式
    }

    public static void show(Inter inter) {
        inter.show();
    }

}

4.3 练习题

lambda表达式是站在函数式编程的角度而言,关注的就是做什么。做什么的实现是通过方法进行实现,也就说关注点就是方法。

方法的分类:

1、无参数无返回值

2、无参数有返回值

案例说明:

  1. 首先存在一个接口(RandomNumHandler)

  2. 在该接口中存在一个抽象方法(getNumber),该方法是无参数但是有返回值

  3. 在测试类(RandomNumHandlerDemo)中存在一个方法(useRandomNumHandler),方法的的参数是RandomNumHandler类型的,

    在方法内部调用了RandomNumHandler的getNumber方法

代码演示:

// 接口
public interface RandomNumHandler {

    // 无参数但是有返回值的方法
    public abstract int getNumber() ;

}

//  测试类
public class RandomNumHandlerDemo {

    public static void main(String[] args) {

        // 调用useRandomNumHandler方法获取一个int类的随机数[0-100]
        // 匿名内部类
        useRandomNumHandler(new RandomNumHandler() {

            @Override
            public int getNumber() {
                // 随机数(0-100)
                Random random = new Random();
                int nextInt = random.nextInt(101);
                return nextInt;
            }

        });

        System.out.println("-------------------------------------------");

        // lambda表达式
        useRandomNumHandler(() -> {
            // 随机数(0-100)
            Random random = new Random();
            int nextInt = random.nextInt(101);
            return nextInt;
        });

    }

    // 使用RandomNumHandler
    public static void useRandomNumHandler(RandomNumHandler randomNumHandler) {
        int number = randomNumHandler.getNumber();      // 调用RandomNumHandler中的getNumber方法
        System.out.println(number);                     // 把结果输入到控制台
    }

}

3、有参数无返回值

代码演示:

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((String msg) -> { System.out.println("我是匿名内部类" + msg);});
        
    }

    // 使用接口的方式
    public static void useStringHandler(StringHandler stringHandler){
        stringHandler.printMessage("itheima");
    }
    
}

// 接口
interface StringHandler {
    void printMessage(String msg);
}

4、有参数有返回值

案例说明:

  1. 首先存在一个接口(Calculator)
  2. 在该接口中存在一个抽象方法(calc),该方法是有参数也有返回值
  3. 在测试类(CalculatorDemo)中存在一个方法(useCalculator),方法的的参数是Calculator类型的,在方法内部调用了Calculator的calc方法

代码演示:

// 接口定义
public interface Calculator {

    // 有参数有返回值的方法
    public abstract int calc(int a , int b) ;

}

// 测试类
public class CalculatorDemo {

    public static void main(String[] args) {

        // 在main方法中去调用useCalculator这个方法
        // 1、匿名内部类的方式
        useCalculator(new Calculator() {
            @Override
            public int calc(int a, int b) {     // 做加法运算
                return a + b ;
            }
        }) ;

        System.out.println("--------------------------------------------");

        // 2、lambda表达式的方式
        useCalculator((int a , int b) -> {
            return a + b ;
        });

    }

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

}

4.4 省略的语法规则

Lambda表达式在使用的时候,也存在省略格式。它的省略规则如下所示:

  1. 参数类型可以省略,但是有多个参数的情况下,不能只省略一个
  2. 如果参数有且仅有一个,那么小括号可以省略
  3. 如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值