ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

匿名内部类、函数式接口和Lambda

2022-05-16 00:00:52  阅读:122  来源: 互联网

标签:void 接口 匿名 test 方法 public Lambda


目录

匿名内部类,函数式接口和Lambda

1. 匿名内部类

1.1 接口 和 abstract 类复习
接口 interface 
	成员变量缺省属性: public static final
	成员方法缺省属性: public abstract

abstract 修饰的方法可以定义在哪些结构中???
	abstract 修饰类,一个是 interface 接口

一个 非 abstract 修饰的类 继承 abstract 类有什么要求???
一个 非 abstract 修饰的类 遵从 接口有什么要求???
	非 abstract 修饰的类必须实现 abstract 类内 或者 interface 接口内的所有 abstract 修饰方法
package com.qfedu.a_ait;

interface A {
	void test();
}

class TypeA implements A {

	@Override
	public void test() {
		System.out.println("遵从接口A必须实现的方法");
	}
	
}

abstract class BaseType {
	public abstract void testMethod();
}

class TypeB extends BaseType {

	@Override
	public void testMethod() {
		System.out.println("非 abstract 类继承 abstract 修饰类要求实现的方法");
	}
	
}
1.2 匿名内部类分析和操作实现
package com.qfedu.a_ait;

interface B {
	void test();
}

/*
TypeC 类名所代表的的内容是 类大括号里面的所有内容。

类大括号所有内容看做是一个类的【本体】
对于 TypeC 类对应的包含内容,实际上是在【实现】接口 B 要求的方法。
	请问类名重要吗???
当前类的主要目的是为了按照接口的要求,实现接口规定的方法,类名称呼不重要

【重点】
	在于实现接口中的方法!!!

类名不重要
	是否可以
	1. 保留必要的继承/遵从关系
	2. 完成方法体实现
	3. 可以实例化对象
	4. 满足方法的调用操作 
 */
class TypeC implements B {

	@Override
	public void test() {
		System.out.println("TypeC 类遵从接口B 实现 test方法");
	}
	
}

public class Demo2 {
	public static void main(String[] args) {
		new TypeC().test();
		
		/*
		 * 看一下 匿名内部类 基本操作方式
		 * B b 接口 B 对应的引用数据类型变量,可以存储 B 接口实现类对象地址
		 * new B() 
		 * 		【注意】这里没有实例化 B 接口对象,而是在描述以下内容
		 * 		1. new 需要在内存的堆区申请必要的数据空间,用于实例化对象使用,同时对当前数据空间进行擦除
		 * 		2. B() 看上去是一个 接口 B 的构造方法,实际上是在告知编译器,当前匿名内部类遵从的接口是 B 接口
		 * 			利用构造方法基本要求的格式形式 new + 构造方法。
		 * 			new B(); 实例化对象,同时告知编译器当前实例化对象数据类型是遵从接口 B 的
		 * 		【注意】没有类名!!!
		 * {} 里面的内容,就是一个遵从接口 B 实现类必须完成的方法内容,从这里也看出匿名类遵从的接口类型是 B 接口
		 * 
		 * 实例化对象赋值给接口 B 引用数据类型变量,方便后期
		 */
		B b = new B() {
			@Override
			public void test() {
				System.out.println("匿名内部类实现方法,实例化对象赋值给接口的引用数据类型变量,方便方法调用");
			}
		};
		
		b.test();
		
		/*
		 * 略微高阶一丢丢的方法
		 * 
		 * 王·渣男·某平
		 * 匿名内部类的匿名对象,直接调用方法
		 */
		new B() {
			
			@Override
			public void test() {
				System.out.println("匿名内部类的匿名对象,直接调用方法");
			}
		}.test();
		
		
		testInnerType(new TypeC());
		
		/*
		 * 匿名内部类的匿名对象直接作为方法的参数!!!
		 * JDK 1.8 之前流行操作!!!
		 */
		testInnerType(new B() {
			
			@Override
			public void test() {
				System.out.println("匿名内部类的匿名对象直接作为方法的参数!!!");
			}
		});
	}
	
	/**
	 * 当前方法所需参数是 接口 B 类型,实际上可以传入的参数是接口 B 的实现类对象
	 * 
	 * @param b B 接口类型,实际参数是接口B的实现类
	 */
	public static void testInnerType(B b) {
		b.test();
	}
	
	/*
	interface USB {
		void connect();
	}
	
	当前方法所需参数是 USB 接口的实现类, USB 设备。
	public static void useUseInterface(USB usb) {
		usb.connect();
	}
	 */

}

2. 函数式接口 【JDK 1.8 新特征】

2.1 基本语法
JDK 1.8 版本及其以上版本有效!!!
语法要求
	1. 使用注解 @FunctionalInterface 告知编译器当前接口是一个【函数式接口】
	2. 在函数式接口中,有且只允许出现一个尚未完成(No method body)的方法。
	3. 允许使用 default 关键字修饰方法,可以存在多个有方法体的方法[非必要]
package com.qfedu.b_fi;


/*
 * @FunctionalInterface
 * 		格式检查注解,要求当前接口中有且只有一个尚未完成(No Method Body)的方法 ,缺省属性为 public abstract 修饰方法
 * 		必须有一个尚未完成(No Method Body)的方法
 * 
 * 		函数式接口是一个对于接口类型约束操作,按照正常的接口操作使用。
 */
@FunctionalInterface
interface A {
	void test();
	
//	void test2();
	default void testDefault() {
		System.out.println("default 修饰默认方法,JDK 1.8 新特征");
	}
}

class TypeA implements A {
	@Override
	public void test() {
		System.out.println("正常操作");
	}
}

public class Demo1 {
	public static void main(String[] args) {
		new TypeA().test();
		
		new A() {
			
			@Override
			public void test() {
				System.out.println("匿名内部类的匿名对象,直接调用方法");
			}
		}.test();
	}
}
2.2 应知应会 JDK1.8 常用函数式接口
// 消费接口
interface Consumer<T> {
	void accept(T t)
}

// 生产接口
interface Supplier<T> {
	T get();
}

// 转换接口
interface Function<T, R> {
	R apply(T t); 
}

// 判断接口
interface Predicate<T> {
	boolean test(T t);
}

// 比较接口
interface Comparator<T> {
	int compare(T o1, T o2)
}

3. Lambda表达式

3.1 基本概述
Lambda 表达式是 JDK1.8 及其以上版本允许的技术点,类似于
	Objective-C Block代码块
	Python JS 匿名函数

核心目标:
	提高代码的执行效率!!!重点关注方法内容实现

技术使用前提:
	1. 常用于方法中!!!
	2. 要求方法参数是一个接口类型。
	3. 方法参数接口类型必须是一个函数式接口 @FunctionalInterface

四类:
	无参数无返回
	有参数有返回
	有参数无返回
	无参数有返回
3.2 无参数无返回 Lambda
	需要定义一个接口,并且接口中有且只有一个未完成的方法!!!就一个函数式接口,最好使用 @FunctionalInterface 开启检查
@FunctionalInterface
interface A {
	void test();
}
准备一个方法,方法参数是接口 A 类型
public static void testLambda(A a) {
	a.test();
}
package com.qfedu.c_lambda;

/*
 * 1. 完成 接口 A 实现类 通过该 实例化对象作为方法参数调用执行 testLambda
 * 2. 直接使用  接口 A 的匿名内部类的匿名对象作为 testLambda 方法参数
 * 3. Lambda 表达式操作
 */

@FunctionalInterface
interface A {
	void test();
}

class TypeA implements A {

	@Override
	public void test() {
		System.out.println("实现类 TypeA 实现完成 test 方法");
	}
	
}

public class Demo1 {
	/*
	 * JVM 执行 main 方法
	 */
	public static void main(String[] args) {
		// 方式一
		testLambda(new TypeA());
		
		// 方式二 JDK 1.8 之前
		testLambda(new A() {
			
			@Override
			public void test() {
				System.out.println("匿名内部类的匿名对象,直接作为方法的参数");
			}
		});
		
		/*
		 * 【重点】方式三 Lambda表达式
		 * () 对应当前 接口 A 中的 test 方法没有参数
		 * -> Java Lambda 表达式语法规则
		 * {} 表示需要完成的方法体内容 
		 * 当前 接口A 中的方法 void test() 没有返回值,所以在 Lambda 表达式对应
		 * 大括号中无需return关键字返回数据
		 */
		testLambda(() -> {
			System.out.println("Lambda表达式直接作为方法的参数");
		});
		
		// Lambda 表达式有且只有一行代码,可以省略大括号
		testLambda(() -> System.out.println("如果Lambda表达式只有一行,可以省略大括号"));
	}
	
	public static void testLambda(A a) {
		a.test();
	}
}

标签:void,接口,匿名,test,方法,public,Lambda
来源: https://www.cnblogs.com/A-Nan-q/p/16275312.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有