Java 8 新特性(1)

目录

1. 允许在接口中有默认方法实现

Java 8允许我们使用default关键字在接口中添加非抽象的方法实现,这个特性也称为扩展方法。

/**
 * Java 8新特性:允许使用default关键字在接口中添加非抽象的方法实现
 * 在接口中除了定义抽象方法query外,还定义了一个默认方法printUsername,该类的实现类只需要实现抽象方法query,在实现类中可以直接调用默认方法;
 */
public interface DefaultMainFieldExample {

    void query(String id);

    default void printUsername(String username) {
        System.out.println(username);
    }
}
/**
 * default默认关键字实现类
 * 在实现类中可以直接调用父类定义的默认方法
 */
public class DefaultMainFieldExampleImpl implements DefaultMainFieldExample {

    @Override
    public void query(String id) {
        System.out.println(id);
    }

    public static void main(String[] args) {
        DefaultMainFieldExampleImpl defaultMainFieldExample = new DefaultMainFieldExampleImpl();
        defaultMainFieldExample.query("001");
        // 直接调用父类定义的默认方法
        defaultMainFieldExample.printUsername("default");
        
		// 匿名对象
		DefaultMainFieldExample mainFieldExample = new DefaultMainFieldExample() {
            @Override
            public void query(String id) {
                printUsername(id);
            }
        };
        mainFieldExample.query("002");
        mainFieldExample.printUsername("default");
    }
}

2. Lambda表达式

先从一个简单的例子说起,如何对一个String列表排序;

// JDK 8以前的方式
// Collections.sort接收一个集合以及比较接口Comparator作为输入参数,可以指定一个匿名对象作为参数传递值
List<String> names = Arrays.asList("Java", "Python", "JavaScript");
Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
});

在Java 8中提供了一种相较于匿名对象更简洁的方法:Lambda表达式

// Lambda表达式
// 适用于接口只有且只有一个"抽象"方法,Lambda表达式必须与抽象方法的声明相匹配
// 如果实现代码只有一行,可以省略大括号以及return关键字
// Java编译器会自动识别参数类型,可以省略参数类型
// IDEA推荐不要直接对象比较(针对该例中的字符串比较)
// Collections.sort(names, (String a, String b) -> b.compareTo(a));
Collections.sort(names, (String a, String b) -> {
    return b.toLowerCase().compareTo(a.toLowerCase());
});
Collections.sort(names, (String a, String b) -> b.toLowerCase().compareTo(a.toLowerCase()));
Collections.sort(names, (a, b) -> b.toLowerCase().compareTo(a.toLowerCase()));

3. 函数式接口

Lambda表达式是如果精确匹配Java的类型系统的呢?

1.每一个Lambda表达式都通过一个特定的接口,和一个给定的类型匹配;
2.函数式接口:每一个函数式接口都有且只有一个抽象方法声明,每个与之对应的Lambda表达式必须要与抽象方法的声明相匹配;
3.默认方法不是抽象的,可以添加任意的默认方法;
4.任意只包含一个抽象方法的接口,我们都可以用来做成Lambda表达式;
5.@FunctionalInterface注解,约束接口中只能有一个抽象方法,否则抛出编译器错误;

// @FunctionalInterface注解:约束接口中只能有一个抽象方法,否则抛出编译器错误;可省略
@FunctionalInterface
public interface LambdaInterface<F, T> {

    T convert(F from);

    default void printTip(String username) {
        System.out.println(username);
    }
}
// 函数式接口
// Lambda如果匹配Java的类型系统?
// 每一个函数式接口都必须包含一个精确的抽象方法声明,接口的每个Lambda表达式都必须与该方法的声明相匹配
// 默认方法不是抽象的,可以添加任意的默认方法
// 只要满足函数式接口的定义:有且仅有一个抽象方法,就可以对任意接口作为Lambda表达式
// @FunctionalInterface注解,约束接口中只能有一个抽象方法,否则抛出编译器错误
LambdaInterface<String, Integer> lambdaInterface = (from) -> Integer.valueOf(from);
lambdaInterface.printTip("Lambda");
Integer integer = lambdaInterface.convert("003");
System.out.println(integer);

4. 方法和构造函数引用

Java 8允许通过关键字"::"获取方法或者构造函数的引用;

// 方法和构造函数引用
// Java 8允许通过"::"关键字获取方法和构造函数的引用
// 说明:使用"::”关键字时,只适用于仅一个参数的方法,构造函数除外;
// 静态方法引用
LambdaInterface<String, Integer> integerLambdaInterface = Integer::valueOf;
System.out.println(integerLambdaInterface.convert("004"));

// 对一个对象的方法引用
SomeThing someThing = new SomeThing();
LambdaInterface<String, String> stringLambdaInterface = someThing::startWith;
System.out.println(stringLambdaInterface.convert("Lambda"));
// 静态方法引用
LambdaInterface<String, String> endWithLambdaInterface = SomeThing::endWith;
endWithLambdaInterface.convert("Lambda");

// 对构造函数的引用
PersonFactory<Person> personFactory = Person::new;
personFactory.create("Jack", "Rose");

class SomeThing {
    public String startWith(String startWith) {
        return String.valueOf(startWith.charAt(0));
    }

    public static String endWith(String endWith) {
        return String.valueOf(endWith.charAt(0));
    }

    public static String subString_0(String subString, int start, int end) {
        return subString.substring(start, end);
    }

    public static String subString_1(String subString) {
        return subString.substring(0, 1);
    }

    public static String subString_2(String subString, int start) {
        return subString.substring(start);
    }
}

class Person {
    private String firstName;
    private String lastName;

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

interface PersonFactory<P extends  Person> {
    P create(String firstName, String lastName);
}

5. Lambda的范围

5.1 访问局部变量

Lambda表达式可以访问外部的的final局部变量;

// 访问外部final局部变量
final int finaNum = 1;
LambdaInterface<Integer, String> lambdaInterfaceFinal = (from -> String.valueOf(finaNum + from));
System.out.println(lambdaInterfaceFinal.convert(2));

// 和匿名对象不一样的地方在于:局部变量不一定要是final
int finalNum = 2;
LambdaInterface<Integer, String> lambdaInterface = (from -> String.valueOf(finalNum + from));
System.out.println(lambdaInterface.convert(3));

// 虽然Lambda访问的外部变量不一定需要定义为final,然鹅在编译的时候变量会被隐式的当做final变量处理
// 从Lambda表达式引用的本地变量必须是最终变量或实际上的最终变量
int finalNoChange = 3;
LambdaInterface<Integer, String> lambdaInterfaceNoChange = (from -> String.valueOf(finalNoChange + from));
System.out.println(lambdaInterfaceNoChange.convert(4));
// finalNoChange = 4;

5.2 访问成员变量和静态变量

在Lambda表达式的内部可以获取对成员变量或者静态变量读写权限;

public void lambdaGetClassVariable() {

    // 访问成员变量和静态变量  
    // 访问静态变量
    LambdaInterface<Integer, String> lambdaInterface1ClassStaticVariable = (from -> String.valueOf(staticNum
            + from));
    System.out.println(lambdaInterface1ClassStaticVariable.convert(7));

    // 访问成员变量
    LambdaInterface<Integer, String> lambdaInterface1ClassNonStaticVariable = (from -> String.valueOf(nonStaticNum
            + from));
    System.out.println(lambdaInterface1ClassNonStaticVariable.convert(8));
}

5.3 访问默认接口方法

默认方法在Lambda表达式中无法访问;

6. 内置函数式接口

JDK 8 API中的函数式接口

6.1 Predicate

Predicate是一个布尔类型的函数,该函数只有一个输入参数。Predicate接口包含了多种默认方法;

public static void main(String args[]) {

    // Predicate是一个布尔类型的函数,该函数只有一个输入参数。Predicate接口包含了多种默认方法,
    // 用于处理复杂的逻辑动词(and, or,negate)
    // 函数式接口方法 - test
    Predicate<String> predicate = s -> s.length() > 0;
    System.out.println(predicate.test("Lambda"));

    // 默认方法 - and
    Predicate<String> predicate1And = s -> s.indexOf("mb") > 0;
    System.out.println(predicate1And.test("lambda"));
    // 连用
    System.out.println(predicate.and(predicate1And).test("JDK-8-Lambda"));

    // 理解:该默认方法的return其实也是一个Lambda表达式,返回一个布尔类型的参数给Predicate对象接收
    // default Predicate<T> and(Predicate<? super T> other) {
        // Objects.requireNonNull(other);
        // 这里的返回其实也是一个Lambda表达式,返回一个布尔类型的参数(or方法也类似)
        // return (t) -> test(t) && other.test(t);
    // }

    // 默认方法 - negate
    Predicate<String> predicate1Negate = s -> s.length() > 0;
    System.out.println(predicate1Negate.negate().test("Predicate.negate"));

    // 默认方法 - or
    Predicate<String> predicate1Or = s -> s.length() > 0;
    System.out.println(predicate1Or.or(predicate1Negate).test("or"));

    // 静态方法 - isEqual
    Predicate<String> predicate1IsEqual = Predicate.isEqual("Lambda");
    predicate1IsEqual.test("Lambda");

    // Predicate - 静态方法实现
    Predicate<Boolean> nonNull = Objects::nonNull;
    System.out.println(nonNull.test(true));
    Predicate<Boolean> isNull = Objects::isNull;
    System.out.println(isNull.test(false));
    Predicate<String> isEmpty = String::isEmpty;
    System.out.println(isEmpty.test("   "));
    Predicate<String> isNotEmpty = isEmpty.negate();
    System.out.println(isNotEmpty.test("Lambda"));
}

Predicate源码查看:
Predicate

6.2 Functions

Function接口接收一个参数,并返回单一的结果,默认方法可以将多个函数串联在一起;

public static void main(String args[]) {

    // Function接口接收一个参数,并返回单一的结果
    Function<String, String> stringFunction = s -> s.substring(1);
    System.out.println(stringFunction.apply("stringFunction"));

    Function<String, Integer> integerFunction = s -> s.length();
    System.out.println(integerFunction.apply("integerFunction"));

    // andThen
    Function<String, Integer> andThenFunction = Integer::valueOf;
    Function<String, String> applyFunctionAndThen = andThenFunction.andThen(String::valueOf);
    System.out.println(applyFunctionAndThen.apply("20200323"));

    // compose 
    Function<Integer, String> composeFunction = String::valueOf;
    Function<String, String> applyFunctionCompose = composeFunction.compose(Integer::valueOf);
    System.out.println(applyFunctionCompose.apply("20200323"));
}

Function源码查看:
Funtion

6.3 Supplier

Supplier接口产生一个给定类型的结果,Supplier没有输入参数;

public static void main(String args[]) {

    // Supplier接口产生一个给定类型的结果,Supplier没有输入参数
    Supplier<String> supplier = String::new;
    System.out.println(supplier.get());
}

6.4 Consumer

Consumer代表在一个输入参数上需要进行的操作;

public static void main(String args[]) {
	
    // Consumer代表在一个输入参数上需要进行的操作
    Consumer<String> consumer = s -> {
        s = s.substring(1);
        System.out.println(s);
    };
    consumer.accept("consumer");
}

/**
 * 源码 - Consumer
 */
 @FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * andThen
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

6.5 Comparator

Comparator接口接收两个参数,实现参数的比较,返回一个int类型的结果值;

public class DefaultFunctionInterfaceComparator {

    public static void main(String[] args) {
		// Person在之前已定义
        Comparator<Person> personComparator = (p_jack, p_rose) -> p_jack.getFirstName()
                .compareTo(p_rose.firstName);
        Person p1 = new Person("John", "Doe");
        Person p2 = new Person("Alice", "Wonderland");
        personComparator.compare(p1, p2);             // > 0
        personComparator.reversed().compare(p1, p2);  // < 0

    }
}

这节到此为止,欲知后事如何,请见下回分解哈!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值