动态代理
代理设计模式的原理
使用一个代理将对象包装起来,然后用该代理对象取代原始对象。
任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
之前为大家讲解过代理机制的操作,属于静态代理,特征是代理类和目标
对象的类都是在编译期间确定下来,不利于程序的扩展。同时,每一个代
理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。最
好可以通过一个代理类完成全部的代理功能。
什么是动态代理
- 动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时
根据需要动态创建目标类的代理对象。
动态代理的优点
动态代理相比静态代理,抽象角色中(按接口)声明的所有方法都被转移到调用处理器
一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。
演示静态代理
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 33 34 35 36 37
|
interface ClothFactory{ void produceCloth(); }
class ProxyCloth implements ClothFactory{ private ClothFactory clothFactory; public ProxyCloth(ClothFactory clothFactory){ this.clothFactory = clothFactory; } @Override public void produceCloth() { System.out.println("代理工厂做一些准备工作..."); clothFactory.produceCloth(); System.out.println("代理工厂做一些收尾工作..."); } }
class NikeClothFactory implements ClothFactory{
@Override public void produceCloth() { System.out.println("nike工厂正在生产一批衣服....."); } }
public class StaticProxy { public static void main(String[] args) { ClothFactory nikeClothFactory = new NikeClothFactory(); ClothFactory proxyCloth = new ProxyCloth(nikeClothFactory); proxyCloth.produceCloth(); }
}
|
演示动态代理
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
interface Human { String getBelief(); void eat(String food); }
class SuperMan implements Human { @Override public String getBelief() { return "I am superMan!"; } @Override public void eat(String food) { System.out.println("我喜欢吃" + food); } }
class ProxyFactory { public static Object getProxyInstance(Object obj) { MyInvocationHandler myInvocationHandler = new MyInvocationHandler(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), myInvocationHandler); } }
class MyInvocationHandler implements InvocationHandler { private Object obj;
public MyInvocationHandler(Object obj) { this.obj = obj; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object returnValue = method.invoke(obj, args); return returnValue; } }
public class ProxyTest { public static void main(String[] args) { SuperMan superMan = new SuperMan(); Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan); System.out.println(proxyInstance.getBelief()); proxyInstance.eat("草莓仙草冻"); } }
|
动态代理与aop
Java8新特性
- 速度更快
- 代码更少(增加了新的语法:Lambada表达式)
- 强大的Stream API
- 便于并行
- 最大化减少空指针异常 : Optional
- Nashorn引擎,允许在JVM上运行JS应用
1、Lambda表达式
什么是Lambada表达式
Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以
传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更
灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了
提升。
lambda表达式的使用
格式:
(o1,o2) -> Integer.compare(o1,o2);
->: Lambda操作符 或 箭头操作符
->左边:Lambda形参列表 (其实就是接口中的抽象方法的形参列表)
->右边: Lambda 体 (其实就是重写的抽象方法的方法体)
Lambda表达式的使用
总结:
-> 左边:lambda形参列表的参数可以省略(类型推断);如果形参列表只有一个参数,可以省略括号
-> 右边:lambda体应该使用一对{}包裹,如果lambda体只有一条执行语句(可能是return语句),则可以省略{}和return
Lambda表达式的本质:
作为函数式接口的实例
演示:
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| public class LambdaTest { @Test public void test1() { Runnable runnable = new Runnable() { @Override public void run() { System.out.println("我爱北京天安门"); } }; runnable.run(); System.out.println("---------------------------");
Runnable r2 = () -> { System.out.println("我爱北京天安门."); }; r2.run(); } @Test public void test2() { Consumer<String> con = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }; con.accept("谎言和誓言的区别是什么?"); System.out.println("-------------------------"); Consumer<String> con2 = (String s) -> { System.out.println(s); }; con2.accept("一个是听的人信了,一个是说的人信了"); } @Test public void test3() { Consumer<String> con1 = (String s) -> { System.out.println(s); }; con1.accept("一个是听的人信了,一个是说的人信了"); System.out.println("----------------"); Consumer<String> con2 = (s) -> { System.out.println(s); }; con2.accept("一个是听的人信了,一个是说的人信了"); } @Test public void test4() { Consumer<String> con2 = s -> { System.out.println(s); }; con2.accept("一个是听的人信了,一个是说的人信了"); } @Test public void test5() { Comparator<Integer> com = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); } }; System.out.println(com.compare(12, 21)); System.out.println("--------------------------"); Comparator<Integer> com2 = (o1, o2) -> { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); }; System.out.println(com2.compare(12,6)); } @Test public void test6(){ Comparator<Integer> com = (o1, o2) -> o1.compareTo(o2); System.out.println(com.compare(12,21)); } }
|
2、函数式(Functional)接口
什么是函数式接口
只包含一个抽象方法的接口,就是函数式接口
我们可以在一个接口上使用 @Functionallnterface
注解,这样做可以检
查它是否是一个函数式接口。同时 javadoc
也会包含一条声明,说明这个
接口是一个函数式接口。
在java.util.function
包下定义了Java 8的丰富的函数式接口
以前用匿名实现类表示的现在都可以用Lambda表达式来写。
java内置四大核心函数式接口
其他接口
使用案例
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
public class CentralFunctionalInterfaces { @Test public void test1(){ happyTime(500.0, new Consumer<Double>() { @Override public void accept(Double aDouble) { System.out.println("在天守阁消费"+aDouble); } }); System.out.println("========================"); happyTime(400.0,money -> System.out.println("在望舒客栈消费"+money)); }
public void happyTime(Double money, Consumer<Double> con){ con.accept(money); }
@Test public void test2(){ List<String> list = Arrays.asList("北京","南京","东京","天津","西京"); List<String> filterString= filterString(list, new Predicate<String>() { @Override public boolean test(String s) { return s.contains("京"); } }); System.out.println(filterString); System.out.println("===================="); List<String> list1 = filterString(list, s -> s.contains("京")); System.out.println(list1);
} public List<String> filterString(List<String> list, Predicate<String> pre){ ArrayList<String> filterList = new ArrayList<>(); for (String s: list){ if (pre.test(s)) filterList.add(s); } return filterList; } }
|
3、方法引用与构造器引用
方法引用基本介绍
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
方法引用可以看做是Lambda表达式深层次的表达。
换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例
,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖
要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的
方法的参数列表和返回值类型保持一致!(仅使用于 对象::实例方法名 和 类::静态方法名)
格式:使用操作符”:”将类(或对象)与方法名分隔开来。
如下三种主要使用情况:
》对象 : : 实例方法名
》类 : : 静态方法名
》类 : : 实例方法名
方法引用的使用
1.使用情境:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
2.方法引用,本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例。所以
方法引用,也是函数式接口的实例。
使用格式: 类(或对象) :: 方法名
具体分为如下的三种情况:
- 情况1 对象 :: 非静态方法
- 情况2 类 :: 静态方法
- 情况3 类 :: 非静态方法
方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的
形参列表和返回值类型相同!(针对于情况1和情况2)
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
public class MethodRefTest {
@Test public void test1() { Consumer<String> con = s -> System.out.println(s); con.accept("北京"); System.out.println("********************"); PrintStream ps = System.out; Consumer<String> con2 = ps::println; con.accept("上海"); }
@Test public void test2() {
Employee emp = new Employee(1002, "Tom", 22, 12104); Supplier<String> supplier = () -> emp.getName(); System.out.println(supplier.get()); System.out.println("-----------分割线------------"); Supplier<String> supplier2 = emp::getName; System.out.println(supplier2.get());
}
@Test public void test3() { Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2); System.out.println(com1.compare(12, 21)); System.out.println("-----------分割线------------"); Comparator<Integer> com2 = Integer::compare; System.out.println(com2.compare(12, 1));
}
@Test public void test4() { Function<Double, Long> fun = new Function<Double, Long>() { @Override public Long apply(Double aDouble) { return Math.round(aDouble); } }; Function<Double, Long> fun1 = d -> Math.round(d); System.out.println(fun1.apply(13.5)); System.out.println("-----------分割线------------"); Function<Double, Long> fun2 = Math::round; System.out.println(fun2.apply(11.2)); }
@Test public void test5() { Comparator<String> com1 = (s1, s2) -> s1.compareTo(s2); System.out.println(com1.compare("abc", "abd")); System.out.println("-----------分割线------------"); Comparator<String> com2 = String::compareTo; System.out.println(com2.compare("c", "a")); }
@Test public void test6() { BiPredicate<String, String> b1 = (t1, t2) -> t1.equals(t2); System.out.println(b1.test("abc", "abc")); System.out.println("-----------分割线------------"); BiPredicate<String, String> b2 = String::equals; System.out.println(b2.test("abd","acf"));
}
@Test public void test7() { Function<Employee,String> f1 = n->n.getName(); System.out.println(f1.apply(new Employee(03,"jerry",10,1231321))); System.out.println("-----------分割线------------"); Function<Employee,String> f2 = Employee::getName; System.out.println(f2.apply(new Employee(06,"tim",21,132131))); }
}
|
构造器引用
一、构造器引用
二、数组引用
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class ConstructorRefTest { @Test public void test1(){ Supplier<Employee> supplier1 = () -> new Employee(); System.out.println(supplier1.get()); System.out.println("---------------------"); Supplier<Employee> supplier2 = Employee::new; System.out.println(supplier2.get()); }
@Test public void test2(){ Function<Integer,Employee> function = new Function<Integer, Employee>() { @Override public Employee apply(Integer integer) { return new Employee(integer); } }; Function<Integer,Employee> function1 = id -> new Employee(id); Function<Integer,Employee> function2 = Employee::new; System.out.println(function2.apply(1003)); }
@Test public void test3(){ BiFunction<Integer,String,Employee> biFunction = Employee::new; System.out.println( biFunction.apply(3306,"Steve")); }
@Test public void test4(){ Function<Integer,String[]> function = length -> new String[length]; String[] arr1 = function.apply(5); System.out.println(Arrays.toString(arr1)); System.out.println("=========================="); Function<Integer,String[]> fun2 = String[]::new; System.out.println(Arrays.toString(fun2.apply(8))); } }
|
4、强大的Stream API
了解Stream
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对 集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数 据库查询。也可以使用 Stream API 来并行执行操作。简而言之, Stream API 提供了一种高效且易于使用的处理数据的方式。
什么是Stream
流(Stream) 到底是什么呢? 是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”
注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream操作的三个步骤
⚫创建 Stream 一个数据源(如:集合、数组),获取一个流
⚫ 中间操作 一个中间操作链,对数据源的数据进行处理
多个中间操作可以连接起来形成一个流水线,除非流水 线上触发终止操作,否则中间操作不会执行任何的处理! 而在终止操作时一次性全部处理,称为“惰性求值”
⚫ 终止操作(终端操作) 一个终止操作,执行中间操作链,并产生结果
创建Stream数据源
方式一:通过集合的stream()方法创建
方式二:通过数组 Arrays.stream(object[]) 创建
方式三:通过Stream的 Of()创建
方式四:通过Stream 的 iterate() 和 generate()创建无限流
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public class StreamAPITest {
@Test public void test1(){ List<Employee> employees = EmployeeData.getEmployees();
Stream<Employee> stream = employees.stream();
Stream<Employee> parallelStream = employees.parallelStream(); }
@Test public void test2(){ int[] arr = new int[]{10,2,5,6,78}; IntStream intStream = Arrays.stream(arr); Employee employee = new Employee(1001,"Tom"); Employee employee2 = new Employee(1002,"Jerry"); Employee[] employees = new Employee[]{employee,employee2}; Stream<Employee> stream = Arrays.stream(employees);
} @Test public void test3(){
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
}
@Test public void test4(){
Stream.generate(Math::random).limit(5).forEach(System.out::println); } }
|
中间操作
筛选与切片
filter(Predicate p) 接受lambda,从流中排除某些元素。
limit(long maxSize) 截断流,使其元素不超过给定数量
skip(long n) 跳过某元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流。与limit(n)互补
distinct()筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Test public void test1(){ List<Employee> employees = EmployeeData.getEmployees(); Stream<Employee> stream = employees.stream();
stream.filter( employee -> employee.getSalary()>7000).forEach(System.out::println); System.out.println("================"); employees.stream().limit(3).forEach(System.out::println);
System.out.println("================="); employees.stream().skip(3).forEach(System.out::println); System.out.println("======================"); employees.add(new Employee(1200,"刘强东",41,23131)); employees.add(new Employee(1200,"刘强东",45,23131)); employees.add(new Employee(1200,"刘强东",41,23131)); employees.add(new Employee(1200,"刘强东",41,23131)); employees.add(new Employee(1200,"刘强东",41,23131)); employees.stream().distinct().forEach(System.out::println); }
|
映射
map(Function f)
接收一个函数作为参数,该函数会被应用到每个元 素上,
并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f)
接收一个函数作为参数,该函数会被应用到每个元 素上,
产生一个新的 DoubleStream
。
mapToInt(ToIntFunction f)
接收一个函数作为参数,该函数会被应用到每个元 素上,
产生一个新的 IntStream
。
mapToLong(ToLongFunction f)
接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream
。
flatMap(Function f)
接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
@Test public void test2(){ List<String> list = Arrays.asList("aa", "bb", "cc", "dd"); Stream<String> stream = list.stream(); stream.map(str->str.toUpperCase()).forEach(System.out::println);
List<Employee> employees = EmployeeData.getEmployees(); Stream<Employee> employeeStream = employees.stream(); Stream<String> stringStream = employeeStream.map(Employee::getName); stringStream.filter(name->name.length()>3).forEach(System.out::println); System.out.println(); Stream<Stream<Character>> streamStream = list.stream().map(StreamTest2::StringToStream);
streamStream.forEach(characterStream -> {characterStream.forEach(System.out::println);}); System.out.println("分割线---------");
Stream<Character> characterStream = list.stream().flatMap(StreamTest2::StringToStream); characterStream.forEach(System.out::println);
} public static Stream<Character> StringToStream(String str){ ArrayList<Character> list = new ArrayList<>(); for (Character c : str.toCharArray()){ list.add(c); } return list.stream(); }
|
排序
sorted()
产生一个新流,其中按自然顺序排序
sorted(Comparator comp)
产生一个新流,其中按比较器顺序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@Test public void test3(){ List<Integer> list = Arrays.asList(11, 66, 3, -9, 6, 55, 21, 33); list.stream().sorted().forEach(System.out::println);
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().sorted((e1,e2)-> { int compare = Integer.compare(e1.getAge(), e2.getAge()); if (compare !=0) return compare; else return (int) (e1.getSalary()-e2.getSalary()); } ).forEach(System.out::println); }
|
Stream的终止操作
终端操作会从流的流水线生成结果。其结果可以是任何不是流的 值,
例如:List、Integer,甚至是 void
匹配与查找
allMatch(Predicate p)
检查是否匹配所有元素
anyMatch(Predicate p)
检查是否至少匹配一个元素
noneMatch(Predicate p)
检查是否没有匹配所有元素
findFirst()
返回第一个元素
findAny()
返回当前流中的任意元素
count()
返回流中元素总数
max(Comparator c)
返回流中最大值
min(Comparator c)
返回流中最小值
forEach(Consumer c)
内部迭代(使用 Collection 接口需要用户去做迭 代,称为外部迭代。
相反,Stream API 使用内部 迭代——它帮你把迭代做了)
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 33 34 35 36 37 38
| @Test public void test1() { List<Employee> employees = EmployeeData.getEmployees(); boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18); System.out.println(allMatch);
boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 10000); System.out.println(anyMatch);
boolean noneMatch = employees.stream().noneMatch(employee -> employee.getName().startsWith("雷")); System.out.println(noneMatch);
Optional<Employee> first = employees.stream().findFirst(); System.out.println(first);
Optional<Employee> any = employees.parallelStream().findAny(); System.out.println(any);
long count = employees.stream().filter(employee -> employee.getSalary() > 3000).count(); System.out.println(count);
Stream<Double> salaryStream = employees.stream().map(Employee::getSalary); Optional<Double> maxSalary = salaryStream.max(Double::compare); System.out.println(maxSalary);
Optional<Employee> employee = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())); System.out.println(employee);
System.out.println("分割线================"); employees.stream().forEach(System.out::println); }
|
归约
reduce(T iden, BinaryOperator b)
可以将流中元素反复结合起来,得到一个值。 返回 T
reduce(BinaryOperator b)
可以将流中元素反复结合起来,得到一个值。 返回 Optional
备注:map 和 reduce 的连接通常称为map-reduce 模式,因 Google 用它 来进行网络搜索而出名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Test public void test2() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Integer integer = list.stream().reduce(0, Integer::sum); System.out.println(integer);
List<Employee> employees = EmployeeData.getEmployees(); Optional<Double> sumMoney = employees.stream().map(Employee::getSalary).reduce(
Double::sum); System.out.println(sumMoney); }
|
收集
collect(Collector c)
将流转换为其他形式。接收一个 Collector接口的 实现,用于给Stream中元素做汇总的方法
1 2 3 4 5 6 7 8 9 10
| @Test public void test3(){
List<Employee> employeeList = EmployeeData.getEmployees().stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList()); employeeList.forEach(System.out::println); System.out.println(); Set<Employee> employeeSet = EmployeeData.getEmployees().stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet()); employeeSet.forEach(System.out::println); }
|
5、Optional类
Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在, 原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且 可以避免空指针异常。
常用方法:
Optional.of(T t)
: 创建一个 Optional 实例
Optional.empty()
: 创建一个空的 Optional 实例
Optional.ofNullable(T t)
若 t 不为 null,创建 Optional 实例,否则创建空实例
isPresent()
: 判断是否包含值
orElse(T t)
: 如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s)
:如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f)
: 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
flatMap(Function mapper)
:与 map 类似,要求返回值必须是Optional
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
public class OptionalTest {
@Test public void test1(){ Girl girl = new Girl();
Optional<Girl> optionalGirl = Optional.of(girl); } @Test public void test2(){ Girl girl = new Girl();
Optional<Girl> optionalGirl = Optional.ofNullable(girl); System.out.println(optionalGirl); Girl girl1 = optionalGirl.orElse(new Girl("赵丽颖")); System.out.println(girl1);
}
public String getGirlName(Boy boy){ return boy.getGirl().getName(); }
@Test public void test3(){ Boy boy = new Boy(); boy = null; String girlName = getGirlName(boy); System.out.println(girlName);
} public String getGirlName1(Boy boy){ if(boy != null){ Girl girl = boy.getGirl(); if(girl != null){ return girl.getName(); } }
return null;
}
@Test public void test4(){ Boy boy = new Boy(); boy = null; String girlName = getGirlName1(boy); System.out.println(girlName);
}
public String getGirlName2(Boy boy){
Optional<Boy> boyOptional = Optional.ofNullable(boy); Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪丽热巴")));
Girl girl = boy1.getGirl();
Optional<Girl> girlOptional = Optional.ofNullable(girl); Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
return girl1.getName(); }
@Test public void test5(){ Boy boy = null; boy = new Boy(); boy = new Boy(new Girl("ikura")); String girlName = getGirlName2(boy); System.out.println(girlName); } }
|