java8新特性

1. lambda表达式

1)概念
(1)Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性

(2)Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中

(3)使用 Lambda 表达式可以使代码变的更加简洁紧凑
2)格式
(parameters) -> expression	或	(parameters) ->{ statements; }
3)特征
(1)可选类型声明:不需要声明参数类型,编译器可以统一识别参数值

(2)可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号

(3)可选的大括号:如果主体包含了一个语句,就不需要使用大括号

(4)可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值

2. 方法引用

    @FunctionalInterface
    public interface Supplier<T> {
        T get();
    }
     
    class Car {
        // Supplier是jdk1.8的接口,这里和lamda一起使用了
        public static Car create(final Supplier<Car> supplier) {
            return supplier.get();
        }
     
        public static void collide(final Car car) {
            System.out.println("Collided " + car.toString());
        }
     
        public void follow(final Car another) {
            System.out.println("Following the " + another.toString());
        }
     
        public void repair() {
            System.out.println("Repaired " + this.toString());
        }
    }
1)构造器引用:Class::new,或者更一般的Class< T >::new ,注意:这个构造器没有参数
		final Car car = Car.create( Car::new );
		final List< Car > cars = Arrays.asList( car );
2)静态方法引用:Class::static_method, 注意:这个方法接受一个Car类型的参数
        cars.forEach( Car::collide );
3)特定类的任意对象的方法引用:Class::method ,注意,这个方法没有定义入参
        cars.forEach( Car::repair );
4)特定对象的方法引用:instance::method ,注意:这个方法接受一个Car类型的参数
		final Car police = Car.create( Car::new );
		cars.forEach( police::follow );

3. 函数式接口

1)概念
(1)函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口

(2)函数式接口可以被隐式转换为 lambda 表达式,函数式接口可以对现有的函数友好地支持 lambda

(3)那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):

	@FunctionalInterface
	interface GreetingService 
	{
	    void sayMessage(String message);
	}

	GreetingService greetService1 = message -> System.out.println("Hello " + message);
2)关于 @FunctionalInterface 注解
(1)Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错

(2)加不加 @FunctionalInterface 对于接口是不是函数式接口没有影响,该注解只是提醒编译器去检查该接口是否仅包含一个抽象方法

(3)函数式接口里是可以包含默认方法,因为默认方法不是抽象方法,其有一个默认实现,所以是符合函数式接口的定义的

(4)函数式接口里是可以包含静态方法,因为静态方法不能是抽象方法,是一个已经实现了的方法,所以是符合函数式接口的定义的

(5)函数式接口里是可以包含Object里的public方法,这些方法对于函数式接口来说,不被当成是抽象方法(虽然它们是抽象方法);因为任何一个函数式接口的实现,默认都继承了 Object 类,包含了来自 java.lang.Object 里对这些抽象方法的实现	
3)java8四大函数式接口
(1)Function<T, R>  		T:入参类型,R:出参类型

	a. 方法    R apply(T t)

	b. 示例

		Function<Integer, Integer> func = p -> p*10;
        Integer result = func.apply(10);
        System.out.println("result = " + result);       

(2)Consumer<T>      		T:入参类型;没有出参

	a. 方法   				void accept(T t)

	b. 示例

		Consumer<String> consumer = p -> System.out.println("p = " + p);
		consumer.accept("消费者你好啊");

(3)Supplier<T> 			T:出参类型;没有入参

	a. 方法   				T get()

	b. 示例

		Supplier<Integer> supplier = () -> 100;
		Integer supplierResult = supplier.get();
		System.out.println("supplierResult = " + supplierResult);

(4)Predicate<T>        	T:入参类型;出参类型是Boolean

	a. 方法		            boolean test(T t)

	b. 示例

		Predicate<Integer> predicate = p -> p % 2 == 0;
        Boolean predicateResult = predicate.test(100);
        System.out.println("predicateResult = " + predicateResult);

        10. Predicate	

	c.概念

		i.   Predicate接口主要用来判断一个参数是否符合要求,类似于Junit的assert

		ii.  Predicate是一个函数式接口,可以被应用于lambda表达式和方法引用

		iii. 可以用Predicate<T>结合lambda表达式来定义一些判断条件

	d. 正则表达式表示为Predicate

		i. Predicate<String> emailFilter = Pattern.compile("^(.+)@example.com$").asPredicate();	

4. 默认方法

1)Java 8 新增了接口的默认方法。简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法

2)我们只需在方法名前面加个 default 关键字即可实现默认方法

3)Java 8 的另一个特性是接口可以声明(并且可以提供实现)静态方法

4)一个接口有默认方法,考虑这样的情况,一个类实现了多个接口,且这些接口有相同的默认方法,解决方案如下:

	(1)第一个解决方案是创建自己的默认方法,来覆盖重写接口的默认方法

	(2)第二种解决方案可以使用 super 来调用指定接口的默认方法(比如 Vehicle.super.print())

5)为什么要有这个特性?

	(1)当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现

	(2)然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题

6)由于JVM上的默认方法的实现在字节码层面提供了支持,因此效率非常高。默认方法允许在不打破现有继承体系的基础上改进接口。该特性在官方库中的应用是:给java.util.Collection接口添加新方法,如stream()、parallelStream()、forEach()和removeIf()等等

7)尽管默认方法有这么多好处,但在实际开发中应该谨慎使用:在复杂的继承体系中,默认方法可能引起歧义和编译错误	

5. Java 8 Stream (见 stream专篇)


6. Optional 类

1)概念
(1)Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象

(2)Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测

(3)Optional 类的引入很好的解决空指针异常
2)常用方法
(1)T get()									如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException

(2)boolean isPresent()						如果值存在则方法会返回true,否则返回 false

(3)T orElse(T other)	        				如果存在该值,返回值, 否则返回 other(传入一个默认值)

(4)static <T> Optional<T> of(T value) 		返回一个指定非null值的Optional

(5)static <T> Optional<T> ofNullable(T value) 如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional
3)经典用法
(1)Optional.ofNullable(user).ifPresent(a -> { do(a) });	            // 是否为空,不为空则执行lambda表达式

(2)Optional.ofNullable(user).filter( a -> {}).orElseGet(() -> { })    // if不为空else为空的场景

7. Nashorn JavaScript

1)概念
(1)从JDK 1.8开始,Nashorn取代Rhino(JDK 1.6, JDK1.7)成为Java的嵌入式JavaScript引擎

(2)Nashorn完全支持ECMAScript 5.1规范以及一些扩展。它使用基于JSR 292的新语言特性,其中包含在JDK 7中引入的 invokedynamic,将JavaScript编译成Java字节码

(3)与先前的Rhino实现相比,这带来了2到10倍的性能提升
2)jjs
(1)jjs是个基于Nashorn引擎的命令行工具。它接受一些JavaScript源代码为参数,并且执行这些源代码

3)Java 中调用 JavaScript
(1)使用 ScriptEngineManager, JavaScript 代码可以在 Java 中执行	

	ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
  	ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");	
  	nashorn.eval("print('" + name + "')"); // 括号里面执行js代码

8. 日期时间 API

1)旧版时间API问题
(1)非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一    

(2)设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计

(3)时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题  
2)新版
(1)Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:	

	a. Local(本地) − 简化了日期时间的处理,没有时区的问题

	b. Zoned(时区) − 通过制定的时区处理日期时间

(2)新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作		

(3)LocalDate/LocalTime 和 LocalDateTime 类可以在处理时区不是必须的情况

(4)如果我们需要考虑到时区,就可以使用时区的日期时间API:ZonedDateTime/ZoneId 

9. Base64

1)在Java 8中,Base64编码已经成为Java类库的标准。Java 8 内置了 Base64 编码的编码器和解码器	

2)Base64工具类提供了一套静态方法获取下面三种BASE64编解码器:

	(1)基本:输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/

	(2)URL:输出映射到一组字符A-Za-z0-9+_,输出是URL和文件

	(3)MIME:输出隐射到MIME友好格式。输出每行不超过76字符,并且使用'\r'并跟随'\n'作为分割。编码输出最后没有行分割

3)内嵌类	

	(1)static class Base64.Encoder            该类实现一个编码器,使用 Base64 编码来编码字节数据

	(2)static class Base64.Decoder			该类实现一个解码器用于,使用 Base64 编码来解码字节数据

10. 排序

1)常见排序
(1)Comparable,对于多元素排序,它的排序依据元素是固定的(compareTo()抽象方法只能实现一次,传入一个参数),因此排序方式固定

(2)Comparator,元素的排序依据元素是可变的,因为可以定义N多个外部类,每个外部类实现一种排序。在不同需求下,选择不同的排序(compare()方法是传入两个对比的参数)
2)java8新增排序方法
(1)Collections.sort(employees, (o1, o2) -> o1.getName().compareTo(o2.getName()));

(2)employees.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));

(3)employees.sort(Comparator.comparing(Employee::getName));

11. 其他

1)Java 8引入了重复注解的概念,使用@Repeatable注解定义重复注解,允许在同一个地方多次使用同一个注解

2)Java 8编译器在类型推断方面有很大的提升,在很多场景下编译器可以推导出某个参数的数据类型,从而使得代码更为简洁

3)Java 8拓宽了注解的应用场景。现在,注解几乎可以使用在任何元素上:局部变量、接口类型、超类和接口实现类,甚至可以用在函数的异常定义上

4)Java8版本新增了很多新的方法,用于支持并行数组处理。最重要的方法是parallelSort(),可以显著加快多核机器上的数组排序

5)并发性

	(1)基于新增的lambda表达式和steam特性,为Java 8中为java.util.concurrent.ConcurrentHashMap类添加了新的方法来支持聚焦操作;另外,也为java.util.concurrentForkJoinPool类添加了新的方法来支持通用线程池操作

	(2)Java 8还添加了新的java.util.concurrent.locks.StampedLock类,用于支持基于容量的锁——该锁有三个模型用于支持读写操作(可以把这个锁当做是java.util.concurrent.locks.ReadWriteLock的替代者)

	(3)在java.util.concurrent.atomic包中也新增了不少工具类

6)使用Metaspace(JEP 122)代替持久代(PermGen space)。在JVM参数方面,使用-XX:MetaSpaceSize和-XX:MaxMetaspaceSize代替原来的-XX:PermSize和-XX:MaxPermSize	

参考网址

菜鸟教程——Java 8 新特性

JAVA8 十大新特性详解

JAVA8之妙用Optional解决判断Null为空的问题

java8 四大核心函数式接口Function、Consumer、Supplier、Predicate

注:文章是经过参考其他的文章然后自己整理出来的,有可能是小部分参考,也有可能是大部分参考,但绝对不是直接转载,觉得侵权了我会删,我只是把这个用于自己的笔记,顺便整理下知识的同时,能帮到一部分人。
ps : 有错误的还望各位大佬指正,小弟不胜感激

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值