当前位置: 首页 > news >正文

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 异常。

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 《梦醒蝶飞:释放Excel函数与公式的力量》10.4 IMREAL函数
  • C#字符串格式化的方式
  • nginx的正向代理和反向代理
  • 微软 Edge 浏览器全解析
  • Kylin系列(三)安装与配置:搭建你的第一个 Kylin 环境
  • 网络防御保护——网络安全概述
  • 第二周:李宏毅机器学习笔记
  • Android知识收集
  • openGauss配置vscode编译调试环境
  • Python: 分块读取文本文件
  • SQL注入如何判断数据库类型
  • JVM专题之G1垃圾收集器下
  • python学习-容器类型
  • Redis 7.x 系列【22】主从复制配置项
  • 创建数据库表的语法定义包含了SQL Server、Mysql、PostgreSQL、SQLite的示例
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 【译】理解JavaScript:new 关键字
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • 2017届校招提前批面试回顾
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • Brief introduction of how to 'Call, Apply and Bind'
  • CentOS从零开始部署Nodejs项目
  • echarts的各种常用效果展示
  • Joomla 2.x, 3.x useful code cheatsheet
  • php的插入排序,通过双层for循环
  • Python十分钟制作属于你自己的个性logo
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • vue-cli在webpack的配置文件探究
  • webpack项目中使用grunt监听文件变动自动打包编译
  • Xmanager 远程桌面 CentOS 7
  • yii2权限控制rbac之rule详细讲解
  • 分布式事物理论与实践
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 驱动程序原理
  • 人脸识别最新开发经验demo
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • Hibernate主键生成策略及选择
  • 从如何停掉 Promise 链说起
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • # Apache SeaTunnel 究竟是什么?
  • (12)Linux 常见的三种进程状态
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (160)时序收敛--->(10)时序收敛十
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (LeetCode C++)盛最多水的容器
  • (二)fiber的基本认识
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (南京观海微电子)——示波器使用介绍
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (实测可用)(3)Git的使用——RT Thread Stdio添加的软件包,github与gitee冲突造成无法上传文件到gitee
  • (四)opengl函数加载和错误处理
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转载)PyTorch代码规范最佳实践和样式指南