Java 8革新:现代编程的全新标准与挑战

在这里插入图片描述

文章目录

    • 一、方法引用
    • 二、接口默认方法
    • 三、接口静态方法
    • 四、集合遍历forEach()方法

一、方法引用

方法引用是Java 8中一种简化Lambda表达式的方式,通过直接引用现有方法来代替Lambda表达式。

方法引用使得代码更加简洁和易读,特别是在处理函数式接口时,可以替代相对冗长的Lambda表达式,提高了代码的可维护性和可读性。

方法引用通常可以分为以下几种类型:

  • 静态方法引用:引用某个类的静态方法。ClassName::staticMethodName
  • 实例方法引用:引用某个对象的实例方法。objectInstance::instanceMethodName
  • 构造方法引用:引用类的构造方法来创建该类的实例。ClassName::new
  1. 静态方法引用

定义一个函数式接口,定义一个抽象方法 convert,接收一个类型为 F 的参数,并返回一个类型为 T 的结果。

@FunctionalInterface
interface Converter<F, T> {T convert(F from);
}

有一个静态方法 StringHelper 中的静态方法 toUpperCase

class StringHelper {public static String toUpperCase(String str) {return str.toUpperCase();}
}

使用静态方法引用来创建一个 Converter 实例。

/*** StringHelper::toUpperCase 就是静态方法引用,它引用了 StringHelper 类的 toUpperCase 方法,该方法的签名与 Converter 接口中的 convert 方法兼容*/
Converter<String, String> converter = StringHelper::toUpperCase;
String convertedStr = converter.convert("hello");
System.out.println(convertedStr); // 输出: 
HELLO
  1. 实例方法引用

定义一个类 StringUtils,有一个实例方法 startsWithIgnoreCase

class StringUtils {public boolean startsWithIgnoreCase(String str, String prefix) {// 检查一个字符串是否以另一个字符串开头(忽略大小写)return str.toLowerCase().startsWith(prefix.toLowerCase());}
}

使用实例方法引用来创建一个 BiPredicate 实例:

/*** 方法引用允许我们在 BiPredicate 接口的上下文中使用 startsWithIgnoreCase 方法作为一个函数,第一个参数作为方法的调用者(即 stringUtils 对象),第二个参数作为方法的参数传递*/
StringUtils stringUtils = new StringUtils();// 使用实例方法引用创建 BiPredicate 实例
BiPredicate<String, String> startsWithIgnoreCase = stringUtils::startsWithIgnoreCase;// 测试 startsWithIgnoreCase 方法引用的效果,调用 test 方法来检查字符串 "Java" 是否以 "ja" 开头(忽略大小写)
boolean result = startsWithIgnoreCase.test("Java", "ja");
System.out.println(result); 
// 输出:
true
  1. 构造方法引用

定义一个类 Person,它有一个构造方法 Person(String name, int age)

class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}
}

使用构造方法引用来创建一个 Supplier 实例。

// 使用构造方法引用创建 Supplier 实例
Supplier<Person> personSupplier = Person::new;
// 获取 Person 对象
Person person = personSupplier.get();// 设置 Person 对象的属性
person = new Person("Alice", 30);
System.out.println(person.getName() + ", " + person.getAge());// 输出: 
Alice, 30

在这里,Person::new 是构造方法引用,它引用了 Person 类的构造方法,根据 Supplier 的函数签名,Java 编译器会自动推断使用哪个构造方法。

是不是感觉构造方法引用有点多余,这样有什么好处吗?为什么不直接new一个构造函数,这样不显得多此一举吗 ?

使用构造方法引用和 Supplier 接口结合起来的好处

  1. 延迟实例化和懒加载
    • 当你使用构造方法引用创建 Supplier 实例时,实际的对象并没有立即被创建。
    • 只有在调用 Supplierget() 方法时,才会真正创建对象。这种方式可以延迟对象的实例化,直到真正需要使用它时。
  2. 与函数式接口的兼容性
    • Supplier 是一个函数式接口,它通常用于表示一个供给型的操作,它不接受任何参数,返回一个指定类型的结果。
    • 使用构造方法引用可以非常自然地与函数式接口一起使用,因为构造方法引用本质上就是一种函数式的表达方式。
  3. 更加清晰和简洁的代码
    • 使用构造方法引用可以使代码更加简洁和易于理解,特别是在需要创建大量对象或者与函数式编程范式结合使用时。它减少了重复的代码,提高了代码的可读性。
  4. 支持方法引用的优势
    • 构造方法引用是方法引用的一种特殊形式,它直接引用类的构造方法。这允许你像引用方法一样引用构造方法,从而提供了更高的灵活性和可复用性。

二、接口默认方法

Java 8 引入了接口的默认方法,这是一种在接口中定义具有默认实现的方法的方式。默认方法允许接口在不破坏现有实现的情况下,向现有的接口添加新的方法。

特点和用途

  1. 默认实现
    • 默认方法在接口中可以提供方法的具体实现,可以直接在接口中定义,并提供一个默认的方法体。
  2. 向后兼容性
    • 默认方法的引入使得现有的接口能够以向后兼容的方式进行扩展。
    • 当接口被新方法扩展时,实现这个接口的所有类都不需要修改现有代码。
  3. 多继承问题的解决
    • 默认方法允许接口在不引入抽象类的情况下定义方法的具体实现。
    • 一个类可以实现多个接口并继承多个默认方法,解决了传统接口不支持多继承的问题。
  4. 接口的演进
    • 默认方法使得接口在 Java 8 中具备了更强的功能,可以像抽象类一样拥有一些默认行为,同时保持其灵活性和扩展性。
interface Vehicle {// 抽象方法void start(); // 默认方法default void stop() {System.out.println("Vehicle stopped"); }
}class Car implements Vehicle {@Overridepublic void start() {System.out.println("Car started");}// 可选:覆盖默认方法@Overridepublic void stop() {System.out.println("Car stopped");}
}public class Main {public static void main(String[] args) {Vehicle car = new Car();// 输出: Car startedcar.start(); // 输出: Car stoppedcar.stop();  }
}

一个类实现了多个接口,这些接口中有相同签名的默认方法(包括继承关系),那么编译器会要求显式地覆盖冲突的默认方法,以消除二义性。

冲突主要存在的情况

  1. 同名同参的默认方法:如果一个类实现了多个接口,这些接口中有相同签名(方法名和参数列表相同)的默认方法,则需要在实现类中手动提供具体实现,从而消除二义性。
  2. 接口继承冲突:如果一个接口继承了另一个接口,并且提供了一个与父接口中默认方法签名相同但默认实现不同的方法,实现类必须覆盖这个方法来解决二义性。
interface InterfaceA {default void greet() {System.out.println("Hello from InterfaceA");}
}interface InterfaceB {default void greet() {System.out.println("Hello from InterfaceB");}
}// 实现类实现了多个接口,这些接口中有同名的默认方法 greet()
class MyClass implements InterfaceA, InterfaceB {// 需要手动实现 greet() 方法,消除二义性@Overridepublic void greet() {// 可以选择调用 InterfaceA 的默认实现InterfaceA.super.greet(); // 也可以自己实现}
}public class Main {public static void main(String[] args) {MyClass obj = new MyClass();obj.greet(); }
}// 输出: 
Hello from InterfaceA

三、接口静态方法

接口静态方法是Java 8引入的一个重要特性,它们扩展了接口的功能,使得接口可以包含静态的方法实现。这种方法通常用于定义一些通用的工具方法,或者提供与接口实例无关的共享代码。静态方法的引入使得Java接口在语法上更加灵活和功能强大。

特点和用途

  1. 方法实现
    • 接口静态方法可以直接在接口中提供方法的具体实现。这些方法使用 static 关键字声明,并且可以有方法体。
  2. 工具方法
    • 静态方法通常用于提供一些通用的工具方法,这些方法与接口的实例无关,直接通过接口名调用。
  3. 代码重用
    • 静态方法可以在接口中定义一些常见的实用方法,以便多个类或实现接口的类共享和重用这些方法。
  4. 不可被继承
    • 接口的静态方法不能被实现该接口的类所继承或覆盖。这使得静态方法的行为与类的静态方法有所不同,类的静态方法可以被继承或隐藏。
interface UtilityInterface {// 静态方法static void printMessage(String message) {System.out.println("Message from interface: " + message);}// 抽象方法void processData(String data);
}class MyClass implements UtilityInterface {@Overridepublic void processData(String data) {System.out.println("Processing data: " + data);}
}public class Main {public static void main(String[] args) {// 调用静态方法UtilityInterface.printMessage("Hello, world!"); MyClass obj = new MyClass();obj.processData("Sample Data");}
}

四、集合遍历forEach()方法

集合类(如List、Set、Map等)引入了一个新的方法 forEach(),用于简化集合的遍历操作。这个方法可以在集合类的实例上直接调用,接受一个函数式接口的实现作为参数,用来定义遍历集合时的操作。

  1. List 遍历
import java.util.Arrays;
import java.util.List;public class Main {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");// 使用 forEach() 遍历输出每个元素names.forEach(name -> System.out.println(name));// 也可以使用方法引用names.forEach(System.out::println);}
}
  1. Set 遍历
import java.util.HashSet;
import java.util.Set;public class Main {public static void main(String[] args) {Set<Integer> numbers = new HashSet<>();numbers.add(1);numbers.add(2);numbers.add(3);// 使用 forEach() 遍历输出每个元素numbers.forEach(number -> System.out.println(number));}
}
  1. Map 遍历
import java.util.HashMap;
import java.util.Map;public class Main {public static void main(String[] args) {Map<Integer, String> map = new HashMap<>();map.put(1, "One");map.put(2, "Two");map.put(3, "Three");// 使用 forEach() 遍历输出每个键值对map.forEach((key, value) -> System.out.println(key + " -> " + value));}
}

注意事项:

  • forEach() 方法不能保证集合元素的顺序,具体取决于集合的实现类。
  • 在遍历过程中,不建议修改集合的结构,这可能会导致 ConcurrentModificationException 异常。

好的木材并不在顺境中生长,风越强,树越壮

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3226899.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

揭秘小红书矩阵系统:源码助力一键自动发布,多平台管理,效率飙升!

在数字化时代&#xff0c;社交媒体已成为品牌和个人展示自我、推广产品的重要舞台。小红书&#xff0c;作为备受年轻人喜爱的社交平台&#xff0c;其影响力不容小觑。然而&#xff0c;面对日益激烈的竞争&#xff0c;如何高效地在小红书上发布内容、管理多平台账号&#xff0c;…

数模打怪(一)之层次分析法

一、什么是层次分析法 层次分析法&#xff08;AHP&#xff09;主要用于解决评价类问题&#xff08;可打分&#xff09; 比如哪种方案更好、哪位运动员更优秀等 二、层次分析法的三个步骤 1、建立层次结构 分析题目&#xff0c;找出评价类问题的三要素&#xff1a; &#x…

通过Xftp向linux系统传文件,出现Permission is not allowed错误怎么办?

使用xftp出现如下情况&#xff0c;就是说明权限不够。什么权限呢&#xff1f;是我们准备传输的linux系统上面的目标文件夹的权限不够&#xff0c;给linux上面这个目标文件夹提升权限即可。 注意点&#xff1a; 777后面跟的是目录名&#xff0c;比如你想往/usr/local/src这个目…

MySQL 数据库基础概念

一、什么是数据库&#xff1f; 数据库&#xff08;Database&#xff09;是按照数据结构来组织、存储和管理数据的仓库。 每个数据库都有一个或多个不同的 API 用于创建&#xff0c;访问&#xff0c;管理&#xff0c;搜索和复制所保存的数据。 我们也可以将数据存储在文件中&…

用python生成词频云图(python实例二十一)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.词频云图 3.1 代码构思 3.2 代码实例 3.3 运行结果 4.总结 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&a…

Python导包问题

文章目录 1问题背景2参考资料及分析3可以兼顾的方法 1问题背景 需要在当前文件中导入当前文件的上级目录下某个文件夹中的文件&#xff0c;如下图所示 即在CBOW.py文件中导入utils\Embedding.py文件中的类&#xff1b; 2参考资料及分析 如何将Python的上级目录的文件导入&am…

react基础语法,模板语法,ui渲染,jsx,useState状态管理

创建一个react应用 这里使用create-react-app的脚手架构建项目&#xff08;结构简洁&#xff0c;基于webpack-cli&#xff09;&#xff0c; npx create-react-app [项目名称] 使用其他脚手架构建项目可以参考&#xff1a;react框架&#xff0c;使用vite和nextjs构建react项目…

数学建模国赛入门指南

文章目录 认识数学建模及国赛认识数学建模什么是数学建模&#xff1f;数学建模比赛 国赛参赛规则、评奖原则如何评省、国奖评奖规则如何才能获奖 国赛赛题分类及选题技巧国赛赛题特点赛题分类 国赛历年题型及优秀论文数学建模分工技巧数模必备软件数模资料文献数据收集资料收集…

【7月长沙】2024年土木、水利与智能建造国际会议(CHEIC 2024)

在21世纪的今天&#xff0c;随着科技的迅猛发展&#xff0c;土木工程、水利工程与智能建造领域正迎来前所未有的变革。为了汇集全球范围内的智慧&#xff0c;推动这一领域的进步与发展&#xff0c;土木、水利工程与智能建造国际会议&#xff08;CHEIC 2024&#xff09;应运而生…

华为浏览器,Chrome的平替,插件无缝连接

文章目录 背景插件书签 背景 不知道各位小伙伴有没有这样的痛点&#xff0c;办公电脑、家里的电脑还有手机、平板等&#xff0c;收藏了一个网址或者在手机上浏览了某个网页&#xff0c;保存起来&#xff0c;可是一换平台或者换个电脑&#xff0c;在想要浏览之前收藏的东西&…

Selenium 中的 JUnit 注解

JUnit 是一个基于 Java 的开源框架&#xff0c;可帮助测试人员执行单元测试。JUnit 主要用于测试应用程序的每个单元或组件&#xff0c;例如类和方法。它有助于编写和运行可重复的自动化测试&#xff0c;以确保项目代码按预期运行。还可以使用 JUnit 执行 Selenium 自动化测试用…

E. Beautiful Array(cf954div3)

题意&#xff1a;给定一个数组&#xff0c;可以先对数组进行任意排序&#xff0c;每次操作可以选择一个ai&#xff0c;将它变成aik&#xff0c; 想让这个数组变成一个美丽数组&#xff08;回文数组&#xff09;&#xff0c;求最少操作次数 分析&#xff1a; 先找出相同的数字…

Linux--深入理与解linux文件系统与日志文件分析

目录 一、文件与存储系统的 inode 与 block 1.1 硬盘存储 1.2 文件存取--block 1.3 文件存取--inode 1.4 文件名与 inode 号 ​编辑 1.5 查看 inode 号码方法 1.6 Linux 系统文件的三个主要的时间属性 1.7 硬盘分区结构 1.8 访问文件的简单了流程 1.9 inode 占用 1.…

从0-1搭建一个web项目(页面布局详解)详解

本章分析页面布局详解详解 ObJack-Admin一款基于 Vue3.3、TypeScript、Vite3、Pinia、Element-Plus 开源的后台管理框架。在一定程度上节省您的开发效率。另外本项目还封装了一些常用组件、hooks、指令、动态路由、按钮级别权限控制等功能。感兴趣的小伙伴可以访问源码点个赞 地…

资产几何?现代组织的外部攻击面

组织的外部攻击面情况如何&#xff1f;组织自己能完全掌握自己资产的情况吗&#xff1f; 工作来源 ASIA CCS 2024 工作背景 CISA 在 2022 年要求对政府的 IT 系统进行漏洞扫描&#xff0c;英国国家网络安全中心&#xff08;NCSC&#xff09;在 2022 年也计划扫描英国互联网…

智慧城市可视化页面怎么做?免费可视化工具可以帮你

智慧城市是一个综合性的概念&#xff0c;广泛应用于各个领域&#xff0c;如基础设施建设、信息化应用、产业经济发展、市民生活品质等。 可视化页面的制作也是一个综合性的过程&#xff0c;需要确定展示内容、数据收集与处理、设计可视化元素等多个环节紧密配合。 1. 明确展示…

无损音频格式 FLAC 转 MP3 音频图文教程

音频文件的格式多样&#xff0c;每种格式都有其独特的特点与适用场景。FLAC&#xff08;Free Lossless Audio Codec&#xff09;&#xff0c;作为一种无损音频压缩格式&#xff0c;因其能够完美保留原始音频数据的每一个细节而备受音频发烧友和专业人士的青睐。 然而&#xff0…

Profibus_DP转ModbusTCP网关模块连马保与上位机通讯

Profibus转ModbusTCP网关模块&#xff08;XD-ETHPB20&#xff09;广泛应用于工业自动化领域。例如&#xff0c;可以将Profibus网络中的传感器数据转换为ModbusTCP协议&#xff0c;实现数据的实时监控和远程控制。本文介绍了如何利用Profibus转ModbusTCP网关&#xff08;XD-ETHP…

AWS-WAF-Log S3存放,通过Athena查看

1.创建好waf-cdn 并且设置好规则和log存储方式为s3 2. Amazon Athena 服务 使用 &#xff08;注意s3桶位置相同得区域&#xff09; https://docs.aws.amazon.com/zh_cn/athena/latest/ug/waf-logs.html#waf-example-count-matched-ip-addresses 官方文档参考,建一个分区查询表…

pytorch实现水果2分类(蓝莓,苹果)

1.数据集的路径&#xff0c;结构 dataset.py 目的&#xff1a; 输入&#xff1a;没有输入&#xff0c;路径是写死了的。 输出&#xff1a;返回的是一个对象&#xff0c;里面有self.data。self.data是一个列表&#xff0c;里面是&#xff08;图片路径.jpg&#xff0c;标签&…