最近浏览Stack OverFlow寻求帮助时,发现国外一些coder已经在玩java12了。此时已是19年5月,去官网一览,发现j2ee 12上线已有些时日。其下载列表中,官网也只明列了:jdk12、11、8~
现在企业开发中,一般都是用的jdk8.其最主要原因是,低版本稳定啊。当然,很多小企业用的还是7、甚至老古董还在玩之前的版本(这位年轻人挺不客气啊
)其实,我觉得还有更多原因是因为:

Oracle收购了Sun公司后,就像其收购了MySql一样,有闭源的风险。
之前一段时间很讨厌苹果公司,其App Store收取开发者30%的服务费,觉得它吃相难看,再后来,腾讯有了小程序和苹果对弈,苹果妥协。但腾讯要收取50%,此事不妥,后又改为流水超过50w再收,不超则免。哎,真的是,每个屠龙勇士屠完龙之后自己又变成了恶龙~不过也期望某天有人屠了Oracle吧
好了,正文开始~
java SE jdk8新特性如下:
1 默认方法2 函数式接口3 Lambda 表达式4 方法引用5 Stream6 Optional 类7 Nashorn, JavaScript 引擎8 新的日期时间 API9 Base64
这个顺序是小可特意排的,因为前6个都与Lambda、Stream有关,但学习得有先后之分,此处也只会浅析前6个特性。
1.默认方法
简单说,默认方法就是接口中可以有方法体,实现类可以选择不去实现该方法
语法:接口中,方法前+个default关键字,即可声明为默认方法
为什么要有这个特性?
接口的缺点:当需要修改接口时候,需要修改全部实现该接口的类。
目前jdk7及之前的集合框架没有forEach方法,通常能想到的解决方案是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法再给接口添加新方法的同时不影响已有的实现。所以引进了默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题
既然接口中能有方法体了,那么接口中也就可以有静态方法了。但是default不能与static一起使用奥~
2.函数式接口
很简单,函数式接口,定义就是接口中有且只有一个抽象方法。
你可能会说,接口中不就只能有抽象方法么,那不就是只有一个方法的接口?那是java7及以前了。现在接口中除了抽象方法,还可以有默认方法呀~
除了上文中的定义,函数式接口你还需要注意以下两点:
1>函数式接口可以定义Object定义过的任何公有方法。即Object的公有方法被视为函数式接口的隐式成员。因为函数式接口的实例会默认自动实现它们
2>默认方法和静态方法,不会违反函数式接口的约定
简单实例:
@FunctionalInterface //该注解【可选】用以声明:该接口是一个函数式接口。作用:使用该注解后,该接口下只能有一个抽象方法,多了报错public interface ITest{void say(String msg);}
jdk8中在java.util.function包下增加了一系列函数式通用接口,如:
Predicate<T>,Consumer<T>,Function<T,R>,Supplier<T>等等。给大家说这些是让它们混个眼熟。在使用Stream的Api中,你会发现,很多API的参数类型就是这些接口。它们实质上,就是官方定义了一些通用的方法。如Predicate<T>,该接口中有个:boolean test(T t)方法,可以返回个boolean值。当你需要个断言时,就可以使用这个Predicate官方接口来实现了
3.Lambda表达式
这是java语言自范型、注解后,发布的另一个重要的新特性了。
λ表达式语法:
1.(parameters) -> expression //表达式
2.或者 (parameters) ->{ statements; } //陈述句
语法特点:
1.可选类型声明:不需要声明参数类型即可
2.可选参数的圆括号:当有多个参数时才必需加上圆括号
3.可选的大括号: 如果主体中只有一条语句,就不需要大括号
4.可选的返回关键字:如果主体中只有一个表达式,则编译器自动返回值
优点:
1>允许把函数作为一个方法的参数(有丢丢像面向函数编程靠近了
)
2>使用λ表达式可以使代码更加简洁紧凑
使用场景:作为函数式接口的实现(当然,为承接上文,此处demo主要为此)
简单实例:
//定义一个函数式接口interface ITest{void say(String msg);}public static void main(String[] args) {//java7可以使用匿名内部类来写这个接口的实现ITest test1 = new ITest() {@Overridepublic void say(String msg) {System.out.println(">>>>>>>>>"+msg);}};//java8使用LambdaITest test2 = (msg) -> System.out.println(msg);}
缺点:
1.Lambda的语句中,不能抛出异常,需要手动处理
2.不能控制流程,比如在forEach方法中,λ表达式不能continue或break等
3.Lambda中变量不能更改,即可看做隐式常量
这么点缺点,丝毫不影响它的使用方便啊~
4.方法引用
双冒号操作符::
双冒号运算操作符是类方法的句柄,Lambda表达式的一种简写
语法如下:
类名::方法名
注意:
1.方法名后没有()
2.懒加载方法是否调用要看调用方使用情况
实例:
//java8使用LambdaITest test2 = (msg) -> System.out.println(msg);//替换为如下:ITest test2 = System.out::println;
5.Stream
介绍:Stream(流)是一个来自数据源的元素队列并支持聚合操作。简单来说,就是对集合做操作的~
1.其内元素是特定类型对象<范型>,形成一个队列。Stream并不会存储元素,而是按需计算
2.数据源:流的来源可以是集合、数组、I/O channel等
3.聚合操作:类似SQL语句的操作。比如filter、map、sorted等
特征:
1.中间操作都会返回流对象本身。这样多个操作可以串连成一个管道
2.内部迭代:以前对集合遍历都是通过Iterator或者for-each方式,显式得在集合外部进行迭代叫外部迭代。Stream通过访问者模式提供了内部迭代的方式
集合对象生成流对象:
java.util.Collection接口中提供了两个默认方法:
1> default Stream<E> stream(){...} //串行流2> default Stream<E> parallelStream(){...} //并行流
实例:
//取出List<User>中,对象年龄是23的其记录idList<Long> ids = list.stream().filter(n -> n.getAge() == 23).map( n -> n.getUid()).collect(Collectors.toList());
Steam流对象提供的API:forEach()、filter()、map()、sorted()等等。精力有限,诸多末节,不做细述。
6.Optional
这个特性挺没劲的,如果不是Stream流,我压根没打算用这个对象。
介绍:Optional类是jdk8中引入的一个可以为null的容器对象,其引入主要是为了避免我们太多精力去判断对象是否为null,解决空指针异常......(其实吧,使用了这个对象未必比我加一句判断省劲吧)所以,挺没趣的,记你这么多API徒然浪费我有限的脑存。了解下就好
其是个容器:它可以保存类型T的值,或者保存null。如果值存在则isPresent()方法会返回true,然后调用get()方法会返回该对象
在Stream流对象中,返回值为Optional常用的成员方法有:
Optional<T> findFirst(); //拿到流对象[集合]中的第一条数据,放在Optional容器中Optional<T> findAny();
实例:
//给新List的每条数据set对应值,若users集合中未找到数据,则设置nulllist.forEach( n -> n.setUser(users.stream().filter(m -> m.getAge()==23).findFirst().orElse(null)));
好了,以上是关于jdk8中比较重要的新特性了。主要是Lambda表达式与Stream流对象~
java也不再向以往一样总是古板不变了,面向对象与面向函数各有优劣。什么技术都不是一成不变,可以一统江湖的。语言也好,框架也罢,都是为了将所有现实的业务场景抽象得抽离出一套统一形式来,方便大家开发,提升效率~
接下来一段时间,可能没太多精力,以后抽空再来陆续总结所得吧
SEE U




