当前位置:首页 » 《关注互联网》 » 正文

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

23 人参与  2024年09月13日 08:01  分类 : 《关注互联网》  评论

点击全文阅读


在这里插入图片描述

文章目录

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

一、方法引用

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

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

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

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

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

@FunctionalInterfaceinterface 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
实例方法引用

定义一个类 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
构造方法引用

定义一个类 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 接口结合起来的好处

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

二、接口默认方法

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

特点和用途

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

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

冲突主要存在的情况

同名同参的默认方法:如果一个类实现了多个接口,这些接口中有相同签名(方法名和参数列表相同)的默认方法,则需要在实现类中手动提供具体实现,从而消除二义性。接口继承冲突:如果一个接口继承了另一个接口,并且提供了一个与父接口中默认方法签名相同但默认实现不同的方法,实现类必须覆盖这个方法来解决二义性。
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() 方法,消除二义性    @Override    public 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接口在语法上更加灵活和功能强大。

特点和用途

方法实现: 接口静态方法可以直接在接口中提供方法的具体实现。这些方法使用 static 关键字声明,并且可以有方法体。 工具方法: 静态方法通常用于提供一些通用的工具方法,这些方法与接口的实例无关,直接通过接口名调用。 代码重用: 静态方法可以在接口中定义一些常见的实用方法,以便多个类或实现接口的类共享和重用这些方法。 不可被继承: 接口的静态方法不能被实现该接口的类所继承或覆盖。这使得静态方法的行为与类的静态方法有所不同,类的静态方法可以被继承或隐藏。
interface UtilityInterface {    // 静态方法    static void printMessage(String message) {        System.out.println("Message from interface: " + message);    }    // 抽象方法    void processData(String data);}class MyClass implements UtilityInterface {    @Override    public 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(),用于简化集合的遍历操作。这个方法可以在集合类的实例上直接调用,接受一个函数式接口的实现作为参数,用来定义遍历集合时的操作。

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);    }}
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));    }}
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://zhangshiyu.com/post/159072.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 祖母寿宴,侯府冒牌嫡女被打脸了(沈屿安秦秀婉)阅读 -
  • 《雕花锦年,昭都旧梦》(裴辞鹤昭都)完结版小说全文免费阅读_最新热门小说《雕花锦年,昭都旧梦》(裴辞鹤昭都) -
  • 郊区41号(许洛竹王云云)完整版免费阅读_最新全本小说郊区41号(许洛竹王云云) -
  • 负我情深几许(白诗茵陆司宴)完结版小说阅读_最热门小说排行榜负我情深几许白诗茵陆司宴 -
  • 九胞胎孕妇赖上我萱萱蓉蓉免费阅读全文_免费小说在线看九胞胎孕妇赖上我萱萱蓉蓉 -
  • 为保白月光,侯爷拿我抵了债(谢景安花田)小说完结版_完结版小说全文免费阅读为保白月光,侯爷拿我抵了债谢景安花田 -
  • 陆望程映川上官硕《我的阿爹是带攻略系统的替身》最新章节阅读_(我的阿爹是带攻略系统的替身)全章节免费在线阅读陆望程映川上官硕
  • 郑雅琴魏旭明免费阅读_郑雅琴魏旭明小说全文阅读笔趣阁
  • 头条热门小说《乔书意贺宴临(乔书意贺宴临)》乔书意贺宴临(全集完整小说大结局)全文阅读笔趣阁
  • 完结好看小说跨年夜,老婆初恋送儿子故意出车祸_沈月柔林瀚枫完结的小说免费阅读推荐
  • 热推《郑雅琴魏旭明》郑雅琴魏旭明~小说全文阅读~完本【已完结】笔趣阁
  • 《你的遗憾与我无关》宋怀川冯洛洛无弹窗小说免费阅读_免费小说大全《你的遗憾与我无关》宋怀川冯洛洛 -

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1