java8新特性介绍

本文介绍了Java 8的四大新特性:接口的默认方法、静态方法,深入探讨函数式接口的概念、API及@FunctionalInterface注解,以及Lambda表达式的语法和作用域规则。通过实例讲解Lambda表达式和方法引用的使用,帮助开发者更好地理解和应用Java 8新特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.接口的默认方法

1.1传统的方法(之前的)

 在java8之前java中接口里面的方法默认都是 public abstract 修饰的抽象方法并且没有方法体

1.2 static方法

  1. 使用static修饰接口中的方法并且必须有主体
  2. 接口的static方法只能被接口本身调用
  3. 接口的static方法不能被子接口继承
  4. 接口的static方法不能够被实现类覆写及直接调用

1.3 default方法

学习了上面的static方法之后,这里模仿来学习 

  1. default方法必须有主体
  2. default方法可以被实现类覆写
  3. default方法可以被子接口继承
  4. default方法可以视作是接口定义时的初始化操作

2.函数式接口

2.1什么是函数式接口

函数式接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转化为lambda表达式

2.2函数式接口API

jdk1.8之前已有的函数式接口

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.util.Comparator
  • java.io.FileFilter
  • java.io.file.PathMatcher
  • ...

jdk 1.8新增的函数接口

java.util.function 此包中包含了很多类,用来支持JAVA的函数式编程

2.3函数式接口注解

@functionalInterface

我们在函数式接口上面加上此注解后,里面就只能够有一个抽象方法了,当然不加此注解且只有一个抽象方法的接口也是函数式接口,只是没有限定提示而已。 

3.Lambda表达式

3.1 什么是Lambda表达式

 简单来说,可以看成是匿名内部类的简写,使用Lambda表达式时,接口必须是函数式接口(有且仅有一个抽象方法)。

3.2 Lambda表达式的语法

基本语法:

<函数接口名> <变量名> = (参数1,参数2...)->{

                    //方法体

}

特点说明:(参数1,参数2 ...)表示参数列表;

                  ->表示连接符

                 {}内部是方法体

  1. =右边的类型会根据左边的函数式接口类型自动判断
  2. 如果形参列表为空,只需保留();
  3. 如果形参只有1个,()可以省略,只需要参数的名称即可
  4. 如果执行语句只有1句,且无返回值,{}可以省略,若有返回值,则若想省略{},则必须同时省略return,且执行语句也保证只有1句
  5. 形参列表的数据类型会自动判断
  6. lambda不会生成一个单独的内部类文件
  7. lambda表达式若访问了局部变量,则局部变量必须是final的,若是局部变量没有加final关键字,系统会自动添加,此后在修改该内部局部变量,会报错

3.3 Lambda学习案例代码

目录结构:

Myinterface文件:

MyinterfaceImpl文件:

Test文件:

package com.dhh.Lambda1;


import com.dhh.defaultMethod.ExtendInterfaceImpl;

public class Test {
    public static void main(String[] args) {
        //传统方式 创建一个MyInteferaceImpl类 然后调用对应的方法
        MyInterface myInterface = new MyInteferaceImpl();

        //不创建MyInteferaceImpl类,使用匿名内部类的方式,这样可以省略MyInteferaceImpl文件,在内部类里实现方法
        MyInterface myInterface1 = new MyInterface() {
            @Override
            public int sum(int num1, int num2) {
                return num1 + num2;
            }
        };

        /**
         * 使用Lambda表达式的方法
         * 【常规写法】获取形参,方法体,用 -> 连接
         **/
        MyInterface myInterface2 = (int num1, int num2) -> {
            return num1 + num2;
        };

        /**
         *  使用Lambda表达式的方法
         * 【简写】1.形参列表的数据类型可以省略,会自动匹配
         *        2.如果方法中的代码只有一句,可以去掉{},如果是return返回数据的,那么可以省略return
         *
         **/
        MyInterface myInterface3 = (num1, num2) -> num1 + num2;
        System.out.println(myInterface3.sum(2, 4));
    }
}

3.4 Lambda作用域-final

  在Lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的某个字段以及静态变量。但如果访问局部变量,需要局部变量必须是final修饰的。

package com.dhh.Lambda2;


public class Test {
    public static void main(String[] args) {
        //定义一个局部变量
        int age = 9;
        MyInterface myInterface = ()-> System.out.println(age);
        age = 10;
        myInterface.printStr();
    }
}

上面代码中,在Lambda表达式用了局部变量age,则age会自动加上修饰符final,在对age赋值10,代码就会报错。

4.方法引用

4.1 构造方法引用

  1.准备一个Person类,提供一个两个参数的构造方法

package com.dhh.Lambda3;

public class Person {
    private String firstName;
    private String secondName;

    public Person(String firstName, String secondName) {
        super();
        this.firstName = firstName;
        this.secondName = secondName;
    }

    @Override
    public String toString() {
        return "Person{" +
                "firstName='" + firstName + '\'' +
                ", secondName='" + secondName + '\'' +
                '}';
    }
}

2.准备一个personFactory接口

package com.dhh.Lambda3;

//获取person对象的工厂接口,也是函数式接口
public interface PersonFactory {
    /**获得Person对象的方法**/
    Person createPerson(String firstName,String secondName);
}

3.不同写法获得person对象

package com.dhh.Lambda3;


import com.dhh.Lambda2.MyInterface;

public class Test {
    public static void main(String[] args) {
        /*
         *需求:
         *      有一个person对象
         *      有一个获得person对象的接口工厂
         *      想通过工厂获得person对象
         *       需要先有一个工厂对象
         */

        //使用匿名内部类的方式
       PersonFactory personFactory = new PersonFactory() {
            @Override
            public Person createPerson(String firstName, String secondName) {
                return new Person(firstName,secondName);
            }
        };
        //使用Lambda常规表达式
        PersonFactory personFactory1 = (firstName,secondName)->new Person(firstName,secondName);
        //使用Lambda表达式简单写法 构造方法引用(保证参数列表和构造参数方法列表一致)
        PersonFactory personFactory2 = Person::new;
        Person person = personFactory2.createPerson("kobe", "bryant");
        System.out.println(person);
    }
}

4.2 静态方法引用

1.准备一个函数式接口,提供一个解析字符串为int的方法

package com.dhh.Lambda4;

public interface ParseInterface {
    /**将字符串解析成int**/
    int parse(String str);
}

2.静态方法的引用

package com.dhh.Lambda4;


import com.dhh.Lambda2.MyInterface;

public class Test {
    public static void main(String[] args) {
        //匿名内部类 Integer.parseInt()为静态方法
       ParseInterface parseInterface = new ParseInterface() {
           @Override
           public int parse(String str) {
               return Integer.parseInt(str);
           }
       };
        //Lambda表达式 常规写法
        ParseInterface parseInterface1 = str->Integer.parseInt(str);

        //Lambda表达式 简写【静态方法引用】 把参数原封不动给Integer调用parseInt方法
        //与构造方法一致,参数未作任何处理继续给构造方法或静态方法调用,则可以采用引用方式
        ParseInterface parseInterface2 = Integer::parseInt;

        int parse = parseInterface.parse("123");

    }
}

4.3 实例方法引用(了解,主要体会场景)

package com.dhh.Lambda5;


import com.dhh.Lambda4.ParseInterface;

import java.util.HashMap;
import java.util.function.Function;

public class Test {
    public static void main(String[] args) {
        /*
         *需求:
         *  已知String中有一个实例方法(非静态的)endswith
         *  想自己写一个类封装这个方法
         *
         * 借助于jdk1.8的一个函数式接口function的apply方法(传入 T 返回 R)
         *           @FunctionalInterface
         *           public interface Function<T, R> {
         *           R apply(T var1);}
         *
         */
        //实例方法引用<T,R>指定数据类型
        //调用者对象s 入参 hello,返回:boolean值
        String s = "hello";
        Function<String,Boolean> function = s::endsWith;
        Boolean apply = function.apply(s);
        System.out.println(apply);
    }

}

 

小结:其实java8提供的Function函数式接口通用性非常强大,后续的学习会继续上传

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值