Lamda表达式
- 从JDK1.8开始为了简化使用者进行代码的开发,专门提供有Lamda表达式的支持,利用此操作形式可以实现函数式的编程,对于函数式编程比较著名的语言:haskell、Scala,利用函数式编程可以避免掉面向对象编程之中的一些繁琐的处理问题;
- 面向对象在其长期发展的过程之中一直有一部分的反对者,这些反对者认为面向对象的设计过于复杂了,并且过于繁琐了,以一个简单的程序为例:
//观察传统开发中的问题
package demo;
interface IMessage {
public abstract void send(String msg);
}
public class JavaDemo {
public static void main(String [] args) {
IMessage msg = new IMessage() { //匿名内部类
public void send(String msg) {
System.out.println(msg);
}
};
msg.send("这是一个消息");
}
}
- 在这样一个程序里面,实际上核心的功能只有一行语句“System.out.println(msg);”,但是为了这一行的核心语句依然需要按照完整的面向对象给出的设计结构进行开发,于是这些问题随着技术的不断发展也是越来越突出了;
//使用Lamda表达式实现与之前一样的功能
package demo;
interface IMessage {
public abstract void send(String str);
}
public class JavaDemo {
public static void main(String [] args) {
IMessage msg = (str) -> {
System.out.println(str);
};
msg.send("这是一个消息");
}
}
- 现在整个程序代码里面会发现真的只是编写了一行语句,于是利用这种形式就避免了复杂的面向对象结构化的要求;
- Lamda表达式如果想要使用,有一个重要的实现要求:SAM(Single Abstract Method)只有一个抽象方法,以之前的IMessage接口为例,在这个接口里面发现只是提供有一个send()方法,除此之外没有任何的其他方法定义,所以这样的接口就被称为函数式接口,而只有函数式接口才可以被Lamda表达式所使用;
package demo;
@FunctionalInterface
interface IMessage {
public abstract void send(String str);
}
public class JavaDemo {
public static void main(String [] args) {
IMessage msg = (str) -> {
System.out.println(str);
};
msg.send("这是一个消息");
}
}
- 对于Lamda表达式而言,提供有如下几种格式:
- 方法没有参数:() -> {};
- 方法有参数:(参数, 参数) -> {};
- 如果现在只有一行语句返回:(参数, 参数) -> 语句;
//定义没有参数的方法
package demo;
@FunctionalInterface
interface IMessage {
public abstract void send();
}
public class JavaDemo {
public static void main(String [] args) {
IMessage msg = () -> {
System.out.println("这是一个消息");
};
msg.send();
}
}
//定义有参数的处理形式
package demo;
@FunctionalInterface
interface IMath {
public abstract int add(int x, int y);
}
public class JavaDemo {
public static void main(String [] args) {
IMath math = (x, y) -> {
return x + y;
};
System.out.println(math.add(10, 5));
}
}
//简化Lamda操作
package demo;
@FunctionalInterface
interface IMath {
public abstract int add(int x, int y);
}
public class JavaDemo {
public static void main(String [] args) {
IMath math = (x, y) -> x + y;;
System.out.println(math.add(10, 5));
}
}
- 利用Lamda表达式的确摆脱了传统面向对象之中关于结构的限制,使得代码更加的简便;
方法引用
- 引用数据类型最大的特点是可以进行内存的指向处理,在传统开发之中一直所使用的只是对象引用操作,而从JDK1.8之后也提供有方法的引用,即:不同的方法名称可以描述同一个方法,如果要进行 方法的引用在Java里面提供有如下的四种形式:
- 引用静态方法:类名称 :: static 方法名称;
- 引用某个实例对象的方法:实例化对象 :: 普通方法;
- 引用特点类型的方法:特定类 :: 普通方法;
- 引用构造方法:类名称 :: new;
//引用静态方法
//在String类里面提供有String.valueOf()方法,这个方法就是静态方法
//方法定义:public static String vauleOf(int i),该方法有参数,并且有返回值
package demo;
@FunctionalInterface
//P描述的是参数,R描述的是返回值
interface IFunction<P, R> {
public abstract R change(P p);
}
public class JavaDemo {
public static void main(String [] args) {
IFunction<Integer, String> fun = String :: valueOf;
String str = fun.change(100);
System.out.println(str.length());
}
}
- 利用方法引用这一概念可以为一个方法定义多个名字,但是要求必须是函数式接口;
//引用实例化对象中的方法
//String类里面有一个转大写的方法:public String toUpperCase()
//这个对象必须在有实例化对象提供的情况下才可以调用
package demo;
@FunctionalInterface
//R描述的是返回值
interface IFunction<R> {
public abstract R upper();
}
public class JavaDemo {
public static void main(String [] args) {
IFunction<String> fun = "www.baidu.com" :: toUpperCase;
System.out.println(fun.upper());
}
}
- 在进行方法应用的时候也可以引用特定类中的一些操作方法,在String类里面提供有一个字符串大小关系的比较:
- 比较大小:public int compareTo(String anotherString);
- 这是一个普通方法,如果要引用普通方法,往往需要实例化对象,但是现在不想给出实例化对象,只是想引用这个方法,则就可以使用特定类来进行引用处理;
//引用指定类中的方法
package demo;
@FunctionalInterface
interface IFunction<P> {
public abstract int compare(P p1, P p2);
}
public class JavaDemo {
public static void main(String [] args) {
IFunction<String> fun = String :: compareTo;
System.out.println(fun.compare("A", "a"));
}
}
//引用构造方法
package demo;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "姓名:" + this.name + "、年龄:" + this.age;
}
}
@FunctionalInterface
interface IFunction<R> {
public abstract R create(String s, int a);
}
public class JavaDemo {
public static void main(String [] args) {
IFunction<Person> fun = Person :: new;
System.out.println(fun.create("张三", 20));
}
}
- 提供方法引用的概念更多的情况下也只是弥补了对于引用的支持功能;
内建函数式接口
- 在JDK1.8之中提供有Lamda表达式也提供有方法引用,但是你会发现现在如果由开发者自己定义函数式接口,往往都需要使用“@FunctionalInterface”注解来进行大量声明,于是很多情况下如果为了方便则可以直接引用系统中提供的函数式接口;
- 在系统之中专门提供有一个java.util.function的开发包,里面可以直接使用函数式接口,在这个包下面一共有如下的几个核心接口供使用:
- 功能型函数式接口:
/**
接口定义:
@FunctionalInterface
public interface Function<T, R> {
public R apply(T t)
}
*/
//在String类中有一个方法判断是否以指定的字符串开头:public boolean startsWith(String str);
//接口使用
package demo;
import java.util.function.*;
public class JavaDemo {
public static void main(String [] args) {
Function<String, Boolean> fun = "**Hello" :: startsWith;
System.out.println(fun.apply("**"));
}
}
- 消费型函数式接口:只能进行数据的处理操作,而没有任何的返回;
/**
接口定义:
@FunctionalInterface
public interface Consumer<T> {
public void accept(T t);
}
*/
//System.out.println();
//接口使用
package demo;
import java.util.function.*;
public class JavaDemo {
public static void main(String [] args) {
Consumer<String> con = System.out :: println;
con.accept("www.baidu.com");
}
}
/**
接口定义:
@FunctionalInterface
public interface Supplier<T> {
public T get();
}
*/
//在String类中提供有转小写方法,这个方法没有接收参数,但是有返回值:public String toLowerCase();
//接口使用
package demo;
import java.util.function.*;
public class JavaDemo {
public static void main(String [] args) {
Supplier<String> sup = "www.BAIDU.com" :: toLowerCase;
System.out.println(sup.get());
}
}
/**
接口定义:
@FunctionalInterface
public interface Predicate<T> {
public boolean test(T t)
}
*/
//在String类有一个equalsIgnoreCase()方法;
//接口使用
package demo;
import java.util.function.*;
public class JavaDemo {
public static void main(String [] args) {
Predicate<String> pre = "baidu" :: equalsIgnoreCase;
System.out.println(pre.test("BAIDU"));
}
}
- 开发之中,如果JDK本身提供的函数式接口可以被我们所使用,那么就没有必要进行重新定义;
网友评论