《Java编程入门官方教程》第十四章练习答案

【练习14-1(LambdaArgumentDemo.java)】作为实参传递lambda表达式

lambda表达式可用在任何提供了目标类型的上下文中。前面示例中使用的上下文是赋值和初始化。另一种情况就是作为实参传递lambda表达式。事实上,这是lambda表达式的一种常见且强大的用途,因为可将可执行代码作为实参传递给方法,这极大地增强了Java的表达力。

为了演示过程,本练习中创建了三个字符串函数,它们执行以下操作:颠倒字符串、颠倒字符串中字母的大小写、用连字符替代空格。这些函数作为函数式接口StringFunc的lambda表达式实现。之和它们作为第一个实参传递给changeStr()方法。changeStr()方法将字符串函数应用于第二个实参传递给changeStr()的字符串并返回结果。因此,changeStr()方法可用于各种不同的字符串函数。

java 复制代码
package javaone.a.beginners.guide.chapterfourteen;

// Use a lambda expression as an argument to a method.
interface StringFunc{
    String func(String str);
}

public class ChapterFourteenProgramOne {

    // This method has a functional interface as the type of its
    // first parameter. Thus, it can be passed a reference to any
    // instance of that interface, including an instance created
    // by a lambda expression. The second parameter specifies the
    // string to operate on.
    static String changeStr(StringFunc sf, String s){
        return sf.func(s);
    }

    public static void main(String[] args) {
        String inStr = "Lambda Expressions Expand Java";
        String outStr;

        System.out.println("Here is input string: " + inStr);

        // Define a lambda expression that reverses the contents
        // of a string and assign it to a StringFunc reference varible.
        StringFunc reverse = (str) -> {
            String result = "";
            for (int i = str.length() - 1; i >= 0 ; i--) {
                result += str.charAt(i);
            }
            return result;
        };

        // Pass reverse to the first argument to changeStr().
        // Pass the input string as the second argument.
        outStr = changeStr(reverse, inStr);
        System.out.println("The string reversed: " + outStr);

        // This lambda expression replace spaces with hyphens.
        // It is embedded directly in the call to changeStr().
        outStr = changeStr((str)->str.replace(' ','-'), inStr);
        System.out.println("The string with spaces replaced: " + outStr);

        // This block lambda invert the case of the characters in the
        // string. It is also embedded directly in the call to changeStr().
        outStr = changeStr((str) -> {
            String result = "";
            char ch;
            for (int i = 0; i < str.length(); i++) {
                ch = str.charAt(i);
                if(Character.isUpperCase(ch)){
                    result += Character.toLowerCase(ch);
                }else{
                    result += Character.toUpperCase(ch);
                }
            }
            return result;
        }, inStr);
        System.out.println("The string in reversed case: " + outStr);
    }

}

14.9 自测题

  1. 什么是lambda运算符?

答案:lambda运算符是->。

  1. 什么是函数式接口?

答案: 函数式接口是指仅指定一个抽象方法的接口。

  1. 函数式接口和lambda表达式是如何关联的?

答案:lambda表达式提供函数式接口定义的抽象方法的实现。函数式接口定义目标类型。

  1. lambda表达式的两种常见类型是什么?

答案:lambda表达式的两种类型是表达式lambda和块lambda。表达式lambda指定单一的表达式,其值由lambda返回。而块lambda包含一个代码块,其值由return语句指定。

  1. 给出一个lambda表达式,如果某个数字在10和20之间(包括10和20),该表达式返回的结果为true。

答案:(n) -> (9 < n && n < 21);

  1. 创建一个函数式接口,使之支持习题5中所创建的lambda表达式。调用接口MyTest及其抽象方法testing()。

答案:

interface MyTest{

boolean testing(int n);

}

  1. 创建一个计算某个整数值的阶乘的块lambda。演示其用法,对于该函数式接口使用本章介绍的NumericFunc。
java 复制代码
package javaone.a.beginners.guide.chapterfourteen;

interface NumericFuncOne{
    int func(int n);
}
public class ChapterFourteenExerciseSeven {

    public static void main(String[] args) {
        // This block lambda computes the factorial of an int value.
        NumericFuncOne factorial = (n) -> {
            int result = 1;
            for (int i = 1; i <= n; i++) {
                result *= i;
            }
            return result;
        };
        System.out.println("The factorial of 3 is " + factorial.func(3));
        System.out.println("The factorial of 5 is " + factorial.func(5));
        System.out.println("The factorial of 9 is " + factorial.func(9));
    }

}
  1. 创建一个名为MyFunc<T>的泛型函数式接口。调用它的抽象方法func()。让func()返回一个T类型的引用,并让它接受T类型的形参(因此,MyFunc将是本章中所介绍的NumericFunc的泛型版本)。重写习题7的答案,演示其用法,这样就可以使用MyFunc<T>而不使用NumericFunc。
java 复制代码
package javaone.a.beginners.guide.chapterfourteen;

interface MyFuncTwo<T>{
    T func(T n);
}

public class ChapterFourteenExerciseEight {
    public static void main(String[] args) {
        // This block lambda computes the factorial of an int value.
        MyFuncTwo<Integer> factorial = (n) -> {
            int result = 1;
            for (int i = 1; i <= n; i++) {
                result *= i;
            }
            return result;
        };
        System.out.println("The factorial of 3 is " + factorial.func(3));
        System.out.println("The factorial of 5 is " + factorial.func(5));
        System.out.println("The factorial of 9 is " + factorial.func(9));
    }
}
  1. 使用练习14-1所示的程序创建一个lambda表达式,删除字符串中的所有的空格并返回结果。通过将其传递给changeStr()演示该方法。
java 复制代码
package javaone.a.beginners.guide.chapterfourteen;

interface StringFuncOne{
    String func(String str);
}
public class ChapterFourteenExerciseNine {

    static String changeStr(StringFuncOne sf, String s){
        return sf.func(s);
    }

    public static void main(String[] args) {
        String inStr = "Lambda Expressions Expand Java";
        String outStr;

        System.out.println("Here is input string: " + inStr);
        outStr = changeStr((str)->str.replace(" ",""), inStr);
        System.out.println("The string with spaces replaced: " + outStr);
    }

}
  1. lambda表达式可使用局部变量吗?如果可以,必须满足什么约束条件?

答案:可以,但变量必须是有效的final。

  1. 如果lambda表达式抛出了经检查的异常,函数式接口中的抽象方法必须有一条包含该异常的throws子句。这种说法正确吗?

答案: 正确。

  1. 什么是方法引用?

答案:方法引用是指引用某个方法但不执行它的一种方法。

  1. 当被计算时,方法引用会创建一个由其上下文提供的_________的实例。

答案:函数式接口。

  1. 假定名为MyClass的类包含静态的抽象方法myStaticMethod(),请说明如何指定对该抽象方法的方法引用。

答案:myClass::myStaticMethod。

  1. 假定名为MyClass的类包含实例方法myInstMethod(),并假定MyClass的一个对象称为mcObj,请说明如何创建对mcObj对象的myInstMethod()方法的引用。

答案:mcObj::myInstMethod。

  1. 在MethodRefDemoTwo程序中,将新方法hasCommonFactor()添加到MyIntNum中。如果方法hasCommonFactor()的int实参和存储在调用对象MyIntNum中的值至少有一个公有因子,该方法就返回true。例如,9和12就有公有因子3,9和16就没有公有因子。请通过方法引用演示hasCommonFactor()的用法。
java 复制代码
package javaone.a.beginners.guide.chapterfourteen;

interface IntPredicateTwo{
    boolean test(int n);
}

class MyIntNumTwo{
    private int v;
    MyIntNumTwo(int x){
        v = x;
    }
    int getNum(){
        return v;
    }
    // Return true if n is a Factor of v.
    boolean isFactor(int n){
        return (v % n) == 0;
    }
    boolean hasCommonFactor(int n){
        for (int i = 2; i < v/i; i++) {
            if(((v % i) == 0) && ((n % i) == 0)){
                return true;
            }
        }
        return false;
    }
}
public class ChapterFourteenExerciseSixteen {

    public static void main(String[] args) {
        boolean result;
        MyIntNumTwo myIntNum = new MyIntNumTwo(12);
        IntPredicateTwo ip = myIntNum::hasCommonFactor;
        result = ip.test(9);
        if(result){
            System.out.println("Common factor found.");
        }
    }

}
  1. 如何指定构造函数引用?

答案:通过指定类名后紧随::,之后紧跟new可以创建构造函数引用。例如,MyClass::new。

  1. Java定义的几个预定义函数式接口都位于哪个包中?

答案:java.util.function。

相关推荐
空中海1 分钟前
02 状态、Hooks、副作用与数据流
开发语言·javascript·ecmascript
Aurorar0rua3 分钟前
CS50 x 2024 Notes C - 09
c语言·开发语言·学习方法
014-code4 分钟前
布隆过滤器:判断“可能存在“和“一定不存在“
java·redis
兔小盈5 分钟前
多线程篇-(二)线程创建、中断与终止
java·开发语言·多线程
jnrjian10 分钟前
Library Cache Load Lock library cache pins are replaced by mutexes
java·后端·spring
hoiii18715 分钟前
基于MATLAB实现内点法解决凸优化问题
开发语言·matlab
abcnull19 分钟前
传统的JavaWeb项目Demo快速学习!
java·servlet·elementui·vue·javaweb
risc12345625 分钟前
【lucene】PostingsEnum跟TermsEnum 的区别是啥?
java·lucene
小江的记录本42 分钟前
【Kafka核心】Kafka高性能的四大核心支柱:零拷贝、批量发送、页缓存、压缩
java·数据库·分布式·后端·缓存·kafka·rabbitmq