JDK8与JDK9新特性学习

一、环境和软件准备
环境:window或者linux环境
下载软件:
1.JDK版本:JDK9下载路径
2.安装eclipse,当然可以使用其他编辑器
二、Lambda表达式预演
1.面向对象的Runnable接口写法

public class DemoRunnable {
	public static void main(String[] args) {
		Runnable task = new Runnable() {
			@Override
			public void run() {
				System.out.println("多线程执行了!");
			}
		};
		new Thread(task).start();
	}
}

2.使用函数式编程思想
异同点:

  • [ 面向对象强调“一切皆对象”,如果想要做事情,必须找到对象来做]
  • [函数式编程思想强调“做什么,而不是怎么做” ]
    例子:
public class DemoRunnable {
	public static void main(String[] args) {
		new Thread(()->System.out.println("多线程执行了!")).start();
	}
}

分析:这样的代码是不是更加简洁。
Runnable接口当中的run方法语义分析:

  1. 参数列表为空,不需要任何条件就可以执行该方法
  2. 没有返回值:方法不产生任何数据结果
  3. 方法体大括号:这个才是关键的方法内容所在

Lambda表达式:

  1. 前面一个小括号:不需要任何参数条件,即可直接执行
  2. 箭头指向后面要做的事情
  3. 箭头后面就好比是方法体大括号,代表具体要做的内容

三、Lambda表达式的标准格式
1.Lambda表达式必须有上下文推导:

  • a.根据调用方法的参数推导得知Lambda对应的接口
  • b.根据局部变量的赋值来推导得知Lambda对应的接口

2.三要素:一些参数、一个参数、一些代码
3.比如:(参数类型 参数名称) -> {一些代码}

  • a. 如果参数有多个,那么使用逗号分隔,如果没有参数,则留空。
  • b.箭头是固定写法
  • c.大括号其实就相当于是方法体

例子
1.新建一个接口类

package com.lambda.demo;
/**
 *  使用Lambda表达式的必要条件:
 *  1.必须有一个接口
 *  2.接口当中必须保证有且仅有一个抽象方法
 * @FunctionalInterface:注释用来检测是不是函数式接口
 * 1.如果是函数式接口,那么编译通过
 * 2.如果不是,那么就编译失败
 * @author Administrator
 *
 */
@FunctionalInterface
public interface Cook {
	//唯一的抽象方法
	void makeFood();
}

2.之前写法要写一个接口实现类

package com.lambda.demo;

public class CookImpl implements Cook{

	@Override
	public void makeFood() {
		System.out.println("菜煮好,吃饭啦!");
	}

}

3.执行类

package com.lambda.demo;


public class DemoCook {
	private static void method(Cook cook) {
		cook.makeFood();
	}
	
	public static void main(String[] args) {
		//调用实现类
		method(new CookImpl());
		//可以使用匿名内部类
		method(new Cook() {
			@Override
			public void makeFood() {
				System.out.println("菜煮好,吃饭啦!");
			}
		});
		
		/**使用标准的lambda表达:根据上下文(method方法)推导,因为Cook只用一个抽象方法,
		* 所以能推 导出调用的方法一定是makeFood()方法,该方法没有参数,那么使用(),括号是空的,
		* {}填写实现的内容
		**/
		method(() -> {System.out.println("菜煮好,吃饭啦!");});
	}
}

四、Lambda表达式的参数和返回值
1.新建一个Person类

package com.lambda.demo;

public class Person {
	private String name;
	private int age ;
	
	public Person() {
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}

2.执行类

package com.lambda.demo;

import java.util.Arrays;
import java.util.Comparator;

public class DemoPersonSort {
	public static void main(String[] args) {
		Person[] arry = {
			new Person("古天",36),new Person("张家",35),
			new Person("周星",56),new Person("任达",45)
		};
		
		System.out.println(Arrays.toString(arry));
		Arrays.sort(arry,new Comparator<Person>() {

			@Override
			public int compare(Person o1, Person o2) {
				//o1大就是正数,o2大就是负数,一样大就是0
				return o1.getAge()-o2.getAge();
			}
			
		});
		
		System.out.println(Arrays.toString(arry));
		//使用Lambda表达式 ,有返回值使用return
		Arrays.sort(arry,(Person p1,Person p2) -> {return p2.getAge()-p1.getAge();});
		System.out.println(Arrays.toString(arry));
	}
}

五、Lambda表达式的省略规则:
1、参数类型可以省略,但是只能省略所有参数的类型,或者干脆都不省略,不能只写个别参数类型
2、如果参数有且仅有一个,那么小括号可以省略。
3、如果大括号之内的语句有且仅有一个,那么无论有没有返回值,return、大括号、分号都可以省略

package com.lambda.demo1;

public interface Calculator {
	public int add(int a,int b);
}

package com.lambda.demo1;
//1.使用Lambda表达式的必要条件:
//    必须有一个接口; 接口当中必须保证有且仅有一个抽象方法
public class DemoCalculatorLambda {
	public static void main(String[] args) {
		method((int a,int b) -> {return a+b;});
	}
	
	private static void method(Calculator calc){
		int add = calc.add(100, 200);
		System.out.println(add);
	}
}
public class DemoCalculatorLambdaFormat {
	public static void main(String[] args) { 
//		method((a,b) -> {return a+b;});
		method((e,y) -> e+y);
	}
	
	private static void method(Calculator calc){
		int add = calc.add(100, 200);
		System.out.println(add);
	}
}

六、接口的组成更新
1.接口组成部分:

  • a.常量
  • b.抽象方法
  • c.默认方法(Java 8)
  • d.静态方法(Java 8)
  • e.私有方法(Java 9)

默认方法例子

package com.jiahui.interfaceDefaultDemo;
/**
 * 接口的实现类当中必须对接口所有抽象方法都要覆盖重写,除非实现类是一个抽象类。
 * 接口升级:本来是2个抽象方法,现在需要变成3个抽象方法,但是别的实现类中已经有再使用抽象方法了。
 * java7以前的版本解决方案是重新定义一个抽象类继承原本的抽象类,然后再写新增的抽象方法;设计模式当中的对扩展开放对修改关闭
 * java8开始,接口当中允许定义defaul默认方法。
 * 常量的修饰符:public static final(都可以省略)
 * 默认方法的修饰符:public default(public可以省略,default不能省略)
 * 
 * 默认方法可以有方法体实现;默认方法也可以被覆盖重写
 * @author 
 *
 */
public interface MyInterface {
	
	void method1();
	void method2();
	
	//新定义一个方法
	public default void methoNew() {
		System.out.println("接口的默认方法执行!");
	}
}

接口实现类

package com.jiahui.interfaceDefaultDemo;
public class MyInterfaceImplA implements MyInterface{
	@Override
	public void method1() {	
	}
	@Override
	public void method2() {
   }
   //默认方法也可以被实现,也可以不用实现
	@Override
	public void methoNew() {
		System.out.println("A接口的默认方法执行");
	}
}

package com.jiahui.interfaceDefaultDemo;
public class MyInterfaceImplB implements MyInterface{
	@Override
	public void method1() {	
	}
	@Override
	public void method2() {	
	}
}

执行

package com.jiahui.interfaceDefaultDemo;
public class MyInterfaceMain {
	public static void main(String[] args) {
		MyInterface objA = new MyInterfaceImplA();
		objA.methoNew();
		MyInterface objB = new MyInterfaceImplB();
		objB.methoNew();
	}
}

静态方法例子

package com.jiahui.interfaceStaticDemo;
/**
 * 从java8开始,接口当中允许定义静态方法:
 * 静态方法的修饰符:public static (public可以省略,static不可以省略)
 * @author jiahui
 *
 */
public interface Animal {

	void eat();
	public static Animal getAnimal() {
		return new Cat();
	}
}

接口实现类

package com.jiahui.interfaceStaticDemo;
public class Cat implements Animal{
	@Override
	public void eat() {
		System.out.println("猫吃鱼");
	}
}

package com.jiahui.interfaceStaticDemo;
public class Dog implements Animal{
	@Override
	public void eat() {
		System.out.println("狗吃骨头");
	}
}

执行

package com.jiahui.interfaceStaticDemo;
/**
 * 左边是接口类型,说明我并不关心到底是猫还是狗,只要是动物
 * @author jiahui
 *
 */
public class AnimalMain {
	public static void main(String[] args) {
		/*Animal animal = new Dog();
		animal.eat();*/
		//新的调用方式
		Animal animal = Animal.getAnimal();
		animal.eat();
	}
}

私有方法例子

package com.jiahui.interfacePrivateDemo;
/**
 * 从java9开始支持在接口当中定义私有方法:
 * 私有方法可以是:1.成员私有方法;2.静态私有方法
 * @author Administrator
 */
public interface MyInterfacePrivate {
	default void method() {
		System.out.println("这个是method方法");
		makeFood();
	}
	default void method2() {
		System.out.println("这个是method2方法");
		makeFood();
	}
   private void makeFood() {
		System.out.println("点火");
		System.out.println("上锅");
		System.out.println("放油");
		System.out.println("炒菜");
		System.out.println("装盘");
	}
   static void methodA() {
	   System.out.println("静态成员方法1");
	   makeCookie();
   }
   static void methodS() { 
	   System.out.println("静态成员方法2");
	   makeCookie();
   }  
   private static void makeCookie() {
	   System.out.println("洗米");
	   System.out.println("开电");
	   System.out.println("洗碗");
	   System.out.println("吃饭");
   }
}

执行

package com.jiahui.interfacePrivateDemo;

public class InterfaceMain {
	public static void main(String[] args) {
		MyInterfacePrivate.methodA();
		MyInterfacePrivate.methodS();
	}
}

七、通过方法引用改进代码
1.从java8开始 ,引入一个全新的运算符,方法引用符(两个冒号“::”)所在的表达是一个方法引用,方法引用和Lambda本质是完全一样的,目的就是为了简化Lambda表达式的写法
例子

package com.jiahui.interfaceRef;
/**
 * @author Administrator
 */
@FunctionalInterface
public interface Printer {
	void print(String str);
}

执行

package com.jiahui.interfaceRef;
public class Demo01Printer {
	public static void main(String[] args) {
		method((String str)->{System.out.println(str);});	
		method(str -> System.out.println(str));
		//使用方法引用;和lambda本质是一样的
		method(System.out::println);
	}	
	private static void method(Printer printer) {
		printer.print("hello me");
	}
}

成员方法引用例子

package com.jiahui.interfaceRef.helper;
public class Assistant {
	void work() {
		System.out.println("努力工作!!!");
	}
}
package com.jiahui.interfaceRef.helper;
@FunctionalInterface
public interface WorkHelper {
	void help();
}

执行

package com.jiahui.interfaceRef.helper;

public class DemoMethodRef {
	public static void main(String[] args) {
		Assistant assistant = new Assistant();
		assistant.work();
		
		method(()->System.out.println("努力工作!!!"));
		//成员方法引用
		method(assistant::work);
	}
	
	private static void method(WorkHelper helper) {
		helper.help();
	}
}

静态方法引用例子

package com.jiahui.interfaceRef.staticDemo;
@FunctionalInterface
public interface Calculator {
	int getAbs(int num);
}

执行

package com.jiahui.interfaceRef.staticDemo;
public class DemoMethodStaticRef {
	public static void main(String[] args) {
		method((t)->{return Math.abs(t);});
		//如果lambda表达式需要的事情,正好就是一个类当中的静态方法内容。
		//那么可以使用静态方法引用:(类名::静态方法名)
		method(Math::abs);
	}
	private static void method(Calculator calculator) {
		int abs = calculator.getAbs(-200);
		System.out.println("结果是:"+abs);
	}
}

父类方法引用例子

package com.jiahui.interfaceRef.superDemo;
public class Human {
	public void sayHello() {
		System.out.println("Hello!");
	}
}

执行


package com.jiahui.interfaceRef.superDemo;

public class Man extends Human{
	@Override
	public void sayHello() {
		method(()->System.out.println("Hello!"));
		method(()->super.sayHello());
		//如果lambda表达式要做的事情,正好就是父类当中的方法内容,
		 //那么可以通过super关键字来引用父类当中的方法,格式:(super::父类方法名称)
		method(super::sayHello);
	}
	private void method(Greetable greetable) {
		greetable.greet();
		System.out.println("I am a man");
	}
}

本类方法引用例子

package com.jiahui.interfaceRef.thisDemo;
@FunctionalInterface
public interface Richable {
	void buyHouse();
}

执行

package com.jiahui.interfaceRef.thisDemo;
/**
 * @author Administrator
 */
public class Husband {
	public void marry(Richable richable) {
		richable.buyHouse();
	}
	public void beHappy() {
		marry(()->System.out.println("买一个大房子!"));
		marry(()->this.buy());
		/**如果lambda表达式要做的事情,正好就是本类当中的方法内容,
		 * 那么可以使用方法引用,借助this关键字,格式如(this::本类方法名称)**/
		marry(this::buy);
	}
	public void buy() {
		System.out.println("买一个大房子!");
	}
}

数组构造器引用例子

package com.jiahui.interfaceRef.construct;
@FunctionalInterface
public interface ArrayBuilder {
	int[] build(int length);
}

执行

package com.jiahui.interfaceRef.construct;

public class ArrayBuilderDemoArray {
	private static void method(ArrayBuilder arrayBuilder) {
		int[] build = arrayBuilder.build(10);
		System.out.println("数组长度为:"+build.length);
	}	
	public static void main(String[] args) {
		method(t->new int[t]);
		/**数组构造器引用,格式(原始类型[]::new)**/
		method(int[]::new);
	}
}

类构造器引用例子

package com.jiahui.interfaceRef.construct;
public class Person {
	private String name;
	public Person() {
	}
	public Person(String name) {
		super();
		this.name = name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
package com.jiahui.interfaceRef.construct;
@FunctionalInterface
public interface PersonBuilder {
     Person build(String name);
}

执行

package com.jiahui.interfaceRef.construct;
public class DemoConstructor {
	public static void method(PersonBuilder builder) {
		Person person = builder.build("能省");
		System.out.println("名字叫作:"+person.getName());
		
	}	
	public static void main(String[] args) {
		method(t->new Person(t));
		
		/**如果lambda表达式要做的事情就是构造方法的内容,那么可以使用构造器引用,格式:(类名称::new)**/
		method(Person::new);
	}
}

七、JDK常用内置的函数式接口
1.从java8开始 ,jdk内置很多函数式接口,下面介绍几个常用到的

Supplier例子

package com.jiahui.interfaceRef.supplierDemo;

import java.util.function.Supplier;

/**
 * 为了更好地支持函数式编程,所以jdk给我们内置了很多常用的函数式接口,
 * 一般都是放在java.util.function包中
 * java.util.function.supplier<T>接口作用:“向外提供”一个数据
 * 
 * lambda表达式如果要使用外部局部变量,局部变量必须是有效final的。
 * @author Administrator
 *
 */
public class DemoSupplier {
	
	private static void method(Supplier<String> supplier) {
		String str = supplier.get();
		System.out.println("字符串:"+str);
	}
	public static void main(String[] args) {
		String dString = "Hello";
//		dString += "abc";如果是这样子就会报错,编译器通不过,因为必须是final的
		method(()->dString);
	}
}

Consumer例子

package com.jiahui.interfaceRef.cunsumerDemo;
import java.util.function.Consumer;
/***
 * @author Administrator
 */
public class DemoConsumer {
     //参数当做消费者
	public static void method(Consumer<String> consumer) {
		//这个方法就是内保存数据,相当于接收数据
		consumer.accept("ddsjsdkdfjdkfjdkf");
	}
	private static void method02(Consumer<String> one,Consumer<String> two) {
		//先做one操作,然后再做two操作,将二者拼装到一起:函数拼装
		one.andThen(two).accept("Hello");
	}
	public static void main(String[] args) {
		method(t->{String upperCase = t.toUpperCase();
		System.out.println(upperCase);
		});
		method02(one -> System.out.println(one.toLowerCase()), two->System.out.println(two.toUpperCase()));
	}
}
package com.jiahui.interfaceRef.cunsumerDemo;
import java.util.function.Consumer;
public class DemoConsumer2 {
	private static void Method(Consumer<String> one,Consumer<String> two,String[] array) {
		for (int i = 0; i < array.length; i++) {
			one.andThen(two).accept(array[i]);
		}
	}	
	public static void main(String[] args) {
		String[] array = {"迪x热巴,女","古t娜扎,女","吉k隽逸,女","赵e雷,男"};
		Method(one->{System.out.println(one.split(",")[0]);}, two->{System.out.println(two.split(",")[1]);}, array);
	}
}

Predicate例子

package com.jiahui.interfaceRef.predicateDemo;

import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 为了更好地支持函数式编程,所以jdk给我们内置了很多常用的函数式接口,
 * 一般都是放在java.util.function包中
 * java.util.function.Predicate<T>接口作用:对指定类型的对象进行操作,
 *      得到一个boolean值结果
 * 
 * lambda表达式如果要使用外部局部变量,局部变量必须是有效final的。
 * @author Administrator
 *
 */
public class DemoPredicate {
	
	private static void method(Predicate<String> predicate) {
		boolean veryLong = predicate.test("Hello");
		System.out.println("字符串太长:"+veryLong);
	}
	public static void main(String[] args) {
		method((s)->s.length()>4);
	}
}

Function例子

package com.jiahui.interfaceRef.functionDemo;
import java.util.function.Function;
/**
 * java.util.function.Function<T,R>
   *   第一个泛型代表:函数参数类型
   *   第二个泛型代表:函数的返回值类型
 * @author Administrator
 * 抽象方法:apply(T param)
 */
public class DemoFunction {
	private static void method(Function<String, Integer> function) {
		Integer apply = function.apply("100");
		System.out.println(apply);
	}
	public static void main(String[] args) {
		method(Integer::parseInt);
		method(t->Integer.parseInt(t));
	}
}
package com.jiahui.interfaceRef.functionDemo;

import java.util.function.Function;

/**
 * Function接口当中默认方法:
 * andThen  先做自己在做其他
 * compose  先做其他再做自己
 * @author Administrator
 *
 */
public class DemoAndThen {
	private static void method(Function<String, String> one,Function<String, Integer> two){
		Integer age = one.andThen(two).apply("女神,23");
		age +=1;
		System.out.println("年龄"+age);
	}
	private static void methodCompose(Function<String, String> one,Function<String, Integer> two){
		Integer age = two.compose(one).apply("女神,23");
		age +=1;
		System.out.println("年龄"+age);
	}
	
	public static void main(String[] args) {
		method(one -> one.split(",")[1], Integer::parseInt);
		methodCompose(one -> one.split(",")[1], Integer::parseInt);
	}
}

八、JDK9使用函数式接口

package com.jiahui.interfaceStaticDemo2;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 * java8当中接口中可以定义的静态方法,这个特性在java9当中得以广泛应用。
 * 集合接口中的工厂静态方法:of
 * @author Administrator
 *
 */
public class DemoCollection {
	public static void main(String[] args) {
		List<String> list = new ArrayList<>();
		list.add("广东省");
		list.add("北京市");
		list.add("天津市");
		list.add("海南省");
		System.out.println(list);
		
		List<String> list2 = new ArrayList<String>() {
			{ 
				add("贵州省");
				add("云南省");
				add("安徽省");
				add("广西");
			}
		};
		System.out.println(list2);
		
		List<String> list3 = List.of("湖北省", "湖南省", "四川省", "青海省", "河北省", "甘肃省");
		System.out.println(list3);
		
		//里面的元素不能重复,重复就会报错
		Set<String> set = Set.of("洪七公","黄药师","欧阳锋","段智兴");
		System.out.println(set);
		
		
		Map<String, Object> map = Map.of("猫","百");
		System.out.println(map);
		
		Map<String, Object> map2 = Map.of("女孩","漂亮","男孩子","帅气");
		System.out.println(map2);		
	}
}

  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值