Java8如何用
2014年发布的Java8,现在应该是业界使用最普遍的Java版本,可很多Java开发人员并没有充分发挥这4年前发布的版本的优点,
本文就是带着“学以致用”的目的去了解Java8,挖掘编码中可提高效率的特性。
什么是Java8?官网第一句话解释
Java Platform, Standard Edition is a major feature release.
注:虽然Java现在半年迭代一次,但LTS版本依然保持3年一个版本的计划(比如从Java8到Java11)
首先是编程语法的增强
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冲突机制变更
精简版的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如何用的更多相关文章
- 如何用Java8 Stream API找到心仪的女朋友
传统的的Java 集合操作是有些啰嗦的,当我们需要对结合元素进行过滤,排序等操作的时候,通常需要写好几行代码以及定义临时变量. 而Java8 Stream API 可以极大简化这一操作,代码行数少,且 ...
- Java8之——简洁优雅的Lambda表达式
Java8发布之后,Lambda表达式,Stream等等之类的字眼边慢慢出现在我们字眼.就像是Java7出现了之后,大家看到了“钻石语法”,看到了try-with-resource等等.面对这些新东西 ...
- spring boot 初试,springboot入门,springboot helloworld例子
因为项目中使用了spring boot ,之前没接触过,所以写个helloworld玩玩看,当做springboot的一个入门例子.搜索 spring boot.得到官方地址:http://proje ...
- spring-data-rest的魔力 10分钟实现增删改查
目录 创建项目 启动项目 添加person 查看person 及 person 列表 条件查询 分页查询 controller 去哪里了 自定义 spring-data-rest 魔力之外的contr ...
- # Java Queue系列之PriorityQueue
在上一篇中我用一张图来梳理了一下Java中的各种Queue之间的关系.这里介绍下PriorityQueue.PriorityQueue位于Java util包中,观其名字前半部分的单词Priority ...
- Spring Security 入门原理及实战
目录 从一个Spring Security的例子开始 创建不受保护的应用 加入spring security 保护应用 关闭security.basic ,使用form表单页面登录 角色-资源 访问控 ...
- 何用Java8 Stream API进行数据抽取与收集
上一篇中我们通过一个实例看到了Java8 Stream API 相较于传统的的Java 集合操作的简洁与优势,本篇我们依然借助于一个实际的例子来看看Java8 Stream API 如何抽取及收集数据 ...
- 手把手教你如何用java8新特性将List中按指定属性排序,过滤重复数据
在java中常常会遇到这样一个问题,在实际应用中,总会碰到对List排序并过滤重复的问题,如果List中放的只是简单的String类型过滤so easy,但是实际应用中并不会这么easy,往往List ...
- Java8 如何进行stream reduce,collection操作
Java8 如何进行stream reduce,collection操作 2014-07-16 16:42 佚名 oschina 字号:T | T 在java8 JDK包含许多聚合操作(如平均值,总和 ...
随机推荐
- YDNJS(上卷):this 的绑定对象
函数中的 this 是在调用时被绑定的,this 指向谁完全取决于函数的调用位置. 确定 this 的绑定对象的方式有 4 种. 默认绑定 默认绑定就是将函数中的 this 绑定给了全局对象 wind ...
- 数据库(学习整理)----7--Oracle导入导出数据库文件
Oracle导入本地数据库操作手册 1.旧数据库忘记了密码,首先进入cmd:1)输入:sqlplus/nolog2)输入:connect/as sysdba3)输入:alter user sys id ...
- 编写高质量代码改善C#程序的157个建议——建议20:使用泛型集合代替非泛型集合
建议20:使用泛型集合代替非泛型集合 在建议1中我们知道,如果要让代码高效运行,应该尽量避免装箱和拆箱,以及尽量减少转型.很遗憾,在微软提供给我们的第一代集合类型中没有做到这一点,下面我们看Array ...
- Javascript脚本 : eval()函数
Javascript 中 eval(X)函数 是将参数 当做语句来执行 var number1='1+2'; alert(number1); 输出为 '12': var number2=eval('1 ...
- DES加密与解密MD5加密帮助类
public class TrialHelper { //默认密钥向量 private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xA ...
- 多态的作用-游戏编程展示------新标准c++程序设计
游戏软件的开发最能体现面向对象设计方法的优势.游戏中的人物.道具.建筑物.场景等都是很直观的对象,游戏运行的过程就是这些对象相互作用的过程.每个对象都有自己的属性和方法,不同对象也可能有共同的属性和方 ...
- 多线程《七》信号量,Event,定时器
一 信号量 信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行,如果说互斥锁是合租房屋的人去抢一个厕所,那么信号量就相当于一群 ...
- python中局部变量和全局变量
局部变量,就是在函数内部定义的变量 不同的函数,可以定义相同的名字的局部变量,但是各用个的不会产生影响 局部变量的作用,为了临时保存数据需要在函数 在函数外边定义的变量叫做全局变量 全局变量能够在所有 ...
- 【Spring Boot-技巧】API返回值去除为NULL的字段
简介 在前后端分离的微服务时代,后端API需要良好的规范.本篇主要将一个数据返回时的一个小技巧-- 过滤为空字段 解决痛点:将有效解决数据传输过程中的流量浪费. 组件简介 Jackson Object ...
- linux系统安全及应用——端口扫描
NMAP是一款强大的网络扫描安全监测工具,通过扫描网络中不需要的服务端口来关闭这些服务,提高安全性.官网是http://nmap.org/,linux安装光盘中自带软件nmap-5.51.3.el6. ...