• 反射、枚举、lambda——小记


    反射

    反射定义

    Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制

    反射相关的类

    在这里插入图片描述

    Class 类

    Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为 一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个 实例(这个Class对象存放在方法区,不在堆里面的).我们通过Java的反射机制应用到这个实例,就 可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类。

    反射示例

    获得Class对象的三种方式

    第一种,使用Class.forName(“类的全路径名”);静态方法。

    Class<?> c1 = Class.forName("refelectdemo.Student");
    
    • 1

    第二种,使用.class 方法

    Class<?> c2 = Student.class;
    
    • 1

    第三种,使用类对象的 getClass() 方法

    Student student = new Student();
    Class<?> c3 = student.getClass();
    
    • 1
    • 2

    完整代码如下:

    class Student{
        //私有属性name
        private String name = "bit";
        //公有属性age
        public int age = 18;
        //不带参数的构造方法
        public Student(){
            System.out.println("Student()");
        }
    
        private Student(String name,int age) {
            this.name = name;
            this.age = age;
            System.out.println("Student(String,name)");
        }
    
        private void eat(){
            System.out.println("i am eat");
        }
    
        public void sleep(){
            System.out.println("i am pig");
        }
    
        private void function(String str) {
            System.out.println(str);
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    
    
    public class Test {
    
        public static void main1(String[] args) throws ClassNotFoundException{
    //        Student student = new Student();
            //1、获取一个Class对象
            Class<?> c1 = Class.forName("refelectdemo.Student");
    
            Class<?> c2 = Student.class;
    
            Student student = new Student();
            Class<?> c3 = student.getClass();
    
            System.out.println(c1.equals(c2));
            System.out.println(c1.equals(c3));
            System.out.println(c2.equals(c3));
            //Class对象  只有1个
        }
    }
    
    • 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

    反射使用 ——代码

    1.通过反射获取Class对象
    2.反射私有构造方法

    public class ReflectClassDemo {
    
        // 创建对象
        public static void reflectNewInstance() {
            try {
                Class<?> c1 = Class.forName("refelectdemo.Student");
    
                Student student = (Student)c1.newInstance();
    
                System.out.println(student);
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
        // 反射私有的构造方法  屏蔽内容为获得公有的构造方法
        public static void reflectPrivateConstructor() {
            try {
                Class<?> c1 = Class.forName("refelectdemo.Student");
    
                Constructor<?> constructor = c1.getDeclaredConstructor(String.class,int.class);
    
                //私有的本身是封装的,
                constructor.setAccessible(true);
    
                Student student = (Student)constructor.newInstance("bit",19);
    
                System.out.println(student);
    
            } catch (ClassNotFoundException e) {
    
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
        // 反射所有的,用私有属性来举例
        public static void reflectPrivateField() {
            try {
                Class<?> c1 = Class.forName("refelectdemo.Student");
    
                Student student = (Student)c1.newInstance();
    
                Field field = c1.getDeclaredField("name");
    
                field.setAccessible(true);
                //student对象的field字段,设置为zhangsan值
                field.set(student,"zhangsan");
    
                System.out.println(student);
    
            } catch (ClassNotFoundException e) {
    
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
        // 反射私有方法
        public static void reflectPrivateMethod() {
            try {
                Class<?> c1 = Class.forName("refelectdemo.Student");
    
                Student student = (Student)c1.newInstance();
    
                //方法名称    方法的参数
                Method method = c1.getDeclaredMethod("function", String.class);
    
                method.setAccessible(true);
    
                method.invoke(student,"我是function的参数!");
    
            } catch (ClassNotFoundException e) {
    
            }  catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            //reflectNewInstance();
            //reflectPrivateConstructor();
            //reflectPrivateField();
            reflectPrivateMethod();
        }
    
    }
    
    • 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

    面试题:你知道有几种创建对象的方式吗?

    1、new关键字实例化对象
    2、clone()
    3、newlnstance()–>Class类的
    4、constructor.newInstance()

    反射优点和缺点

    优点:

    1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
    2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
    3. 反射已经运用在了很多流行框架如: Struts、Hibernate、Spring 等等。

    缺点:

    1. 我们认为反射是一个“自省"的过程,所以在性能上面有性能的问题,一般不建议用在小型程序上,可用到框架当中。
    2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。

    枚举

    枚举是在JDK1.5以后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式:

    public static final RED = 1; 
    public static final GREEN = 2; 
    public static final BLACK = 3;
    
    • 1
    • 2
    • 3

    但是常量举例有不好的地方,例如:可能碰巧有个数字1,但是他有可能误会为是RED。现在我们可以直接用枚举来进行组织,这样一来,就拥有了类型,枚举类型。

    public enum TestEnum { RED,BLACK,GREEN; }
    
    • 1

    优点:将常量组织起来统一进行管理
    场景:错误状态码,消息类型,颜色的划分,状态机等等…
    本质:是 java.lang.Enum 的子类,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。

    不能反射枚举对象
    在这里插入图片描述

    Lambda表达式

    概念

    Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body),可以是一个表达式或一个代码
    块)。 Lambda 表达式(Lambda expression)可以看作是一个匿名函数,基于数学中的λ演算得名,也可称为闭
    包(Closure) 。

    Lambda表达式的语法

    基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
    Lambda表达式由三部分组成:

    1. paramaters类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明,也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
    2. ->:可理解为“被用于”的意思
    3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回

    如果方法体只有一条语句,花括号{}可省略

    函数式接口有且只有一个抽象方法。

    代码

    package lambda;
    
    import java.util.Comparator;
    import java.util.PriorityQueue;
    
    /**
     * @Author 12629
     * @Date 2022/4/4 20:19
     * @Description:
     */
    //无返回值无参数
    @FunctionalInterface
    interface NoParameterNoReturn {
        void test();
    }
    //无返回值一个参数
    @FunctionalInterface
    interface OneParameterNoReturn {
        void test(int a);
    }
    //无返回值多个参数
    @FunctionalInterface
    interface MoreParameterNoReturn {
        void test(int a,int b);
    }
    
    //有返回值无参数
    @FunctionalInterface
    interface NoParameterReturn {
        int test();
    }
    
    //有返回值一个参数
    @FunctionalInterface
    interface OneParameterReturn {
        int test(int a);
    }
    //有返回值多参数
    @FunctionalInterface
    interface MoreParameterReturn {
        int test(int a,int b);
    }
    
    
    
    public class Test1 {
        public static void main1(String[] args) {
            MoreParameterReturn moreParameterReturn = new MoreParameterReturn(){
                @Override
                public int test(int a, int b) {
                    return a+b;
                }
            };
    
            MoreParameterReturn moreParameterReturn2 = (int a,int b)->{return a+b;};
    
    
            PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o1-o2;
                }
            });
    
            PriorityQueue<Integer> priorityQueue1 = new PriorityQueue<>((o1, o2) -> {return o1-o2;});
    
        }
    }
    
    • 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

    一般调用有返回值多参是以下代码实现

    MoreParameterReturn moreParameterReturn = new MoreParameterReturn(){
                @Override
                public int test(int a, int b) {
                    return a+b;
                }
            };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    即 一个匿名内部类实现了当前接口,并且重写了这个接口的方法

    正则化表达式用如下形式表示,相比之下代码变得更加简洁;

    MoreParameterReturn moreParameterReturn2 = (int a,int b)->{return a+b;};
    
    • 1
  • 相关阅读:
    CSDN页内跳转
    判断子序列
    dosbox调试模式下0000:0000地址中内容被修改的原因
    Java三方库-单元测试
    spark Structured报错解决
    股票交易查询接口api新增哪些了特点?
    新品上市的软文怎么写?产品软文撰写实用技巧
    光伏并网逆变器低电压穿越技术研究(Simulink仿真)
    写给新用户-Mac软件指南篇:让你的Mac更好用
    基于51单片机的可调节占空比四种三种波形发生器proteus仿真
  • 原文地址:https://blog.csdn.net/xy199931/article/details/128041152