引言
- 伴随着编程技术的不断发展,oracle为了编程的便捷和提升项目的可维护性,对java做了许多的升级,比如新出现的lambda表达式的引入,在接口中增加静态方法和默认方法以及提取私有方法,下文首先复习一下lambda表达式。
lambda表达式
为什么采用lambda表达式?
- Lambda表达式是为了使得接口编程更加方便,这也可以与从lambda表达式的编程思想来考虑,函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”,所以这个可以使java编程变得更加优雅,代码更加简洁。
使用Lambda表达式需要注意的事项有哪些?
- 使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法。
- 必须有上下文环境,才能推导出Lambda对应的接口。
以下是lambda表达式的具体实例理解。
根据局部变量的赋值得知Lambda对应的接口
Runnable r = () -> System.out.println(“Lambda表达式”);
根据调用方法的参数得知Lambda对应的接口
new Thread(() -> System.out.println(“Lambda表达式”)).start();
可以将lambda表达式理解为实现接口的一个对象()
lambda表达式与匿名内部类有什么区别?
1)所需类型不同
匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
Lambda表达式:只能是接口
2)使用限制不同
如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类,如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式。
3)实现原理不同
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成。
案例
采用lambda表达式和匿名内部类实现绵绵的接口,并体会两种方式的不同。
接口类1
public interface Addable {
int add(int x, int y);
}
接口类2
public interface Eatable {
void eatable(String s);
}
接口类3
public interface Likable {
void like(String s);
}
测试类
public class LambdaDemo {
public static void main(String[] args) {
useAddable(new Addable() {
@Override
public int add(int x, int y) {
System.out.println("------------Add采用匿名内部类-------------");
return x+y;
}
});
useEatable(new Eatable() {
@Override
public void eatable(String s) {
System.out.println("----------Eat采用匿名内部类------------");
System.out.println(s);
}
});
useLikable(new Likable() {
@Override
public void like(String s) {
System.out.println(s);
}
});
System.out.println("----------采用lambda表达式--------------");
useAddable((int x,int y)->{
System.out.println("-------------Eat采用lambda表达式---------------");
return x+y;
});
useEatable((String str)->{
System.out.println("----------Eat采用lambda表达式------------");
});
useLikable((String s)->{
System.out.println(s);
});
System.out.println("----------采用省略lambda表达式----------");
useEatable((s)-> System.out.println(s));
useAddable((x,y)->x+y);
useLikable((s)-> System.out.println(s));
}
public static void useEatable(Eatable eat){
eat.eatable("我爱吃苹果");
}
public static void useAddable(Addable add){
int sum = add.add(10, 20);
System.out.println("sum:"+sum);
}
public static void useLikable(Likable like){
//System.out.println("--------i love java---------");
//System.out.println("---------i love python----------");
like.like("--------i love java---------");
like.like("---------i love python----------");
}
}
测试结果
接口新特性
- Jdk根据用户需求在接口中可以加入静态方法,默认方法,私有方法等等,这都是为了方便项目扩展,减少代码之间的耦合性,下面来看实际案例。
案例
体验jdk中新增带有方法体的私有方法。
接口类
public interface MyInterface {
void show(String s);
public static void show01(){
System.out.println("---------this is static void show01----------");
show03();
//无法调用非静态方法
//show04();
}
public default void show02(){
System.out.println("-----------this is default void show03------------");
show03();
show04();
}
private static void show03(){
System.out.println("---------this is private static void show03--------");
}
private void show04(){
System.out.println("---------this is private normal void show04--------");
}
}
测试类
public class TestDemo {
public static void main(String[] args) {
useMyInterface((s)->{
System.out.println("------这是通过lambda表达式实现MyInterface的show方法-------");
System.out.println(s);
});
MyInterface.show01();
MyInterface myInterface = new MyInterface() {
@Override
public void show(String s) {
System.out.println("------这是通过new的对象实现MyInterface的show方法-------");
System.out.println(s);
}
};
myInterface.show("I LOVE PYTHON");
myInterface.show02();
}
public static void useMyInterface(MyInterface myInterface){
myInterface.show("i love java");
}
}
测试结果
notes
默认方法可以调用私有的静态方法和非静态方法
静态方法只能调用私有的静态方法。
方法引用
为什么会出现方法引用?
在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,所以就再也没有必要写重复逻辑。
什么是方法引用符?
:: 该符号为引用运算符,而它所在的表达式被称为方法引用
lambda表达式和方法引用是什么关系?
方法引用是Lambda的孪生兄弟
如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导;如果使用方法引用,也是同样可以根据上下文进行推导。
案例一
各类接口
public interface Converter {
int convert(String s);
}
public interface MyString {
String mySubString(String str,int x, int y);
}
public interface Printable {
void printUpperCase(String s);
}
Student build(String name,int age);
}
学生类
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
printStr类
public class PrintStr {
public void printUpper(String s){
String str = s.toUpperCase();
System.out.println(str);
}
}
测试类
public class ReferenceDemo {
public static void main(String[] args) {
useConverter((s)->{
int i = Integer.parseInt(s);
//System.out.println(i);
return i;
});
//采用静态方法
useConverter(Integer::parseInt);
System.out.println("-----------------------");
//采用lambda接口来
usePrintStr((s)->{
System.out.println(s.toUpperCase());
});
//采用对象应用方法
PrintStr printStr = new PrintStr();
usePrintStr(printStr::printUpper);
System.out.println("-----------------------");
//引用类中成员方法
useMyString((s,x,y)-> s.substring(x,y));
useMyString(String::substring);
System.out.println("------------------------");
//采用构造方法
useStudentBuilder((s,x)->new Student(s,x));
useStudentBuilder(Student::new);
}
public static void useConverter(Converter converter){
System.out.println("the result is:"+converter.convert("666"));
}
public static void usePrintStr(Printable printable){
printable.printUpperCase("I Love Java I Love Python");
}
public static void useMyString(MyString myString){
String str = myString.mySubString("HelloJava", 1, 6);
System.out.println(str);
}
public static void useStudentBuilder(StudentBuilder studentBuilder){
Student student = studentBuilder.build("赵丽颖", 34);
System.out.println(student.getName()+":"+student.getAge());
}
}
测试结果
案例二
采用
public class FunctionInterface {
public static void main(String[] args) {
String string = getString(() -> "巨量鹏");
System.out.println(string);
System.out.println("-------------------");
int val = getInteger(() -> 30);
System.out.println(val);
System.out.println("------------------");
int[] arr = {19, 97, 28, 37, 46,76};
int maxVal=getMax(()->{
int max =arr[0];
for (int i = 1; i < arr.length; i++) {
if(arr[i]>max){
max=arr[i];
}
}
return max;
});
System.out.println(maxVal);
System.out.println("------------------");
/*operatorString("天量鹏",(String s)->{
System.out.println(s);
});*/
//采用lambda表达式
operatorString("天量鹏", s-> System.out.println(s));
//采用函数式应用
// operatorString("天量鹏", System.out::println);
//采用匿名内部类
operatorString("若皮赞", new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
//反向输入
operatorString("天量鹏",s-> System.out.println(new StringBuilder(s).reverse().toString()));
System.out.println("---------------------------");
operatorString("天量鹏",s-> System.out.println(s),
s-> System.out.println(new StringBuilder(s).reverse().toString()));
System.out.println("---------------------------");
String [] strArr={"杨颖,38","赵丽颖,34"};
operatorString(strArr,s -> {
String sName=s.split(",")[0];
System.out.println("姓名:"+sName);
},s->{
int sAge=Integer.parseInt(s.split(",")[1]);
System.out.println("年龄:"+sAge);
});
System.out.println("------------------------");
boolean test = checkString("hello", s ->
s.length() > 4
,s -> s.length() < 9);
System.out.println(test);
System.out.println("------------------------");
String [] str= {"刘亦菲,40","刘岩,42","韩雪,44","文章,32","迪丽热巴,36","杨幂,37","我爱罗,34"};
ArrayList<String> arrayList = condition(str, s -> {
String s1 = s.split(",")[0];
return s1.length() > 2;
}, s -> {
int i = Integer.parseInt(s.split(",")[1]);
return i > 35;
});
for (String o : arrayList) {
System.out.println(o);
}
System.out.println("--------------------------");
String myConverter = converter("120", 6, (s) -> {
return Integer.parseInt(s);
}, (s) -> Integer.toString(s));
System.out.println(myConverter);
}
//定义一个方法,返回一个整数数据
private static Integer getInteger(Supplier<Integer> sup) {
return sup.get();
}
//定义一个方法,返回一个字符串数据
private static String getString(Supplier<String> sup) {
return sup.get();
}
private static int getMax(Supplier<Integer> sup){
return sup.get();
}
private static void operatorString(String str, Consumer<String> consumer){
consumer.accept(str);
}
private static void operatorString(String str, Consumer<String> consumer1,Consumer<String > consumer2){
//consumer1.accept(str);
//consumer2.accept(str);
consumer1.andThen(consumer2).accept(str);
}
private static void operatorString(String [] str,Consumer<String> consumer1,Consumer<String > consumer2){
for (String s :
str) {
consumer1.andThen(consumer2).accept(s);
}
}
private static boolean checkString(String s, Predicate<String> s1,Predicate <String> s2){
/*boolean test1 = s1.test(s);
boolean test2=s2.test(s);
return test1&&test2;*/
//也可以使用or方法
return s1.and(s2).test(s);
}
private static ArrayList condition(String [] str,Predicate<String> s1,Predicate<String> s2){
ArrayList<String> arrayList = new ArrayList<>();
for (String s : str) {
boolean test = s1.and(s2).test(s);
if(test){
arrayList.add(s);
}
}
return arrayList;
}
//Function接口
private static String converter(String s, int startVal, Function<String ,Integer > fun1,Function<Integer ,String > fun2){
Integer apply = fun1.apply(s)+startVal;
String apply1 = fun2.apply(apply);
return apply1;
//不能满足要求
//return fun1.andThen(fun2).apply(s);
}
}
测试结果