了解Java1.8新特性

  前几天电脑上的JDK自动更新到1.8,这两天了解了一下JDK1.8的一些新特性。下面就来浅谈一下我所了解的。

  我们都知道,Java是不能多继承的,但是可以多实现。它与C++不同,C++是可以多继承的。尽管Java可以实现多个接口,但是接口中只能有抽象方法,不能有具体的实现。但是在JDK1.8中,接口里新增了默认方法。可以对默认方法进行具体的实现,但是这个方法必须是default。看下面这段代码:

 1 interface AA{
 2     public int add(int a,int b);    //申明方法
 3     default void sing(String name){        //默认方法
 4         System.out.println("The song name is " + name);
 5     }
 6 }
 7
 8 public class CC implements AA{
 9     public static void main(String[] args){
10         AA aa = new AA(){    //匿名内部类
11             public int add(int a,int b){
12                 return (a + b);
13             }
14         };
15         aa.sing("The Bird And The Bee");    //方法调用
16         System.out.println(aa.add(5,3));
17     }
18 }

  在接口AA中,我们有两个方法,并且有一个默认方法。在main函数中,我们对AA中的add方法进行实现,之后调用AA中的两个方法,这段代码是正确的。现在来想一个问题,既然现在接口中可以有方法的实现,而且接口又是可以多继承的,那么如果两个接口中有同样的方法签名的两个方法,那么在实现这两个接口的实现类中,会有冲突吗?

  接口C继承了接口A和B,而在A,B中有相同方法签名的函数。注:函数的方法签名包括:函数名,参数个数,参数类型以及顺序,不包括返回值。代码如下:

 1 interface A1{
 2     default int add(int a,int b){
 3         return (a + b);
 4     }
 5     default void say(){
 6         System.out.println("Hello,I am A1");
 7     }
 8 }
 9
10 interface B1{
11     default int subtraction(int a,int b){
12         return (a - b);
13     }
14     default void say(){
15         System.out.println("Hello,I am B1");
16     }
17 }
18
19 interface C1 extends A1,B1{}

  上面这段代码在编译时候会出现错误。

  之后我们稍稍修改一下我们的接口C1,让它覆盖父接口的say()方法。并完善我们代码:

 1 interface A1{
 2     default int add(int a,int b){
 3         return (a + b);
 4     }
 5     default void say(){
 6         System.out.println("Hello,I am A1");
 7     }
 8 }
 9
10 interface B1{
11     default int subtraction(int a,int b){
12         return (a - b);
13     }
14     default void say(){
15         System.out.println("Hello,I am B1");
16     }
17 }
18
19 interface C1 extends A1,B1{
20     @Override
21     default void say(){
22         //B1.super.say();    指定调用父接口中的say()
23         System.out.println("Hello,I am C1");    //有自己的实现
24     }
25 }
26
27 public class Test implements C1{
28     public static void main(String[] args){
29         Test t = new Test();
30         t.say();
31         System.out.println(t.add(3,5));
32         System.out.println(t.subtraction(5,2));
33     }
34 }

  我们使用覆盖父类的方式来避免上面错出现的冲突。在覆盖方法中,我们可以有自己的实现,也可以指定实现某个父接口中的方法。好,解决了这个问题,我们来继续思考另外一个问题,如果一个子类继承一个基类并实现了一个接口,并且不幸的事,基类中有一个方法是接口中的默认方法,此时又会出现冲突吗?

  代码如下:

 1 interface A1{
 2     default int add(int a,int b){
 3         System.out.println("add() in interface A1 ---> ");
 4         return (a + b);
 5     }
 6     default void say(){
 7         System.out.println("Hello,I am interface A1");
 8     }
 9 }
10
11 class A2{
12     public int add(int a,int b){
13         System.out.print("add() in class A2 ---> ");
14         return (a + b);
15     }
16     public void say(){
17         System.out.println("Hello,I am class A2");
18     }
19 }
20
21 public class Test extends A2 implements A1{
22     public static void main(String[] args){
23         Test t = new Test();
24         t.say();
25         System.out.println(t.add(3,5));
26     }
27 }

  运行结果如下:

  从结果可以看出,当基类和接口中的默认方法具有相同方法签名的函数时,子类优先继承基类中的函数实现,而不是父接口中的默认方法。如果父类没有相同的方法签名,子类才会继承接口中的默认方法。说了这么多关于默认方法,想一想JDK1.8为什么要新增加这一特性呢?由于Collection库需要为批处理操作添加新的方法,如forEach(),stream()等,但是不能修改现有的Collection接口——如果那样做的话所有的实现类都要进行修改,包括很多客户自制的实现类。拿forEach()方法来说,以前我们遍历一个集合的时候,都是自己写遍历操作的代码,相信下面这段代码我们都是很熟悉的:

 1 import java.util.*;
 2
 3 public class Newlist{
 4     public static void main(String[] args){
 5         List<String> strList = new ArrayList<String>();
 6         strList.add("123");
 7         strList.add("234");
 8         strList.add("345");
 9         strList.add("456");
10         strList.add("567");
11
12         for(String list : strList){
13             System.out.println(list);
14         }
15     }
16 }

  但是现在不必要这么麻烦了,我们可以直接使用现成的方法进行遍历。使用下面这行代码,代替上面的for循环,即可。

list.forEach(o->{System.out.println(o);});

  forEach()方法在List接口中就是一个默认方法,所以所有实现了这个接口,继承这接口的类或接口都具有这个方法,这就是新增默认方法的原因。

  这行代码又引出了一个新特性-->lambda表达式。lambda表达式就是一个匿名函数,主要用于替换以前广泛使用的内部匿名类,各种回调,比如事件响应器、传入Thread类的Runnable等。Java8有一个短期目标和一个长期目标。短期目标是:配合“集合类批处理操作”的内部迭代和并行处理(上面将已经讲到);长期目标是将Java向函数式编程语言这个方向引导(并不是要完全变成一门函数式编程语言,只是让它有更多的函数式编程语言的特性,关于函数式编程语言和命令式编程语言请参看这篇博客http://blog.jobbole.com/42178/),也正是由于这个原因,Oracle并没有简单地使用内部类去实现λ表达式,而是使用了一种更动态、更灵活、易于将来扩展和改变的策略(invokedynamic)。下面举个简单例子了解lambda表达式:

 1 interface A{            //函数接口
 2     public int add(int a,int b);
 3     boolean equals(Object obj);
 4     default void say(){
 5         System.out.println("Hello,I am A");
 6     }
 7 }
 8 public class Lambda implements A{
 9     public static void main(String[] args){
10         /* A a = new A(){    匿名内部类实现add()
11             public int add(int a,int b){
12                 return (a+b);
13             }
14         }; */
15         A a = (x,y)->{return (x+y);};
16         a.say();
17         System.out.println(a.add(5,3));
18     }
19 }

  在上面的main中我们使用了lambda表示式对接口A中add()方法进行了实现,上面注释是我们不使用表达式而是使用匿名内部类去实现接口中的非默认方法。可以看出,λ表达式是由(参数)、->、{}三部分构成的。左边是接口定义方法的参数,可以省略参数类型,并且只有当方法仅唯一参数时,小括号才能省略,没有参数应该写成()。表达式右边是代码块,也就是我们平时书写函数体中的内容。请注意:能够使用λ表达式的目标类型必须是函数接口,函数接口的定义是:一个接口,如果只有一个显式声明的抽象方法,那么它就是一个函数接口。一般用@FunctionalInterface标注出来(也可以不标)。说的简单一点就是在一个接口中只有一个显示申明的函数。在上面的例子中,我们的接口A就是函数接口,因为只有一个显示申明的add()。你可能疑惑,那equals方法呢?equals方法是Object的,所有的接口都会声明Object的public方法——它是隐式的。下面举一个线程的例子:

 1 public class Lambda{
 2     public static void main(String[] args){
 3         Thread tt = new Thread(new Runnable(){    //一般做法
 4             public void run(){
 5                 for(int i=0;i<100;i++){
 6                     System.out.println("normal function!");
 7                 }
 8             }
 9         });
10
11         Thread tt = new Thread(()->{    //使用lambda表示式
12             for(int i=0;i<100;i++){
13                     System.out.println("lambda expression!");
14                 }
15         });
16     tt.start();
17     }
18 }

  JDK1.8有很多新特性,我列出的只是很小一部分,作为Java语言忠实的粉丝,感觉学习Java越来越有趣。

  参考博客:http://blog.csdn.net/ioriogami/article/details/12782141

时间: 2024-12-15 21:13:22

了解Java1.8新特性的相关文章

java1.8新特性(一)

一直在更新java 版本,原来也没有关注java版本的变化 引入的一些新的api  引起注意的还是  关于一些并发包的使用,那时候才对每个版本的特性 去了解了一下,虽然 不一定都用上了,但是不管学习什么语言,花点时间学习新的api还是很有必要的,在工作中 还用一些 1.8的新特性,但是 始终 是 不明白.总是有问题,特意花些时间 去重点学习一下,如果其中 有什么说的不对,请一定要提出来! 用户 对象 User: package com.java; public class User { Stri

java1.4升级到java1.5 新特性

前几天和一位腾讯的技术大牛聊天,聊到关于jdk的很多支持,包括jvm的优化,gc的调用机制,1.4-到1.8每次升级版本的新特性等,做软件这行这么多年了,一直在使用java,但是却从来没有细细的研究每个版本新特性到底有什么不同,所以特意编写了这么一篇文档,让自己能了解些他们的新特性,也共享一下新特性的改变,当然我下面的验证并不能当做最官方的,但最起码我是一个一个实验了,如果存在问题或解释的不正确的,也劳烦各位大牛给予指正. 目前我下载的jdk版本,如果大家需要这些版本的话,后期我会上传到百度云上

Java1.8新特性

1.Lambda表达式和函数式接口 Lambda表达式(也称为闭包)是Java 8中最大和最令人期待的语言改变.它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理:函数式开发者非常熟悉这些概念.很多JVM平台上的语言(Groovy.Scala等)从诞生之日就支持Lambda表达式,但是Java开发者没有选择,只能使用匿名内部类代替Lambda表达式. Lambda的设计耗费了很多时间和很大的社区力量,最终找到一种折中的实现方案,可以实现简洁而紧凑的语言结构.最简单的Lambda表

java1.8 新特性(五 如何使用filter,limit ,skip ,distinct map flatmap ,collect 操作 java集合)

使用filter 根据 条件筛选 出结果:例如 找出 user 中 age >=15 的用户 package lambda.stream; /** * @author 作者:cb * @version 创建时间:2019年1月4日 下午2:35:05 */ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; publi

java1.8 新特性(关于 match,find reduce )操作

match处理Integer集合 package lambda.stream; /** * @author 作者:cb * @version 创建时间:2019年1月4日 下午2:35:05 */ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class StreamDemo { public st

java1.8新特性(optional 使用)

经常在程序中出现 java.lang.NullPointerException  为了避免  报错,总是要进行一些 是否为null 的if else 判断 ,1.8 可以使用optional 类 来简化处置   optional :A container object which may or may not contain a non-null value.:可能包含也可能不包含非空值的容器对象. 既然optional 是一个容器对象,那就应该先创建该 对象 才能调用该对象的一些方法 创建op

黑马程序员------Java中jdk1.5新特性

Java培训.Android培训.iOS培训..Net培训.期待与您交流! JDK1.5新特性: 为什么会出现新特性: 新的技术出现是为了解决老的问题,Java语言为了提高开发者的开发效率,对之前的某些不利于提高效率的技术进行改进. 静态导入: 静态导入:可以导入某个类下的静态方法,静态导入后,可以不写类名而直接使用此类下的静态方法. 语法:import static 包名.类名.静态方法 代码示例: package com.itheima.day1; /** * 静态导入 * @author

JAVA JDK1.5-1.9新特性

JAVA JDK1.5-1.9新特性 1.5 1.自动装箱与拆箱: 2.枚举(常用来设计单例模式) 3.静态导入 4.可变参数 5.内省 1.6 1.Web服务元数据 2.脚本语言支持 3.JTable的排序和过滤 4.更简单,更强大的JAX-WS 5.轻量级Http Server 6.嵌入式数据库 Derby 1.7 1,switch中可以使用字串了 2.运用List tempList = new ArrayList<>(); 即泛型实例化类型自动推断 3.语法上支持集合,而不一定是数组 4

java1.5的新特性

java1.5的新特性. java作为一门语言,是sun公司出品,这门语言有自己的语法规范.同时围绕着这门语言有一些基本的类库来供大家使用. 一门程序设计语言,可以简单的认为包含两部分,一个是基本的语法规则(包括关键字),另一个是用来支持这门语言的一些系统级得到基础类库. 所以,一门程序设计语言是可以不断被升级更新的,升级更新后的语言可能会增加新的语法规范. java1.5和java1.4作为不同版本的java语言,就有些不一样的地方: 所以就有java1.5的新特性需要掌握: 1.java1.