当前位置:   article > 正文

Java基础(二十二)——反射(获取属性)、jdk8 与 jdk9 接口的特性概念、Lambda表达式、四个函数式接口(Supplier、Consumer、Predicate、Function)_java 反射方法变成function

java 反射方法变成function

Java基础(二十二)——反射(获取属性)

一、反射

1、获取属性

反射前面讲了这么多,就只剩下获取属性没讲。
先看下反射获取属性的方法:
在这里插入图片描述

学生类的属性:
在这里插入图片描述

2、getFields()——获得所有公开的属性

在这里插入图片描述
然后效果:
在这里插入图片描述

3、getDeclaredFields()——获得所有属性(包括私有的)

在这里插入图片描述

效果:
在这里插入图片描述

4、getField()——获得单个公有的属性

私有同理,就不再作演示了。

在这里插入图片描述

二、jdk8 与 jdk9 接口的特性概念

1、概念

概念:在jdk8与jdk9之后,接口不仅可以存在抽象方法,还可以有普通的成员方法。

2、增加内容

jdk8:增加的静态方法与默认方法。
jdk9:增加了私有的方法

3、影响

接口中可以存在抽象方法,也可以存在普通的成员方法。

所以接口与抽象类的差距缩小,接口可以多继承,所以在实际的开发中大部分使用接口来定义。

4、接口中的默认方法

a、了解

1、概念:在jdk8之后,接口才能增加默认的方法
2、默认方法使用的关键字: default
3、语法: 访问修饰符 default 返回值类型 方法的名称 (参数列表) {方法体}
4、注意点:
	A.接口中的默认方法,必须通过实例化实现类才能进行调用。
	B.接口中的默认方法,实现类不是必须强制性需要重写。
	C.接口的实现类,需要调用接口中的默认方法,必须通过  接口的名称.super.方法名()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

b、调用方法一

先来看下接口:
在这里插入图片描述

然后是实现类:
在这里插入图片描述

然后调用:
在这里插入图片描述
通过多态创建对象,然后通过这个对象直接调用接口的默认方法。

c、调用方法二:

在这里插入图片描述

通过实现类的对象来调用接口的默认方法,但是前提必须是实现类中的方法通过 super 调用到接口中的默认方法。

5、接口中的静态方法

a、了解

1.概念:在jdk8之后,接口中才能存在静态方法。
2.使用的关键字修饰:static
3.语法: 访问修饰符 static 返回值类型 方法的名称 (参数列表) {方法体}
4.注意点:
	A.接口中定义方法,不必须强制进行重写。
	B.接口静态方法,只能通过接口的名称来进行调用。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

b、调用

接口代码:
在这里插入图片描述

调用:
在这里插入图片描述

6、接口中私有的方法

a、了解

1.概念:在jdk9之后,接口中才能定义私有的方法。
2.注意点:
	A.接口中的默认方法是可以调用私有的方法,静态方法不能调用普通私有的方法。
	B.接口中静态的私有方法,默认方法与静态方法都是可以进行调用。
  • 1
  • 2
  • 3
  • 4

b、调用

由于博主没有搞 jdk 1.9,所以这里以后再补上。

三、Lambda表达式

1、了解 Lambda 表达式

1、本质:Lambda本质是一个接口 是一个匿名接口。

2、前提条件:必须是一个函数式接口,接口中只能有一个抽象方法,但是可以有默认的方法,例
子:Comparable

3、简化匿名内部类的写法。

4、语法:

(参数) ->{
	方法体
}
  • 1
  • 2
  • 3

5、解释:
参数:表示的是接口中抽象方法的参数。
->:Lambda的语法,指向方法体。
{}:执行具体的操作。

2、通过例子了解 Lambda 表达式

a、通过匿名内部类创建线程,并用 Lambda 表达式简化

public class Demo1 {
    public static void main(String[] args) {
        new Thread(new Runnable() {            //   通过匿名内部类写一个线程
            @Override
            public void run() {
                System.out.println("喵喵喵");
            }
        }).start();{
        };

        new Thread(()->{                    //  Lambda 表达式简化匿名内部类
            System.out.println("喵喵喵");
        }).start();{
        };
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

b、没有参数没有返回值的 Lambda 表达式

通过前面的前提条件,可以了解到,能够使用 Lambda 表达式的前提是必须是一个函数式接口,其他方法不管你有没有,里面只能有一个抽象方法。因此,我们可以手动写这么一个接口,然后自己手动的使用这个 Lambda 表达式。

接口代码:

public interface Inter1 {
    void show1();
}
  • 1
  • 2
  • 3

主函数代码:

public class Demo02 {
    public static void main(String[] args) {
//        show(()->{      //  没有参数没有返回值
//            System.out.println("lambda表达式");
//        });

        show(()-> System.out.println("lambda表达式"));     //  简化。一行搞定。精简了大括号。
    }

    public static void show(Inter1 inter1){     //  实现这个接口
        inter1.show1();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

c、有参数没有返回值的 Lambda 表达式

接口代码:

public interface Inter2 {
    void show2(String name);
}
  • 1
  • 2
  • 3

主函数代码:

public class Demo03 {
    public static void main(String[] args) {    //  有参数没有返回值

//        show("我是傻批",(String name)->{      //  只有一个参数的 Lambda 表达式
//            System.out.println(name);
//        });
        show("二狗", name -> System.out.println(name));   //  简化写法。只有一个参数的情况下,可以省略数据类型。精简了大括号。
    }

    public static void show(String name,Inter2 inter2){
        inter2.show2(name);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

d、有参数有返回值的 Lambda 表达式

接口代码:

public interface Inter3 {
    int show3(int a,int b);
}
  • 1
  • 2
  • 3

主函数代码:

public class Demo04 {
    public static void main(String[] args) {
//        System.out.println(show(3, 5, (int a,int b)->{        //  两个参数的 Lambda 表达式。这里省略了接收返回值,直接输出。
//            return a*b;
//        }));

        System.out.println(show(3, 5, (int a,int b) -> a*b ));     //  简化写法。少了大括号和 return 语句。
    }

    public static int show(int a,int b,Inter3 inter3){
        return  inter3.show3(a, b);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3、案例:用 Lambda 表达式代替匿名内部类传递比较器

还记得之前的一个排序写法,其中用到的传递比较器方法,当时用的是匿名内部类。这里通过 Lambda 表达式再优化一下:

主函数代码:

public class Demo01 {
    public static void main(String[] args) {
        String[] strArrays = {"a","ab","abc","abcd"};
        Arrays.sort(strArrays,getsort());
        System.out.println(Arrays.toString(strArrays));
    }
    public static Comparator<String> getsort(){
//        return new Comparator<String>() {         //  这里通过匿名内部类传递比较器
//            @Override
//            public int compare(String o1, String o2) {
//                return o1.length()-o2.length();
//            }
//        };

//        return (String s1,String s2) ->{      //  通过 Lambda 表达式精简匿名内部类
//            return s1.length()-s2.length();
//        };

        return (String s1,String s2) -> s1.length()-s2.length();    // 简化写法。精简了大括号和 return 语句。
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

这里的功能是根据字符个数进行排序。

4、Lambda简化方式小结

第一种情况:如果只有一个参数,可以省略其小括号与数据类型。
第二种情况:如果方法体只有一句话,可以省略大括号以及分号。
第三种情况:如果方法有返回值,方法体只有返回值这一句话,可以省略 retrun 分号、大括号。

四、四个函数式接口

1、了解相关知识

1、概念:函数式接口只能有一个抽象方法 可以存在其它的默认方法 以及静态方法。

2、函数式接口使用的注解:@FunctionalInterface 用于来检查是否是函数式接口。

3、函数式接口两种体现形式:
第一种:以函数式接口作为方法的参数。
第二种:以函数式接口作用方法的返回值。

2、Supplier——供给型接口

在这里插入图片描述
接口描述:
其实这个接口本身并没有提供什么功能,就是你使用了这个接口,那么就意味着会返回一个结果。至于是返回什么结果,有什么功能,完全由你自己去写。

a、使用供给性接口获取一个字符串

主函数代码:

public class Demo01 {
    public static void main(String[] args) {
//        String str = getStr(()->{         //  lambda 表达式
//            return "牛牛";
//                });

        String str = getStr(() ->"牛牛");  //  简化写法

        System.out.println(str);
    }

    public static String getStr(Supplier<String> sup){
        return sup.get();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

效果:
在这里插入图片描述

b、使用供给性接口获取最小值

主函数代码:

public class Demo02 {
    public static void main(String[] args) {    //  通过供给型接口求出最小值
        
        int a = getStr(()->{    //  Lambda 表达式。下面开始写功能
            int min ;
            int[] nums = {1,8,-20,14,-2,20,9};
            min = nums[0];
            for (int i = 0; i < nums.length; i++) {
                if (min > nums[i]){
                    min = nums[i];
                }
            }
            return min;
        });
        
        System.out.println(a);
    }

    public static int getStr(Supplier<Integer> supplier){
        return supplier.get();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

3、Consumer——消费型接口

在这里插入图片描述
作用:感觉就是取出一些数据,并对这些数据进行二次处理。

通过例子来了解

a、例子(一) ——取字符串的一部分

使用消费型接口对牛牛子进行消费--->得到的结果是牛牛。

public class Demo01 {
    public static void main(String[] args) {        //  消费型接口消费字符串。也就是取字符串某一部分
        getStr("牛牛子", n->{
            System.out.println(n.substring(0,2));
        });
    }

    public static void getStr(String s, Consumer<String> con){
        con.accept(s);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

b、例子(二)——将一个字符串转换为大写,再转化为小写。

public class Demo02 {
    public static void main(String[] args) {    //  把字符串先转大写,再转小写.
        getStr("qweasd", (String s)->{
            System.out.println(s.toUpperCase());
        },(String w)->{
            System.out.println(w.toLowerCase());
        });
    }

    public static void getStr(String s, Consumer<String> con1,Consumer<String> con2){
        con1.andThen(con2).accept(s);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

c、例子(三)——取出数组中的字符串,并重新拼接字符串

//   需求: 对数组进行消费String [] arrays={"迪丽热巴:28","古力娜扎:24","渣渣辉:26"} 消费之后的字符串:
//        	姓名:迪丽热巴,年龄:28 姓名:古力娜扎,年龄:24 姓名:渣渣辉,年龄:26

public class Demo03 {
    public static void main(String[] args) {                //   对数组进行消费
        String [] arrays={"迪丽热巴:28","古力娜扎:24","渣渣辉:26"};
        getStr(arrays,  s->{
            System.out.print("姓名:"+s.split(":")[0]+",");
        }, (w->{
            System.out.println("年龄:"+w.split(":")[1]+"  ");
        }));
    }

    public static void getStr(String[] arrays, Consumer<String> con1,Consumer<String> con2){
        if (arrays != null && arrays.length>0){
            for (int i = 0; i < arrays.length; i++) {       //  对传进来的数组的每一个元素都进行比较
                con1.andThen(con2).accept(arrays[i]);
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

4、Predicate——断言型接口

这个接口的作用就是进行判断处理

在这里插入图片描述

a、例子(一)——判断字符串长度是否大于5

public class Demo1 {
    public static void main(String[] args) {
        boolean flag = isFlag("qweasd", s -> {  //  断言型接口 判断字符串长度是否大于5
            return s.length()>5;
        });
        System.out.println(flag);
    }
    public static boolean isFlag(String s, Predicate<String> predicate){
        return predicate.test(s);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

b、例子(二)——判断字符串长度是否大于5,再判断是否包含a

public class Demo2 {
    public static void main(String[] args) {    // 断言型接口 判断字符串长度是否大于5 判断字符串是否包含a
        boolean flag = isFlag("qweasdz", (s -> {
            return s.length()>5;
        }),(w->{
            return w.contains("a");
        }));
        System.out.println(flag);
    }

    public static boolean isFlag(String s, Predicate<String> s1,Predicate<String> s2){
        return s1.and(s2).test(s);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

c、例子(三)——将数组里面满足条件的数据添加到集合当中去

public class Demo3 {
    public static void main(String[] args) {    // 断言型接口 定义一个数组 String []array={"迪丽热巴","古丽热娜","苍老师","波多老师","小野老师"}
                                                // 将数组中元素的长度>=4 并且 包含老师 满足条件的数据存入的到集合
        String []array={"迪丽热巴","古丽热娜","苍老师","波多老师","小野老师"};
        List<String> list =  isFlag(array, (s)->{
            return s.length()>=4;
        },(w)->{
            return w.contains("老师");
        });
        System.out.println(list);
    }

    public static List<String> isFlag(String[] arrays, Predicate<String> pre1,Predicate<String>pre2){
        List<String> list = new ArrayList<>();
        if (arrays!= null && arrays.length >0){
            for (int i = 0; i < arrays.length; i++) {
                if (pre1.and(pre2).test(arrays[i])){
                    list.add(arrays[i]);
                }
            }
        }
        return list;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

5、Function<T, R>——函数型接口

目前感觉的作用是处理不同类型之间的转换

在这里插入图片描述

a、例子(一)——将 String 类型转换为 int 类型

public class Demo1 {
    public static void main(String[] args) {    //  使用函数型接口 将String类型转换为int类型
        int num = getStr("123", (s)->{
            return Integer.parseInt(s);		//	String 类型数据转换为 int 类型
        });
        System.out.println(num);
    }

    public static int getStr(String s, Function<String,Integer> fun){
        return fun.apply(s);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

b、例子(二)——将 String 类型里面的数据除杂,最后取出里面的 int 类型

public class Demo2 {        //  使用函数型接口 将String(华子 12) 转换为 String 12 再将String 转换int 12
    public static void main(String[] args) {
        int num = getStr("华子 12", (s -> {
            return s.split(" ")[1];		//	以空格切割,切割之后是数组,取出 int 类型的数据
        }),(w->{
            return Integer.parseInt(w);
        }));
        System.out.println(num);
    }

    public static int getStr(String s, Function<String,String> fun1,Function<String,Integer> fun2){
        return fun1.andThen(fun2).apply(s);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/726730
推荐阅读
相关标签
  

闽ICP备14008679号