Java8新特性 十二大总结 (面试篇)

可见,我们采用Lambda表达式优化后,代码会更加简洁

Lambda表达式是用过函数式接口(只有一个方法的普通接口)来实现的,函数式接口可以被隐式转换为Lambda表达式,为了与普通的接口区分开,JDK1.8新增加了一种特殊的注解@FunctionalInterface 如下


@FunctionalInterface

public interface Function<T, R> {



    /**

     * Applies this function to the given argument.

     *

     * @param t the function argument

     * @return the function result

     */

    R apply(T t);

}



二、方法的默认实现和静态方法

=================================================================================

JDK1.8通过使用关键字default可以给接口中的方法添加默认实现,此外,接口中还可以定义静态方法,如下


package com.wanshi.common.bean;



/**

 * Lambda表达式是通过函数式接口(只有一个方法得接口)来实现的。函数式接口可以被隐式地转换为Lambda表达式,

 * 为了与普通的接口区分开(普通接口中可能会有多个方法),jdk1.8新增加了一种特殊的注解@FunctionalInterface

 */

@FunctionalInterface

public interface Fun {



    void f();



    default void g() {

        System.out.println("this is default method in interface");

    }



    static void h() {

        System.out.println("this is static method in interface");

    }

}





那么为什么要引入接口中方法的默认实现呢?

其实,这样做的最重要的一个目的就是为了实现接口升级。在原有的设计中,如果想要升级接口,例如给接口中添加一个新的方法,那么会导致所有实现这个接口i的类都要被修改,这给Java语言已有的一些框架进行升级带来了很大的麻烦,如果接口能够支持默认方法的实现,那么可以给这些类库的升级带来许多便利,例如,为了支持Lambda表达式,Collection中引入了forEach方法,可以通过这个语法增加默认的实现,从而降低对这个接口进行升级

必看视频!获取2024年最新Java开发全套学习资料 备注Java

的代价,不需要所有实现这个接口的类进行修改。

三、方法引用

=========================================================================

方法引用指的是可以直接引用Java类或对象的方法,它可以被看成是一种更加简介易懂的Lambda表达式,使用方法引用后,上个例子中的排序代码可以更加简洁的编写


Arrays.sort(people, Comparator.comparing(Person::getAge));



方法引用共有下面4种形式

  • 引用构造方法:ClassName::new

  • 引用类静态方法:ClassName::methodName

  • 引用特定类 的任意对象方法:ClassName::methodName

  • 引用某个对象的方法:ClassName::methodName

下面是一个方法引用的例子:


package com.wanshi.common.bean;



import java.util.Arrays;

import java.util.Comparator;

import java.util.function.Supplier;



public class Person {



    private String name;



    private int age;



    public Person() { }



    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }



    public static Person getInstance(final Supplier<Person> personSupplier) {

        return personSupplier.get();

    }



    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;

    }



    @Override

    public String toString() {

        return "Person{" +

                "name='" + name + '\'' +

                ", age=" + age +

                '}';

    }



    public static int compareByAge(Person a, Person b) {

        return b.getAge() - a.getAge();

    }



}

class CompareProvider {



    public int compareByAge(Person a, Person b) {

        return a.getAge() - b.getAge();

    }

}



class Test {

    public static void main(String[] args) {

        //引用构造方法

        Person person = Person.getInstance(Person::new);

        person.setAge(19);

        System.out.println("测试引用构造方法:" + person.getAge());

        Person[] people = {new Person("James", 25), new Person("Jack", 21)};

        //引用特定类的任意对象方法

        Arrays.sort(people, Comparator.comparing(Person::getAge));

        System.out.println("测试引用特定类的任意对象方法:");

        for (Person person1 : people) {

            System.out.println(person1);

        }



        Arrays.sort(people, Person::compareByAge);

        System.out.println("测试引用类静态方法:");

        for (Person person1 : people) {

            System.out.println(person1);

        }



        //引用某个对象的方法

        Arrays.sort(people, new CompareProvider()::compareByAge);



        System.out.println("测试引用引用某个对象的方法:");

        for (Person person1 : people) {

            System.out.println(person1);

        }



    }

}



测试结果如下

在这里插入图片描述

四、注解(Annotation)

===================================================================================

  1. JDK1.5引入了注解机制,但是有一个限制:相同的注解在同一位置只能声明一次。JDK1.8引入了重复注解机制后,相同的注解在同一个地方可以声明多次。

  2. JDK1.8 对注解进行了扩展。使得注解被使用的范围更广,例如可以给局部变量,泛型,方法异常提供注解。

五、类型推测

=========================================================================

JDK1.8加强了类型推测机制,这种机制可以使得代码更为简洁,假如有以下类的定义


class List<E> {

    static <Z> List<Z> nil() {...};

    static <Z> List<Z> cons(Z head, List<Z> tail) {...};

    E head(){...}

}



在调用的时候,可以使用下面的代码


//通过赋值的目标类型来推测泛型的参数

List<Integer> l = List.nil();



在JDK1.7的时候,这种写法将会产生编译错误,Java7的正确写法如下


List<Integer> l = List<Integer> List.nil();



同理,在调用 cons 方法的时候写法为:


//通过方法的第一个参数来推测泛型的类型

List.cons(5, List.nil());



六、参数名字

=========================================================================

JDK1.8通过在编译的时候增加 -parameters 选项,以及增加反射API与 Parameter,getName() 方法实现了获取方法参数名的功能。

示例代码如下


package com.wanshi.common.bean;



import java.lang.reflect.Method;

import java.lang.reflect.Parameter;



public class Test6 {



    public static void main(String[] args) {

        Method method;

        try {

            method = Test6.class.getMethod("main", String[].class);

            for (Parameter parameter : method.getParameters()) {

                System.out.println("parameter::" + parameter.getName());

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}





如果使用指令 javac Test6.java 来编译以上程序,那么运行的结果是 parameter::args()

如果使用的是 javac Test6.java -parameters 来编译 那么结果是parameter::args

七、新增Optional类

================================================================================

在使用Java语言的进行编程的时候,经常需要使用大量的代码来处理空指针异常,而这种操作往往会降低程序的可读性,JDK1.8引入了Optional类来处理空指针的情况,从而提高代码的可读性,如下


public static void main(String[] args) {

    Optional<String> s1 = Optional.of("hello");

    //判断是否有值

    if (s1.isPresent()) {

        //获取值

        System.out.println(s1.get());

    }



    Optional<Object> s2 = Optional.ofNullable(null);



    if (s2.isPresent()) {

        System.out.println(s2.get());

    }



}



这里只是介绍了 Optional 简单的使用示例,更多可参考JDK帮助文档

八、新增Stream 类

===============================================================================

JDK1.8新增了Stream类,从而把函数式编程的风格引入到Java语言中,Stream类的API提供了强大的功能,使用Stream后,可以写出更加强大,更加简洁的代码


package com.wanshi.common.bean;



import java.util.*;

import java.util.stream.Collectors;



public class Test3 {



    public static void main(String[] args) {

        List<Person> l = new ArrayList<>();

        l.add(new Person("Wang", 10));

        l.add(new Person("Li", 13));

        l.add(new Person("Zhang", 10));

        l.add(new Person("Zhao", 15));

        System.out.println("找出年龄为10的第一个人类:");

        Optional<Person> s = l.stream().filter(person -> person.getAge() == 10).findFirst();

        if (s.isPresent()) {

            System.out.println(s.get().getName() + ", " + s.get().getAge());

        }

        System.out.println("找出年龄为10的所有人类:");

        List<Person> personList = l.stream().filter(person -> person.getAge() == 10).collect(Collectors.toList());

        personList.forEach(person -> {

            System.out.println(person.getName() + ", " + person.getAge());

        });



        System.out.println("对人类年龄分组");

        Map<Integer, List<Person>> map = l.stream().collect(Collectors.groupingBy(Person::getAge));

        Iterator<Map.Entry<Integer, List<Person>>> iterator = map.entrySet().iterator();

        while (iterator.hasNext()) {

            Map.Entry<Integer, List<Person>> next = iterator.next();

            Integer age = next.getKey();

            System.out.println(age+":");

            List<Person> value = next.getValue();

            value.forEach(person -> {

                System.out.print(person.getName()+" ");

            });

            System.out.println();

        }

    }

}





运行结果为

在这里插入图片描述

九、日期新特性

==========================================================================

在JDK1.8以前,处理日期相关的类主要有如下三个

  1. Caalendar:实现日期和时间字段之间的转换,它的属性是可变的,因此,它不是线程安全的。

  2. DateFormat:格式化和分析日期字符串

  3. Date:用来承载日期和时间信息,它的属性是可变的,因此,它不是线程安全的。

这些API使用起来都不是很方便的,而且有很多缺点,如下:


Date date = new Date(2022, 5, 1);

System.out.println(date);



在Date类传入参数,月份为5月,但输出却是 Thu Jun 01 00:00:00 CST 3922

JDK1.8 对日期相关的API进行了改造,提供了更加强大的API。新的java.time 主要包含了处理日期、时间、日期/时间、时区、时刻 (instants)、和时钟(clock) 等操作。下面是使用案例


package com.wanshi.common.bean;



import java.time.*;



public class Test4 {



    public static void main(String[] args) {

        //Clock类通过指定一个时区,可以获取到当前的时刻,日期与时间

        Clock clock = Clock.system(ZoneId.of("Asia/Shanghai"));

        System.out.println("测试Clock:");

        System.out.println(clock.millis());

        System.out.println(clock.instant());



        //Instant 使用方法

        System.out.println("测试Instant:");

        Instant now = Instant.now();

        //精确到秒

        System.out.println(now.getEpochSecond());

        //精确到毫秒

        System.out.println(now.toEpochMilli());



        //LocalDate 以ISO-8601 格式显示的日期类型,无时区信息

        LocalDate date = LocalDate.now();

        LocalDate dateFromClock = LocalDate.now(clock);

        System.out.println("测试LocalDate:");

        System.out.println(date);

        System.out.println(dateFromClock);



        //LocalTime是以ISO-8601 格式显示日期类型,无时区信息

        final LocalTime time = LocalTime.now();

        LocalTime timeFromClock = LocalTime.now(clock);

        System.out.println("测试LocalTime:");

        System.out.println(time);

        System.out.println(timeFromClock);



        //LocalDateTime 以ISO-8601 格式显示的日期和时间

        LocalDateTime dateTime = LocalDateTime.now();

        LocalDateTime datetimeFromClock = LocalDateTime.now(clock);

        System.out.println("测试LocalDateTime:");

        System.out.println(dateTime);

        System.out.println(datetimeFromClock);

    }

}





执行结果

在这里插入图片描述

十、调用JavaScript

=================================================================================

JDK1.8增加API使得通过Java程序来调用JavaScript代码,使用示例:


public static void main(String[] args) throws ScriptException {

    ScriptEngineManager manager = new ScriptEngineManager();

    ScriptEngine engine = manager.getEngineByName("JavaScript");

    System.out.println(engine.getClass().getName());

    System.out.println(engine.eval("function f() {return 'hello';}; f() + ' world!';"));

}



运行结果

在这里插入图片描述

十一、Base64

============================================================================

Base64 编码是一种常见的字符编码,可用来作为电子邮件或Web Service 附件的传输编码,JDK1.8把Base64 编码添加到了标准类库中,示例代码:


public static void main(String[] args) {

    String str = "Hello World!";

    // 编码

    String encodeStr = Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8));

    System.out.println(encodeStr);

	//解码

    String decodeStr = new String(Base64.getDecoder().decode(encodeStr), StandardCharsets.UTF_8);

    System.out.println(decodeStr);

}



执行结果

在这里插入图片描述

十二、并行数组

==========================================================================

JDK1.8增加了对数组并行处理的方法(parallelXxx),下面以排序为例介绍其用法


public static void main(String[] args) throws ScriptException {



    int[] arr = {1, 3, 2, 4, 55, 64, 98, 23};

    Arrays.parallelSort(arr);

    Arrays.stream(arr).forEach(i -> {

        System.out.print(i + " ");

    });

    System.out.println();

}



执行效果

在这里插入图片描述

拓展1:常见加密算法

=============================================================================

⛺三种加密算法分类


  • 对称加密:密钥只有一个,解密、加密都是这一个密钥,加解密速度快,典型的有DES、AES、RC4

  • 非对称加密:密钥成对出现,分别为公钥和私钥,从公钥无法推算私钥,相反,私钥也无法推算公钥,加解密使用不同的密钥,公钥加密需要私钥解密,私钥加密需要公钥解密,非对称加密速度极慢,典型的有RSA、DSA、DSS.

总结

一般像这样的大企业都有好几轮面试,所以自己一定要花点时间去收集整理一下公司的背景,公司的企业文化,俗话说「知己知彼百战不殆」,不要盲目的去面试,还有很多人关心怎么去跟HR谈薪资。

这边给大家一个建议,如果你的理想薪资是30K,你完全可以跟HR谈33~35K,而不是一下子就把自己的底牌暴露了出来,不过肯定不能说的这么直接,比如原来你的公司是25K,你可以跟HR讲原来的薪资是多少,你们这边能给到我的是多少?你说我这边希望可以有一个20%涨薪。

最后再说几句关于招聘平台的,总之,简历投递给公司之前,请确认下这家公司到底咋样,先去百度了解下,别被坑了,每个平台都有一些居心不良的广告党等着你上钩,千万别上当!!!

Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书。
在这里插入图片描述

拓展1:常见加密算法

=============================================================================

⛺三种加密算法分类


  • 对称加密:密钥只有一个,解密、加密都是这一个密钥,加解密速度快,典型的有DES、AES、RC4

  • 非对称加密:密钥成对出现,分别为公钥和私钥,从公钥无法推算私钥,相反,私钥也无法推算公钥,加解密使用不同的密钥,公钥加密需要私钥解密,私钥加密需要公钥解密,非对称加密速度极慢,典型的有RSA、DSA、DSS.

总结

一般像这样的大企业都有好几轮面试,所以自己一定要花点时间去收集整理一下公司的背景,公司的企业文化,俗话说「知己知彼百战不殆」,不要盲目的去面试,还有很多人关心怎么去跟HR谈薪资。

这边给大家一个建议,如果你的理想薪资是30K,你完全可以跟HR谈33~35K,而不是一下子就把自己的底牌暴露了出来,不过肯定不能说的这么直接,比如原来你的公司是25K,你可以跟HR讲原来的薪资是多少,你们这边能给到我的是多少?你说我这边希望可以有一个20%涨薪。

最后再说几句关于招聘平台的,总之,简历投递给公司之前,请确认下这家公司到底咋样,先去百度了解下,别被坑了,每个平台都有一些居心不良的广告党等着你上钩,千万别上当!!!

Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书。
[外链图片转存中…(img-1iK0vEcM-1716449802619)]

  • 26
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值