1.介绍
java8提供了默认接口方法,Lambda表达式,方法引用和重复注解等新的特性及API

2.允许在接口中有默认方法实现
Java 8 允许我们使用default关键字,为接口声明添加非抽象的方法实现。这个特性又被称为扩展方法: 
举例:

public interface PhoneService {
    void call();
    //接口中默认方法实现
    default String who(String name) {
        return "name"+name;
    }
}
1
2
3
4
5
6
7
3.lambad表达式
java中lambad表达式的实现有两个结构。一个是lambad表达式自身。另一个是函数式接口。

lambad表达式本质上是一个匿名(未命名)方法。 
函数式接口是仅包含一个抽象方法的接口。如Runnable接口

lambad表达式语法

(0个或多个参数) -> 语句块

如:() -> 3.14 ; (n) -> {return n*10;}

3.1 lambad 函数式接口
把一个lambad表达式赋给一个函数式接口的引用时。会自动创建实现函数式接口的一个类的实例。

举例: 
定义一个函数式接口:

public interface PhoneService {
    void call();

default String who(String name) {
        return "name"+name;
    }
}
1
2
3
4
5
6
7
测试:

public class LambadTest {
    public static void main(String[] args) {
        PhoneService service = () -> {System.out.println("call");};
        service.call();
    }
}
1
2
3
4
5
6
lambad表达式的参数要么显示指定。要么程序可以根据上下文做隐式的推断。 
举例:

public interface DogService {
    String who(String name);
}

public class LambadTest {
    public static void main(String[] args) {
        //单个表达式 可以省略{}
        DogService service = (name) ->  "name is:" + name;

//根据上下文推断上下文类型;多个表达式要指定{}
        DogService service1 = (name) -> {
            System.out.println("wangwang");
            return "name is:" + name;
        };
        //强制指定参数类型
        DogService service2 = (String name) -> {
            return "name is:" + name;
        };

//抽象方法只有一个参数时可以忽略()括号
        DogService service3 = name -> {
            return "name is" + name;
        };

System.out.println(service.who("haha"));
        System.out.println(service1.who("xiaozhang"));
        System.out.println(service2.who("xiaoma"));
        System.out.println(service3.who("xiaowang"));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
3.2 lambad 泛型函数式接口
lambad表达式自身不能指定类型参数。因此lambad表达式不能是泛型。但是与lambad是关联的函数式接口的参数可以是泛型。此时,lambad表达式中的参数有调用接口时指定的参数类型来决定具体的类型。

举例:

public interface SomeFunc<T> {
    T fun(T t);
}

public class FanTest {
    public static void main(String[] args) {
        SomeFunc strFun = (str) -> str +"";

System.out.println(strFun.fun(1));
        System.out.println("hello");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
3.3 作为参数传递lambad表达式
把lambad表达式作为参数传给函数体。这是lambad式最常见的用途。也是lambad最强大的表达式,因为可以将可执行代码块最为参数传递给方法。这极大的增强了java的表达能力。

为了将lambad表达式作为参数传递。接收lambad表达式的参数类型必须是与该lambad表达式兼容的函数式接口的类型。

举例:

public interface StringFunc {
    String func(String n);
}

public class LambadAsArgumentDemo {
    static String stringOp(StringFunc sf,String s) {
        return  sf.func(s);
    }

public static void main(String[] args) {
        String result = stringOp((n) -> n.toUpperCase(),"hello");
        System.out.println(result);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
3.3 lambad表达式与异常
lambad表达式可以抛出异常。但是,如果抛出经检查异常,该异常必须与函数式接口的抽象方法的throws字句中列出的异常兼容。

举例:

public interface DoubleNumbicArrayFunc {
    double func(double[] n) throws  IllegalArgumentException;
}

public class LambadExceptionDemo {
    public static void main(String[] args) {
        double values[] = {1.0,2.1,3.2};
        DoubleNumbicArrayFunc func = n -> {
            if (n.length == 0) {
                throw new IllegalArgumentException("array empty");
            }

double sum = 0.0;
            for (double c:n) {
                sum = sum + c;
            }
            return sum / n.length;
        };

System.out.println(func.func(values));
        System.out.println(func.func(new double[0]));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
3.4 lambad表达式与变量捕获
lambad表达式可以获取或设置其外层类的实例或静态变量值。以及调用外层类定义的方法。

但是,当lambad使用其外层作用域定义的局部变量时,会产生一种特殊的情况,称为变量捕获。在这种情况下,lambad表达式只能使用实质上是final的局部变量。不能修改外层作用域的局部变量

举例:

public interface MyFunc {
    int func(int n);
}

public class MyFuncDemo {
    private int age = 24;

private static final String name = "zhangxj";

private void printName() {
        System.out.println("my name is zxj");
    }

public static void main(String[] args) {
        int height = 175;

MyFuncDemo demo = new MyFuncDemo();

MyFunc func = n -> {
            demo.printName();
            System.out.println(demo.age);
            demo.age = demo.age + 1;
            System.out.println(demo.age);
            System.out.println(MyFuncDemo.name);
            System.out.println(height);
            //对height只能访问。不能修改。否则报错
            return n + height;
        };
        System.out.println(func.func(12));
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
lambad可以使用和修改其调用类的实例变量,只是不能使用外层作用域内的局部变量,除非该变量实质上是final 变量。

方法引用

方法引用提供了一种引用而不执行方法的方式。这种特性与lambad表达式关联,因为它也需要由兼容的函数式接口构成的目标上下文。 
函数引用会创建函数式接口的一个实例。

3.5 静态方法的方法引用
ClassName::methodName

public interface StringFunc {
    String func(String n);
}

public class MyStringOps {
    public static String strUppcase(String str) {
        return str.toUpperCase();
    }
}

public class MethodRefDemo {

static String stringOp(StringFunc sf,String s) {
        return sf.func(s);
    }

public static void main(String[] args) {
        //静态方法引用
        String outStr = stringOp(MyStringOps::strUppcase,"lambads add power to java");
        System.out.println(outStr);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
3.6 实例方法的引用
objRef::methodName

public interface StringFunc {
    String func(String n);
}

public class MyStringOps {
    public  String strUppcase(String str) {
        return str.toUpperCase();
    }
}

public class MethodRefDemo {

static String stringOp(StringFunc sf,String s) {
        return sf.func(s);
    }

public static void main(String[] args) {
        MyStringOps ops = new MyStringOps();
        //引用方法实例
        String outStr = stringOp(ops::strUppcase,"lambads add power to java");
        System.out.println(outStr);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
3.7 泛型中的方法引用
在泛型类/泛型方法中。可以使用方法引用

public interface MyFunc<T> {
    int func(T[] vals,T v);
}

public class MyArrayOps {
    static <T> int countMatching(T[] vals,T v) {
        int count = 0;

for (int i = 0; i < vals.length;i++) {
            if (vals[i] == v) count++;
        }
        return count;
    }
}

public class GenericMethodRefDemo {
    static <T> int myOp(MyFunc<T> f,T[] vals,T v) {
        return f.func(vals,v);
    }

public static void main(String[] args) {
        Integer[] vals = {1,2,3,4,4,4,5,6};

int result = myOp(MyArrayOps::countMatching,vals,4);
        System.out.println(result);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
3.8 构造函数引用
className::new

可以把这个引用赋值给定义的方法与构造函数兼容的任何函数式接口的引用。

public interface MyFunc {
     MyClass func(int n);
}

public class MyClass {
    private int val;

public MyClass(int val) {
        this.val = val;
    }

public MyClass() {
        this.val = 0;
    }

public int getVal() {
        return val;
    }
}

public class ConstructRefDemo {
    public static void main(String[] args) {
        MyFunc myFunc = MyClass::new;

//创建MyClass的一个实例
        MyClass myClass = myFunc.func(100);

System.out.println(myClass.getVal());
    }
}

java的lamb表达式相关推荐

  1. 10个Java 8 Lambda表达式经典示例

    Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表 达式,它将允许我们将行为传到函数里.在J ...

  2. BeanShell中的Java指令和表达式

    我的博客原址:点击此处 BeanShell 能够理解标准的 Java 指令,表达式和方法的语法.那些指令和表达式都是在一个 Java 方法中你会提到的非常常见的东西,像变量的定义和分配,方法调用,循环 ...

  3. Java 8 Lambda 表达式详解

    版权声明:本文由吴仙杰创作整理,转载请注明出处:https://segmentfault.com/a/1190000009186509 1. 引言 在 Java 8 以前,若我们想要把某些功能传递给某 ...

  4. Java 8 Lambda表达式-接口实现

    Java 8 Lambda表达式在只有一个方法的接口实现代码编写中,可以起到简化作用: (argument list) -> body 具体看Runnable接口的例子 public class ...

  5. 这是一个有趣的问题,Java 8 Lambda 表达式被编译成了什么?

    在了解了Java 8 Lambda的一些基本概念和应用后, 我们会有这样的一个问题: Lambda表达式被编译成了什么? 这是一个有趣的问题,涉及到JDK的具体的实现.本文将介绍OpenJDK对Lam ...

  6. Java 8 Lambda 表达式被编译成了什么?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取个gui 在了解了Java 8 Lambda的一些基本概念和应用后, 我们会 ...

  7. java 8 lambda表达式中的异常处理

    文章目录 简介 处理Unchecked Exception 处理checked Exception 总结 java 8 lambda表达式中的异常处理 简介 java 8中引入了lambda表达式,l ...

  8. java 正则表达式 开头_如何在Java中修复表达式的非法开头

    java 正则表达式 开头 您是否遇到过这个令人难以置信的错误,想知道如何解决它? 让我们仔细阅读一下,研究如何解决表达式Java非法开头错误. 这是一个动态错误,这意味着编译器会发现某些不符合Jav ...

  9. 如何在Java中修复表达式的非法开头

    您是否遇到过这个令人难以置信的错误,想知道如何解决它? 让我们浏览一下这篇文章,研究如何解决表达式Java非法开头错误. 这是一个动态错误,这意味着编译器会发现某些不符合Java编程规则或语法的内容. ...

最新文章

  1. java list布局_java – 使用2种不同的布局重用Android Listvi...
  2. java基本语句回文数实验_实验二 java基本数据类型与把持语句.doc
  3. MSP430F5529 DriverLib 库函数学习笔记(七)定时器B
  4. ThreadLocal线程范围内的共享变量
  5. hdu 1514 记忆化搜索
  6. HttpClient4文件上传
  7. centos mysql
  8. fedora 23 vlc 以root运行的方法
  9. 主梁弹性模量计算_桥梁支座详解全攻略!图文+计算详解,值得收藏!
  10. Activity启动模式singleTask模式
  11. Raid磁盘阵列并管理
  12. 项目开发过程中遇到的问题和解决方法
  13. 入院前、入产房前、分娩前物品准备
  14. 输出n行数字三角形(已修改)
  15. domino-notes-Designer- java环境配置
  16. python 搜索引擎 词位置加权_网站搜索引擎推广公司,360关键词推广
  17. 为什么零信任网络的设计需求有优先级列表?
  18. 琢石成器――windows环境下32位汇编语言程序设计(第三版)笔记
  19. Windows系统在任务管理器中结束任务后电脑黑屏恢复
  20. 国科大计算机学院推免,电子科技大学2020届保研率17.8%,主要保研本校、国科大、北大、中科大...

热门文章

  1. [python自动化]简单实现接口自动化测试(基于python+unittest)
  2. 【NLP】文本分类微调技巧实战2.0
  3. java编程实现素数环_回溯法解决素数环
  4. MPEG、RM、WMV电影文件格式转换指南(转)
  5. 回眸01之美,六宫粉黛失色
  6. 回味小时候拿着诺基亚玩的推箱子
  7. tgp显示网络无法连接服务器,tgp显示未链接服务器
  8. 埃及分数 古埃及曾经创造出灿烂的人类文明,他们的分数表示却很令人不解。
  9. 試試看寫博客 留著參考用
  10. 对于项目开发中团队领导者的作用和影响的思考