JAVA SE 反射,枚举与lambda表达式

06-02 1554阅读

文章目录

    • 📕1. 反射
        • ✏️1.1 反射相关的类
        • ✏️1.2 Class类中的相关方法
        • ✏️1.3 Field类中的相关方法
        • ✏️1.4 Method类中的相关方法
        • ✏️1.5 Constructor类中的相关方法
        • ✏️1.6 获取Class对象的三种方式
        • ✏️1.7 反射的使用
        • 📕2. 枚举
            • 2.1 枚举的定义
            • ✏️2.2 枚举的使用
            • ✏️2.3 枚举的构造方法
            • ✏️2.4 枚举与反射
            • 📕3. Lambda表达式
                • ✏️3.1 Lambda表达式语法
                • ✏️3.2 函数式接口
                • ✏️3.3 变量捕获

                  📕1. 反射

                  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

                  ✏️1.1 反射相关的类
                  类名用途
                  Class类代表类的实体,在运行的Java应用程序中表示类和接口
                  Field类代表类的成员变量(类的属性)
                  Method类代表类的方法
                  Constructor代表类的构造方法
                  ✏️1.2 Class类中的相关方法
                  方法用途
                  getClassLoader()获得类的加载器
                  getDeclaredClasses()返回一个数组,数组中包含该类中所有的类和接口的对象(包含私有的)
                  forName(String className)根据类名返回类的对象
                  newInstance()创建类的实例
                  getName()获得类的完整路径名字
                  ✏️1.3 Field类中的相关方法
                  方法用途
                  getField(String name)获得某个共有的属性对象
                  getFileds()获得所有共有的属性对象
                  getDeclaredField(String name)获得某个属性对象
                  getDeclaredFields()获得所有属性对象
                  ✏️1.4 Method类中的相关方法
                  方法用途
                  getDeclaredMethod((String name, Class… parameterTypes)获得该类某个方法
                  getDeclaredMethods()获得该类的所有方法
                  getMethod((String name, Class… parameterTypes)获得该类某个公有方法
                  getMethods()获得该类所有公有方法
                  invoke(对象名,要修改的参数)触发方法执行的方法
                  ✏️1.5 Constructor类中的相关方法
                  方法用途
                  getConstructor( Class… parameterTypes)获得该类中与参类型匹配的某个公有构造方法
                  getConstructors()获得该类中所有的公有构造方法
                  geDeclaredtConstructor(Class… parameterTypes)获得该类中与参类型匹配的某个构造方法
                  geDeclaredtConstructors()获得该类中所有的构造方法
                  ✏️1.6 获取Class对象的三种方式

                  在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的

                  1. 我们先构造出一个学生类作为演示示例
                  class Student {
                      //私有属性name
                      private String name = "xiaozhuxiaozhu";
                      //公有属性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 +
                                  '}';
                      }
                  }
                  

                  1.使用 Class.forName(“类的全路径名”); 静态方法(前提:已明确类的全路径名。 )。

                  public class test1 {
                      public static void main(String[] args) throws ClassNotFoundException {
                          //通过 Class 对象的 forName() 静态⽅法来获取,⽤的最多,但可能抛出 ClassNotFoundException 异常
                          //注意这⾥是类的全路径,如果有包需要加包的路径
                          Class c1 = Class.forName("reflection.Student");
                      }
                  }
                  
                  1. 使用 .class 方法(仅适合在编译前就已经明确要操作的 Class)。
                  public class test2 {
                      public static void main(String[] args) throws ClassNotFoundException {
                          //直接通过 类名.class 的⽅式得到,该⽅法最为安全可靠,程序性能更⾼
                          Class c2 = Student.class;
                      }
                  }
                  
                  1. 使用类对象的 getClass() 方法
                  public class test3 {
                      public static void main(String[] args) throws ClassNotFoundException {
                          Student s1 = new Student();
                          Class c3 = s1.getClass();
                      }
                  }
                  
                  ✏️1.7 反射的使用

                  接下来我们开始使用反射,我们依旧反射上面的Student类

                  注意:所有和反射相关的包都在 import java.lang.reflect 包下面。

                  package reflection;
                  import java.lang.reflect.Method;
                  import java.lang.reflect.Constructor;
                  import java.lang.reflect.Field;
                  import java.lang.reflect.InvocationTargetException;
                  public class demo_test {
                      public static void main(String[] args) throws ClassNotFoundException, 
                      	InstantiationException,
                       IllegalAccessException, 
                       NoSuchMethodException,
                       SecurityException, 
                       IllegalArgumentException, 
                       InvocationTargetException,
                       NoSuchFieldException {
                          // 获取Class对象
                          Class c1 = Class.forName("reflection.Student");
                          Object newInstance = c1.newInstance();;
                          Student student = (Student)newInstance;
                          System.out.println(student);
                          // 获取构造方法
                          Constructor constructors = c1.getDeclaredConstructor(String.class, int.class);
                          //设置为true后可修改访问权限
                          constructors.setAccessible(true);
                          Object newInstance1 = constructors.newInstance("zhangsan", 20);
                          Student student1 = (Student)newInstance1;
                          System.out.println(student1);
                          // 反射私有⽅法
                          Method method = c1.getDeclaredMethod("function", String.class);
                          //设置为true后可修改访问权限
                          method.setAccessible(true);
                          method.invoke(student1, "hello");
                          // 反射私有属性
                          Field field = c1.getDeclaredField("name");
                          //设置为true后可修改访问权限
                          field.setAccessible(true);
                          field.set(student1, "lisi");
                          System.out.println(student1);
                      }
                  }
                  

                  📕2. 枚举

                  枚举是在JDK1.5以后引⼊的。本质是一个特殊的类,是 java.lang.Enum 的⼦类,⾃⼰写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。枚举的关键字为enum,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。

                  2.1 枚举的定义
                  限定符 enum 枚举名称{
                  	常量1,常量2,常量3....;
                  }
                  
                  ✏️2.2 枚举的使用
                  1. switch语句
                  public enum testenum {
                      RED,BLACK,WHITE;
                      public static void main(String[] args) {
                          testenum t1 = testenum.BLACK;
                          switch (t1) {
                              case RED:
                                  System.out.println("红色");
                                  break;
                              case BLACK:
                                  System.out.println("黑色");
                                  break;
                              case WHITE:
                                  System.out.println("白色");
                                  break;
                              default:
                                  break;
                          }
                      }   
                  }
                  
                  1. 常⽤⽅法
                  方法名称描述
                  values()以数组形式返回枚举类型的所有成员
                  ordinal()获取枚举成员的索引位置
                  valueOf()将普通字符串转换为枚举类型
                  compareTo()比较两个枚举成员在定义时的顺序
                  //将枚举类型的所有成员以数组形式返回并打印
                  testenum[] values = testenum.values();
                  for (int i = 0; i  
                  
                  ✏️2.3 枚举的构造方法

                  💡💡💡💡💡注意:当枚举对象有参数后,需要提供相应的构造函数

                  💡💡💡💡💡注意:枚举的构造函数默认是私有的 这个⼀定要记住

                  public enum testenum {
                      RED("红色",1),BLACK("黑色",2),WHITE("白色",3);
                      private String color;
                      private int key;
                      private testenum(String color,int key){
                          this.color=color;
                          this.key=key;
                      }
                  }
                  
                  ✏️2.4 枚举与反射

                  关于枚举与反射,请记住一个结论:你不能通过反射获取枚举类的实例!

                  这也是问题的答案.至于为什么呢,等我学完单例模式之后在来补充…

                  📕3. Lambda表达式

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

                  ✏️3.1 Lambda表达式语法

                  基本语法: (parameters) -> expression 或(parameters) -> {statement;}

                  Lambda表达式由三部分组成:

                  1. paramaters:类似方法中的形参列表,这⾥的参数是函数式接口里的参数。

                  2. ->:可理解为“被用于”的意思

                  3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么

                  都不反回,这里的代码块块等同于方法的方法体。

                  // 1. 不需要参数,返回值为 2
                  () -> 2
                  // 2. 接收⼀个参数(数字类型),返回其2倍的值
                  x -> 2 * x
                  // 3. 接受2个参数(数字),并返回他们的和
                  (x, y) -> x + y
                  // 4. 接收2个int型整数,返回他们的乘积
                  (int x, int y) -> x * y
                  // 5. 接受⼀个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
                  (String s) -> System.out.print(s)
                  
                  ✏️3.2 函数式接口

                  函数式接口定义:⼀个接口有且只有⼀个抽象方法 。

                  💡💡注意:

                  1. 如果一个接口只有一个抽象方法,那么该接口就是⼀个函数式接口
                  2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
                  @FunctionalInterface
                  interface NoParameterNoReturn {
                  //注意:只能有⼀个⽅法
                  void test();
                  }
                  
                  ✏️3.3 变量捕获
                  @FunctionalInterface
                  interface NoParameterNoReturn {
                  	void test();
                  }
                  public static void main(String[] args) {
                  	int a = 10;
                  	NoParameterNoReturn noParameterNoReturn = ()->{
                  		// a = 99; error
                  		System.out.println("捕获变量:"+a);
                  	};
                  	noParameterNoReturn.test();
                  }
                  
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码