2014年发布的Java8,现在应该是业界使用最普遍的Java版本,可很多Java开发人员并没有充分发挥这4年前发布的版本的优点,

本文就是带着“学以致用”的目的去了解Java8,挖掘编码中可提高效率的特性。

什么是Java8?官网第一句话解释

Java Platform, Standard Edition  is a major feature release.
注:虽然Java现在半年迭代一次,但LTS版本依然保持3年一个版本的计划(比如从Java8到Java11)

1. Java Programming Language

首先是编程语法的增强

1) Lambda表达式:更多的场景是跟“函数式接口”结合。(注:函数式接口只有一个抽象方法)例:

public class Java8Tester {
public static void main(String args[]){
Java8Tester tester = new Java8Tester(); // 类型声明(MathOperation是在本Class中定义的内部接口)
MathOperation addition = (int a, int b) -> a + b; // 不用类型声明
MathOperation subtraction = (a, b) -> a - b; // 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; }; // 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b; System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division)); // 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message); // 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message); greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
} interface MathOperation {
int operation(int a, int b);
} interface GreetingService {
void sayMessage(String message);
} private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
}
}

注意:lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

2) 方法引用:特点是一对引号引用方法,包括构造方法,静态方法,实例方法等的引用,可跟Lambda表示式结合使用,例:

import java.util.List;
import java.util.ArrayList; public class Java8Tester {
public static void main(String args[]){
List names = new ArrayList(); names.add("Google");
names.add("Runoob");
names.add("Taobao");
names.add("Baidu");
names.add("Sina"); names.forEach(System.out::println);
}
}

 3)函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法(无实现),但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。

Java8之前一直被匿名类实现,并不是说之前没有函数式接口,只是实现方法不同罢了,比如以下类就是函数式接口,就经常被匿名类实现

java.lang.Runnable // 用于线程实现
java.util.concurrent.Callable // 也用于线程,跟Runnable不同的是可以返回值,抛出异常
java.security.PrivilegedAction // 用于异步编程,一般用于AccessController.doPrivileged
java.util.Comparator // 类之间的比较,排序
java.io.FileFilter // 文件或者路径名匹配
java.nio.file.PathMatcher // NIO的文件路径匹配
java.lang.reflect.InvocationHandler // 反射中的动态代理接口(Spring的AOP就是通过动态代理实现的)
java.beans.PropertyChangeListener // 属性变更监听
java.awt.event.ActionListener // 动作监听
javax.swing.event.ChangeListener // 用户界面的变更监听

简单实例如下:

// Java8中添加此注解是为了编译级错误检查
@FunctionalInterface
interface GreetingService
{
void sayMessage(String message);
}

使用方法(lambda来表示一个实现):

GreetingService greetService1 = message -> System.out.println("Hello " + message);

Java8加上java.util.function包的很多函数式接口,比如典型Predicate:

Predicate <T> 接口是一个函数式接口,它接受一个输入参数 T,返回一个布尔值结果。

该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。

该接口用于测试对象是 true 或 false。

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate; public class Java8Tester {
public static void main(String args[]){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); // Predicate<Integer> predicate = n -> true
// n 是一个参数传递到 Predicate 接口的 test 方法
// n 如果存在则 test 方法返回 true
System.out.println("输出所有数据:"); // 传递参数 n
eval(list, n->true); System.out.println("输出所有偶数:");
eval(list, n-> n%2 == 0 ); System.out.println("输出大于 3 的所有数字:");
eval(list, n-> n > 3 );
} public static void eval(List<Integer> list, Predicate<Integer> predicate) {
for(Integer n: list) {
if(predicate.test(n)) {
System.out.println(n + " ");
}
}
}
}

上面输出大于3的更简单写法(过滤集合数据常用):

list.stream().filter(n -> n > 3).forEach(System.out::println);

4)接口的默认实现方法,这个不需多解释

5)允许重复注解:主要是为了代码的可读性比如@Authorize(role="USER") @Authorize(role="ADMIN")

6)注解可用于任何地方,不只类,属性,方法

7)改进的类型引用。例:

// <>中类型可以被编译器识别
List<Integer> = new ArrayList<>()

8)Method parameter reflection(通过反射取得方法参数):例:http://tutorials.jenkov.com/java-reflection/methods.html

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter; /**
* @author liuwei
* @date 2019/1/1
*/
public class TestMethodFlection { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class aClass = TestMethodFlection.class;
Method method = aClass.getMethod("test", int.class, int.class); // 包装类作为参数的话,也需要完全匹配
for (Parameter parameter : method.getParameters()) {
System.out.println("参数类型:" + parameter.getType());
}
System.out.println("返回类型" + method.getReturnType());
System.out.println("invoke方法结果为:" + method.invoke(null, 1, 2 )); // 静态方法的话,null作为第一个参数;否则,传具体object
} public static int test(int x, int y){
return x + y;
}

4)Optional:对于保存NULL对象的容器(很好的解决空指针异常)

public Integer sum(Optional<Integer> a, Optional<Integer> b){

      // Optional.isPresent - 判断值是否存在

      System.out.println("第一个参数值存在: " + a.isPresent());
System.out.println("第二个参数值存在: " + b.isPresent()); // Optional.orElse - 如果值存在,返回它,否则返回默认值
Integer value1 = a.orElse(new Integer(0)); //Optional.get - 获取值,值需要存在
Integer value2 = b.get();
return value1 + value2;
}

2. Collections

1)Stream(分串行模式和并行模式)

一个来自数据源的元素队列并支持聚合操作。典型用法:Pipelining,内部迭代。例:

// foreach
Random random = new Random();
random.ints().limit(10).forEach(System.out::println); // map(取得元素加工后的Value)
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList()); // 过滤空字符串
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
int count = strings.stream().filter(string -> string.isEmpty()).count(); // limit
Random random = new Random();
random.ints().limit(10).forEach(System.out::println); // 排序
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println); // 转化为Map
Map<String, String> versionMap = versions.stream().collect(Collectors.toMap(PersonAppVersion::getAppName, PersonAppVersion::getAppVersion));
// 并行程序(可以充分利用多CPU来加快处理速度)
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
int count = strings.parallelStream().filter(string -> string.isEmpty()).count(); // 统计
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());

2)HashMap的性能提升:key冲突机制变更

3. Compact Profiles

精简版的profile,使得可以将一个大的java项目部分编译成较小版本

4. Security

. 客户单默认使用TLS1.2协议(注:TLS和SSL的区别

5. Nashorn取代Rhino(JDK 1.6, JDK1.7)成为Java的嵌入式JavaScript引擎

   // Java中执行JS代码
public static void main(String args[]){ ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn"); String name = "Runoob";
Integer result = null; try {
nashorn.eval("print('" + name + "')");
result = (Integer) nashorn.eval("10 + 2"); }catch(ScriptException e){
System.out.println("执行脚本错误: "+ e.getMessage());
} System.out.println(result.toString());
}

 除此之外,jjs是个基于Nashorn引擎的命令行工具,可以直接执行js代码或者文件。另外,js中也可以执行Java代码,这个应用场景较少,就不再举例

6. 日期工具类

之前的日期工具类存在很多问题,比如线程安全,时区问题,让不熟悉的程序员掉入坑里。Java8中引入的最主要API如下:

  • Local(本地) − 简化了日期时间的处理,没有时区的问题。(包括Locatate,LocalDateTime等)

  • Zoned(时区) − 通过制定的时区处理日期时间。(包括ZonedDateTime等)

以上类都是线程安全的,java.time.Instant用于时间戳

Java8新特性参考:官网介绍

国内网站:http://www.runoob.com/java/java8-new-features.html

函数式接口:http://www.cnblogs.com/chenpi/p/5890144.html

重复注解:What can be real case use of Repeating annotations?

TLS和SSL:https://kb.cnblogs.com/page/197396/

动态代理机制:https://www.cnblogs.com/xiaoluo501395377/p/3383130.html

反射机制:http://tutorials.jenkov.com/java-reflection

Java8如何用的更多相关文章

  1. 如何用Java8 Stream API找到心仪的女朋友

    传统的的Java 集合操作是有些啰嗦的,当我们需要对结合元素进行过滤,排序等操作的时候,通常需要写好几行代码以及定义临时变量. 而Java8 Stream API 可以极大简化这一操作,代码行数少,且 ...

  2. Java8之——简洁优雅的Lambda表达式

    Java8发布之后,Lambda表达式,Stream等等之类的字眼边慢慢出现在我们字眼.就像是Java7出现了之后,大家看到了“钻石语法”,看到了try-with-resource等等.面对这些新东西 ...

  3. spring boot 初试,springboot入门,springboot helloworld例子

    因为项目中使用了spring boot ,之前没接触过,所以写个helloworld玩玩看,当做springboot的一个入门例子.搜索 spring boot.得到官方地址:http://proje ...

  4. spring-data-rest的魔力 10分钟实现增删改查

    目录 创建项目 启动项目 添加person 查看person 及 person 列表 条件查询 分页查询 controller 去哪里了 自定义 spring-data-rest 魔力之外的contr ...

  5. # Java Queue系列之PriorityQueue

    在上一篇中我用一张图来梳理了一下Java中的各种Queue之间的关系.这里介绍下PriorityQueue.PriorityQueue位于Java util包中,观其名字前半部分的单词Priority ...

  6. Spring Security 入门原理及实战

    目录 从一个Spring Security的例子开始 创建不受保护的应用 加入spring security 保护应用 关闭security.basic ,使用form表单页面登录 角色-资源 访问控 ...

  7. 何用Java8 Stream API进行数据抽取与收集

    上一篇中我们通过一个实例看到了Java8 Stream API 相较于传统的的Java 集合操作的简洁与优势,本篇我们依然借助于一个实际的例子来看看Java8 Stream API 如何抽取及收集数据 ...

  8. 手把手教你如何用java8新特性将List中按指定属性排序,过滤重复数据

    在java中常常会遇到这样一个问题,在实际应用中,总会碰到对List排序并过滤重复的问题,如果List中放的只是简单的String类型过滤so easy,但是实际应用中并不会这么easy,往往List ...

  9. Java8 如何进行stream reduce,collection操作

    Java8 如何进行stream reduce,collection操作 2014-07-16 16:42 佚名 oschina 字号:T | T 在java8 JDK包含许多聚合操作(如平均值,总和 ...

随机推荐

  1. Java日志组件logback使用:加载非类路径下的配置文件并设置定时更新

    Java日志组件logback使用:加载非类路径下的配置文件并设置定时更新 摘自: https://blog.csdn.net/johnson_moon/article/details/7887449 ...

  2. Mr_matcher的细节2

    1.参数服务器 ROS参数服务器能保存数据类型包括:strings, integers, floats, booleans, lists, dictionaries, iso8601 dates, a ...

  3. Mybatis_映射文件_Select

    一.Select元素来定义查询操作 Id:唯一标识符.用来引用这条SQL语句,需要和接口的方法名一致 parameterType:参数类型.可以不传,MyBatis会根据TypeHandler自动推断 ...

  4. 手打的table

    突然觉得,如果我不上传源码和写篇博客,对不起花在这个破网页2个小时的时间,完全手打,浏览器调效果. 源码如下: a.html: <!DOCTYPE html PUBLIC "-//W3 ...

  5. JavaScript -- Array中的push()方法和concat()方法介绍

    Array => push()方法向数组的末尾添加一个或者多个元素,也就是说它会改变数组本身 concat() => concat()方法用于连接2个或者多个数组,但它的特殊之处在于,它会 ...

  6. 远程访问Function时报错Remote table-valued function calls are not allowed.

    开始是这样调用的:select * from [LinkedServer].[db name].dbo.[function name](param1, param2) 原因: Only table-v ...

  7. cbv+resful+APIView源码分析

    CBV源码分析 1概念:什么是cbv和fbv 已经什么是API class bass View ---基于类的视图 function bass View ---基于函数的视图 API(Applicat ...

  8. C# int?

    int?:表示可空类型,就是一种特殊的值类型,它的值可以为null用于给变量设初值得时候,给变量(int类型)赋值为null,而不是0int??:用于判断并赋值,先判断当前变量是否为null,如果是就 ...

  9. JSON Assertion(JSON断言)

    JSON断言允许你完成对JSON文档的校验,首先,如果如果数据不是JSON,则会解析失败:其次,JMeter会用指定语法寻找指定的path,如果没有找到,则会失败:第三,如果验证期望值为null,JM ...

  10. 日期 Date()

    1.Date 对象用于处理日期和时间.创建 Date 对象的语法:var myDate=new Date()Date 对象会自动把当前日期和时间保存为其初始值.2.参数形式有以下5种: new Dat ...