首页 > 其他分享 >【JDK8】新特性(一)

【JDK8】新特性(一)

时间:2024-07-06 10:59:37浏览次数:20  
标签:String void 特性 Person JDK8 static println public

1. 简介

JDK8是官方发布的一个大版本, 提供了很多新特性功能给开发者使用, 包含语言、编译器、库、工具和JVM等方面的十多个新特性。 本文将介绍编码过程中常用的一些新特性. JDK8帮助文档

2.lambda表达式

概念:

语法:

注意:

        函数式接口:接口中只有一个抽象方法。

        (参数一,参数二):抽象方法的参数

        ->:分隔符

        {}:表示抽象方法的实现

代码示例:

public class Test01 {
    public static void main(String[] args) {


        // 该构造方法需要传递一个线程任务对象。Runnable类型
        MyThread mt = new MyThread();
        Thread t1 = new Thread(mt);
        t1.start();

        Runnable mt2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名内部类");
            }
        };
        Thread t2 = new Thread(mt2);
        t2.start();

        // 使用Lambda表达式
        Runnable mt3 = () -> {
            System.out.println("Lambda表达式");
        };
        Thread t3 = new Thread(mt3);
        t3.start();

    }
}

class MyThread implements Runnable{
    @Override
    public void run() {
        System.out.println("自定义任务接口");
    }
}

分析:

  • Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心
  • 为了指定 run 的方法体,不得不需要 Runnable 接口的实现类
  • 为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类
  • 必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错
  • 而实际上,似乎只有方法体才是关键所在。 

2.1无参无返回值

 代码示例:

public class Test01 {

    public static void main(String[] args) {

        // 匿名内部类
        Swimming s = new Swimming() {
            @Override
            public void swim() {
                System.out.println("使用匿名内部类的方式");
            }
        };
        s.swim();

        // lambda表达式
        fun(() -> {
            System.out.println("使用lambda表达式");
        });

    }

    // 定义fun方法,接受一个Swimming类型的参数
    public static void fun(Swimming s) {
        s.swim();
    }
}

// 函数式接口
@FunctionalInterface
interface Swimming {
    public void swim();
}

2.2有参有返回值

代码示例:

public class Test02 {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("张三", 55, 180));
        list.add(new Person("李四", 49, 190));
        list.add(new Person("王五", 60, 200));
        list.add(new Person("赵六", 21, 210));

        // 对集合中的元素进行排序 按照年龄大小
        // 传统做法
        Comparator<Person> comparator = new Comparator<Person>() {
            // int:0表示新加的元素和集合中原来的比对相同
            // int:1表示新加的元素和集合中原来的比对不同 02<01
            // int:-1表示新加的元素和集合中原来的比对不同 02>01
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge() - o1.getAge();
            }
        };
        Collections.sort(list, comparator);
        for (Person person : list) {
            System.out.println(person);
        }

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

        Comparator<Person> comparator1 = (Person o1, Person o2) -> {
            return o1.getAge() - o2.getAge();
        };
        Collections.sort(list, comparator1);
        for (Person person : list) {
            System.out.println(person);
        }


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

        // Lambda表达式
        Collections.sort(list, (o1, o2) -> o1.getAge() - o2.getAge());
        for (Person person : list) {
            System.out.println(person);
        }


    }

}

class Person{
    private String name;
    private int age;
    private int height;

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }

    public Person(String name, int age, int height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
}

2.3详细介绍lambda表达式

  • Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分
    • 左侧:(参数1,参数2…)表示参数列表
    • 右侧:{}内部是方法体
  • 注意事项
    • 形参列表的数据类型会自动推断
    • 如果形参列表为空,只需保留()
    • 如果形参只有1个,()可以省略,只需要参数的名称即可
    • 如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句
    • Lambda不会生成一个单独的内部类文件 

3.函数式接口

  • 如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口,可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上
     
  • @Functionalnterface 注解检测接口是否符合函数式接口。

内置函数式接口的由来

public class Test03 {

    public static void main(String[] args) {
        Operation o = arr -> {
            int sum = 0;
            for (int n : arr) {
                sum += n;
            }
            System.out.println(sum);
        };
        fun(o);  // 调用 fun 方法并传递 lambda 表达式
    }

    public static void fun(Operation o) {
        int[] arr = {1, 2, 3, 4, 5};
        o.getSum(arr);
    }
}

@FunctionalInterface
interface Operation {
    // 求数组的和
    void getSum(int[] arr);
}

分析:

我们知道使用lambda表达式的前提是需要有函数式接口,而lambda使用时不关心接口名、抽象方法名,只关心抽象方法的参数列表和返回值类型。因此为了让我们使用lambda方便,JDK提供了大量常用的函数式接口。

常见的函数式接口

在java.util.funcation保存

3.1Consumer<T>

这个接口表示接受单个输入参数并且不返回任何结果的操作。它通常用于需要对单个参数执行某些操作,但不需要返回值的情况。

        void accept(T t);

public class Test {
    public static void main(String[] args) {
        Consumer<Double> c = t -> {
            System.out.println("按摩消费了:" + t + "元");
        };
        fun01(c,1000.0);
    }

    public static void fun01(Consumer<Double> consumer,double money){
        consumer.accept(money);
    }

}

4.2Supplier<T>供给型函数式接口

这个接口代表一个供给型接口,它不接受任何参数,但会返回一个结果。接口定义非常简单,只有一个抽象方法:

           T get();

public class Test02 {
    public static void main(String[] args) {
        Supplier<Integer> supplier = ()-> (int)(Math.random()*100);
        fun(supplier);
    }

    public static void fun(Supplier<Integer> supplier){
        Integer num = supplier.get();
        System.out.println("内容为:"+num);
    }
}

4.3Function<T,R>函数型函数式接口

这个接口表示一个函数,接受一个类型为 T 的参数,并返回一个类型为 R 的结果。接口定义如下:

        R apply(T t);

public class Test03 {
    public static void main(String[] args) {
        fun(s -> s.toUpperCase(),"hello");
    }

    public static void fun(Function<String ,String> function,String msg){
        String s = function.apply(msg);
        System.out.println(s);
    }

}

4.4Predicate<T>

这个接口表示一个接受单个参数并返回布尔值的断言函数。它用于对传入的参数进行判断,并返回一个布尔值结果。

        boolean test(T t);

当传入一个参数时,需要对该参数进行判断时,则需要这种函数。

public class Test04 {
    public static void main(String[] args) {
        fun(s->s.length()>3?true:false,"撒大大大v啊");
    }

    public static void fun(Predicate<String> predicate,String name){
        boolean b = predicate.test(name);

        System.out.println("该名称的长度是否长啊"+b);
    }

}

5.方法引用

5.1lambda表达式的冗余

public class Test01 {
    public static void main(String[] args) {
        Consumer<Integer[]> consumer = arr -> {
            int sum = 0;
            for (Integer integer : arr) {
                sum += integer;
            }
            System.out.println(sum);
        };
        fun(consumer);
    }
    public static void fun(Consumer<Integer[]> consumer){
        Integer[] arr = {1,2,3,4,5,6,7,8,9,10};
        consumer.accept(arr);
    }

    public static void sum(Integer[] arr){
        int sum = 0;
        for (Integer integer : arr) {
            sum += integer;
        }
        System.out.println(sum);
    }
}

分析:


如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接“引 用”过去就好了: ---方法引用

public class Test01 {
    public static void main(String[] args) {

        Consumer<Integer[]> consumer1 = Test01::sum;
        fun(consumer1);
    }
    public static void fun(Consumer<Integer[]> consumer){
        Integer[] arr = {1,2,3,4,5,6,7,8,9,10};
        consumer.accept(arr);
    }

    public static void sum(Integer[] arr){
        int sum = 0;
        for (Integer integer : arr) {
            sum += integer;
        }
        System.out.println(sum);
    }
}

5.2什么是方法引用?

方法引用允许你直接引用现有方法(静态方法、实例方法或构造方法),而不必像 lambda 表达式那样完全重新实现一个功能。它的语法基本上是 :: 符号,后跟方法的名称

方法引用的分类

5.3实例方法引用

实例方法引用,顾名思义就是调用已经存在的实例的方法,与静态方法引用不同的是类要先实例化静态方法引用类无需实例化,直接用类名去调用。

 案例:计算一个字符串列表中每个字符串的长度。

public class Test{
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("hello", "world", "java", "method", "reference");

        // 使用实例方法引用,计算字符串长度
        Function<String, Integer> stringLength = String::length;
        List<Integer> lengths = strings.stream()
                                       .map(stringLength)
                                       .collect(Collectors.toList());

        // 输出字符串长度列表
        lengths.forEach(System.out::println);
    }
}

5.4对象方法引用

 案例:将一个字符串列表转换为大写字母。

public class Test01{
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("hello", "world", "java", "method", "reference");

        // 使用对象方法引用,将字符串转换为大写
        Function<String, String> toUpperCase = String::toUpperCase;
        List<String> upperCaseStrings = strings.stream()
                                               .map(toUpperCase)
                                               .collect(Collectors.toList());

        // 输出转换后的字符串列表
        upperCaseStrings.forEach(System.out::println);
    }
}

5.5构造方法引用

案例:根据名字创建 Person 对象的列表。

public class Test03{
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用构造方法引用创建 Person 对象
        Function<String, Person> personConstructor = Person::new;
        List<Person> people = names.stream()
                                   .map(personConstructor)
                                   .collect(Collectors.toList());

        // 输出 Person 对象列表
        people.forEach(System.out::println);
    }
}
class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "'}";
    }
}

还有一部分没有写完!晚会补上!

标签:String,void,特性,Person,JDK8,static,println,public
From: https://blog.csdn.net/As_Yua/article/details/140217881

相关文章

  • GaussDB AI新特性:gs_index_advise推荐索引
    GaussDB的AI新特性,可以把SQL文本嵌套在函数中,数据库会返回一个创建合适索引的列gs_index_advise(text)描述:针对单条查询语句推荐索引。参数:SQL语句字符串返回值类型:record  一、通常的SQL优化会通过参数调优的方式进行调整,例如如下参数setenable_fast_query_shippi......
  • 抬头显示器HUD原理及特性
    HUD基本原理  抬头数字显示仪(HeadUpDisplay),又叫平视显示系统,它的作用,就是把时速、导航等重要的行车信息,投影到驾驶员前风挡玻璃上,让驾驶员尽量做到不低头、不转头就能看行车信息。 HUD成像为离轴三反的过程,该过程中,PGU中的像被不断放大反射,最终形成虚像,成像大小......
  • CentOS安装部署JDK8
    1.下载jdk8(1)、官网下载:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html2)百度网盘:链接:https://pan.baidu.com/s/1dTwKC65nDWBjmckWc-9igg?pwd=paxl提取码:paxl2、开始部署(1)解压jdk包,并将解压后的包移至想要存放的目录下,我放在/usr/loc......
  • 一图看懂华为云 CodeArts API 7 大特性,带你玩转一站式 API
    everythingisAPI,预计未来将有80%以上的商业合作会通过API来完成。华为云CodeArtsAPI是API全生命周期一体化协作平台,支持开发者高效实现API设计、API开发、API测试、API托管、API运维、API变现的一站式体验。以API契约为锚点,CodeArtsAPI保证了API各阶段数据高度一致,为开发......
  • 新特性之C++14
    C++14是C++11的一个增量升级版本,虽然没有引入像C++11那样的大量新特性,但它通过对已有特性进行优化和扩展,提高了语言的可用性和性能。本文将详细介绍C++14引入和优化的新特性功能。概述C++14旨在修复C++11的一些缺陷,并提供了一些重要的增强功能,以简化开发者的日......
  • C++11——新特性超详细总结
    目录一、C++11介绍二·、为什么要用C++11三、新特性总结1、类型推导(auto/decltype)2、序列for循环语句3、lamdba表达式4、构造函数:委托构造和继承构造5、容器(array/forward_list)6、垃圾回收机制7、正则表达式基础7.1、符号7.2、速记理解技巧7.3、检验数字的表达式......
  • 从0到1Flink的成长之路(二十)-Flink 高级特性(二)之自动重启策略和恢复 ,固定延迟重启策
    从0到1Flink的成长之路(二十)-Flink高级特性(二)之自动重启策略和恢复,,固定延迟重启策略(开发中使用)自动重启策略和恢复1)、重启策略配置方式配置文件在flink-conf.yml中可以进行配置,示例如下:restart-strategy:fixed-delayrestart-strategy.fixed-delay.attempts:3restart-strat......
  • 【C++ | 继承】|概念、方式、特性、作用域、6类默认函数
    继承1.继承的概念与定义2.继承的方式2.1继承基本特性2.2继承的作用域2.2.1隐藏赋值兼容派生类的创建和销毁构造函数拷贝构造赋值重载1.继承的概念与定义继承是面向对象编程中的一个重要概念。它的由来可以追溯到软件开发中的模块化设计和代码复用的需求。在软件......
  • 学懂C#编程:常用高级技术——学会C#的高级特性 LINQ
    LINQ(LanguageIntegratedQuery)是C#中的一项强大特性,它允许开发者以一种统一的方式查询和操作各种数据源,如集合、数据库、XML等。LINQ将查询功能直接集成到C#语言中,使得数据查询和操作变得更加直观和高效。LINQ的基本概念LINQ的核心思想是将数据查询表达为一种类似于SQL的查......
  • C++23特性一览
    NewlanguagefeaturesNewlanguagefeaturetestingmacrosExplicitobjectparameters,explicitobjectmemberfunctions(deducingthis)ifconsteval/ifnotconstevalMultidimensionalsubscriptoperator(e.g.v[1,3,7]=42;)staticoperator()static......