数据结构—(java)反射,枚举,lambda表达式

news2024/11/16 4:18:34

文章目录

  • 反射
    • 反射的定义:
    • 反射相关的类:
    • 反射相关的方法:
    • 反射示例:
      • 获取Class类对象
      • 创建指定类的对象
      • 反射私有属性:
      • 反射私有方法:
      • 反射私有的构造方法
  • 枚举
    • 枚举的意义
    • 枚举类的实现
    • 枚举类的使用:
    • Enum类中常用的四个方法:
    • 枚举与反射:
  • lambda表达式
    • 函数式接口:
    • lambda表达式的语法:
    • lambda表达式的使用:
    • 关于lambda表达式语法精简的问题:
    • java集合类与lambda表达式的使用问题:
  • 变量捕获:


反射

反射的定义:

java的反射机制是指,在程序的运行状态中,对于任意一个类,可以获取这个类的全部信息(包括,类加载器(后面会学到),构造方法,成员属性,成员方法等。)对于任意一个对象,我们也能够调用其属性与方法进行修改信息,这种动态地获取信息与动态地调用对象的机制,我们称为反射机制。

反射相关的类:

在这里插入图片描述

反射相关的方法:

在Class类中即包含了获取类加载器,创建指定类对象,获取构造方法,属性,成员方法的方法,如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

反射示例:

获取Class类对象

此处的Class并不是指表示类名的关键字,而是指Class这个具体的类,
因为Class类的构造方法是私有方法,所以不能够直接实例化对象。
我们需要获取Class类对象有三种方式:
第一种:调用对象的getClass方法

        Student student = new Student();
        //getClass方法也是用c/c++代码实现的
       Class<Student> c1 = (Class<Student>) student.getClass();

第二种:直接调用类名的class属性

 但是我们并没有在Student中定义class属性
    //这说明每一个方法都有一个默认的class属性
   Class c2 = Student.class;

第三种:通过class对象的ForName方法来获取

   Class c3 = null ;
   c3 = Class.forName("reflectDemo.Student");

判断这三个class对象是不是同一个对象。

        System.out.println(c1 ==c2);
        System.out.println(c1==c3);
        System.out.println(c2==c3);

在这里插入图片描述
结果表明,我们通过三种方式创建的三个Class对象实际上是一个,

实际上是因为任何一个类在JVM中只会被加载一次,所以其所对应的Class对象也
只会被创建一次。如果通过两个不同的类来创建Class对象,则这两个Class对象不一样。
    Class c2 = Dog.class;

结果为:此时c2与c1,c3均不相同。
在这里插入图片描述

创建指定类的对象

使用的Student类

public 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 static void reflectNewInstance() throws   ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class c3 = null ;
        c3 =     Class.forName("reflectDemo.Student");
        //要通过c3对象来调用实例化对象的方法
        Student student1 = (Student) c3.newInstance();
        System.out.println(student1);

    }

调用此方法。

 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //通过class对象创建一个学生对象
          reflectNewInstance();
          }

在这里插入图片描述

反射私有属性:

//简写了
public class Student {
      //私有属性name
          private String name = "bit"; //公有属性age
             public int age = 18;

反射私有属性的方法:

public static void reflectPrivateField(){
    Class c3 = null ;
    try {
        c3 =   Class.forName("reflectDemo.Student");
        Field field =  c3.getDeclaredField("name");
        //我们可以修改这个私有属性的值
        field.setAccessible(true);
        //还需要有一个Student对象,
        Student student3 = (Student)c3.newInstance();
        field.set(student3,"张三");
        System.out.println(student3);

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}
  public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        reflectPrivateField();
    }

在这里插入图片描述

反射私有方法:

public class Student {
private void eat(String s){
     System.out.println(s);
     }
  }
public static void reflectPrivateMethod(){
        Class  c4 = null;
    try {
        c4 = Class.forName("reflectDemo.Student");
                                                                                               //在有参数时一定要加上参数类型的class
        Method method = c4.getDeclaredMethod("eat",String.class);
        Student student4 = (Student) c4.newInstance();
        method.setAccessible(true);
        method.invoke(student4, "i am eat");

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}
 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        reflectPrivateMethod();
    }

在这里插入图片描述

反射私有的构造方法

public class Student {
 private Student(String name,int age) {
       this.name = name;
       this.age = age;
        System.out.println("Student(String,name)");
  }
}
 public static void reflectPrivateConstructor(){
        Class c3 = null ;
        try {
            c3 =     Class.forName("reflectDemo.Student");
            //调用getConstructor方法,参数为

            Constructor<Student> constructor =  c3.getDeclaredConstructor(String.class,int.class);
           //在获取了构造方法之后呢?
            constructor.setAccessible(true);
            //直接调用此构造方法,为对象赋值
         Student student2 =    constructor.newInstance("张三",15);
            System.out.println(student2);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
  public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
       reflectPrivateConstructor();
    }

在这里插入图片描述

枚举

枚举的意义

枚举是将一组常量组织起来,即将这一组常量赋予特殊的意义,用特殊的类型表示它们。
所用的场景为:错误状态码,消息类型,颜色的划分,状态机等等…

枚举类的实现

枚举类有自己特定的关键字即enum,
在这里插入图片描述
所有我们自己定义的枚举类均继承于java提供的Enum类。

枚举类的使用:

在类中定义枚举成员:

public enum Myenum {
    //在自定义的枚举类中定义一些成员
   Red,Yellow,Blue,Green;
}

获取枚举成员:

public enum Myenum {
    //在自定义的枚举类中定义一些成员
   Red,Yellow,Blue,Green;

public static void main(String[] args) {
//我们可以通过枚举类名,来直接获取枚举成员,而不需要创建枚举类的对象。
       System.out.println(Myenum.Blue);

    }
}

关于枚举类的构造方法:
在这里插入图片描述
:因为枚举类型的构造方法是私有的,所以不能够在其他类中进行
创建对象,但是在枚举类中也不能够创建枚举类对象,
在这里插入图片描述
枚举类的使用意义并不在于它的对象,而在于它的枚举成员,其枚举成员可以直接通过类名调用。

Enum类中常用的四个方法:

在这里插入图片描述
因为我们定义的枚举类继承于Enum类,所以Enum类中的所有方法均可使用

public static void main(String[] args) {
        //关于枚举类中方法的使用
        //1. values方法,用于获取枚举类中所有的枚举成员。
        //问题:在Enum类中并没有values方法,那么这个方法是从哪里来的?
      Myenum[] myenums = Myenum.values();
        for (Myenum myenum2: myenums) {
            //在获取了每个枚举成员后,开始进行每个枚举成员的索引位
            // 2. 调用ordinal方法
          System.out.println(  myenum2  +" "+myenum2.ordinal());
        }
        // 3.  valueof方法,将普通的字符串转换成枚举实例?
    //    System.out.println(Myenum.valueOf("GREEN"));
       //意思为:如果在枚举类中有此枚举成员,则会返回对应的枚举成员,如果没有则报异常
        System.out.println("Red");
     // 4. 第四个方法:compareTo方法
        //在Enum类中实现了comparable接口,实现了compareTo方法,用于比较两个
        //枚举成员的索引位置。
        System.out.println(Red.compareTo(Blue));
    }

在这里插入图片描述

枚举与反射:

我们不能够通过枚举的构造方法来实例化枚举类对象,那么能否通过反射机制来创建枚举类对象呢?
实际上是不行的。
Enum类中的构造方法:
在这里插入图片描述

public static void main(String[] args)  {
        //尝试通过反射进行实例化enum对象
        Class<?> c1 = null;
        try {
            //要注意当父类的构造方法未调用时,子类的构造方法是不能被调用的
            c1 = Class.forName("enumdemo.Myenum");
            //枚举类不能够通过反射类进行创建。
            //在指定的类的具有父类时,也应该加上父类形参类型的.class属性
             Constructor  constructor=   c1.getDeclaredConstructor(String.class,int.class,int.class,String.class);
             //获取了相应的构造方法后
            constructor.setAccessible(true);

            Myenum myenum = (Myenum) constructor.newInstance(2,"hong");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

运行结果:
在这里插入图片描述

lambda表达式

函数式接口:

如果一个接口中只有一个抽象方法,则此接口称为函数式接口。
lambda表达式可代替函数式接口的实现,直接将lambda表达式赋给接口类型的变量。

lambda表达式的语法:

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

lambda表达式的使用:

interface NoParameterNoReturn{
    //无参且无返回值
      void test();
}
interface OneParameterNoReturn{
    //有一个参数无返回值
    void test(int a);
}
interface MultipleParameterNoReturn{
    //有多个参数无返回值
    void test(int a,int b);
}
interface NoParameterReturn{
    //无参且有返回值
    int test();
}
interface OneParameterReturn{
    //有一个参数有返回值
    int  test(int a);
}
interface MultipleParameterReturn{
    //有多个参数有返回值
    int  test(int a,int b);
}

public static void main(String[] args) {
        //Lambda表达式可用于实现只有一个抽象方法的接口。
       //先实现无返回值无参数的接口
        NoParameterNoReturn noParameterNoReturn1 = new NoParameterNoReturn() {
            @Override
            public void test() {
                System.out.println("调用无返回值无参数方法");
            }
        };
        //直接调用方法
        noParameterNoReturn1.test();
        //我们采用lambda表达式,直接赋给noParameterNoReturns变量
      NoParameterNoReturn noParameterNoReturn2 = ()->{ System.out.println("调用无返回值无参数方法");};
      noParameterNoReturn2.test();

    }

在这里插入图片描述
此两种方式效果相同。

 public static void main(String[] args) {
        //调用一个无参有返回值的方法
        NoParameterReturn noParameterReturn = ()->10;  //可以不写return 关键字,直接写数值或语句
        System.out.println(noParameterReturn.test());

    }

在这里插入图片描述

关于lambda表达式语法精简的问题:

  1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。
  2. 参数的小括号里面只有一个参数,那么小括号可以省略
  3. 如果方法体当中只有一句代码,那么大括号可以省略
  4. 如果方法体中只有一条语句,且是return语句,那么大括号可以省略,且去掉return关键字。

java集合类与lambda表达式的使用问题:

在这里插入图片描述
在这里插入图片描述

public static void main(String[] args) {
        //举例:ArrayList中的forEach语句
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(10);
        arrayList.add(20);
        arrayList.add(15);
        //遍历数组可以用迭代器,foreach语句等,也可以采用arrayList本身的方法
        //accept是接口中的抽象方法,将其重写

        //方法1:直接创建匿名内部类调用。
        arrayList.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        });

      // 方法2:通过lambda表达式
        //当我们这样编写时,代码很简洁,但是可读性比较差。
        arrayList.forEach((a)->{
            System.out.println(a);
        });

    }
 public static void main(String[] args) {
        //举例: List中的sort方法
     ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(10);
        arrayList.add(20);
        arrayList.add(15);
   /* arrayList.sort(new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    });*/
       // System.out.println(arrayList);
        arrayList.sort(((o1, o2) -> {return o1.compareTo(o2);}));
        System.out.println(arrayList);
    }

变量捕获:

    //变量捕获是指在匿名内部类,或lambda表达式中,所使用的变量在此之前与之后不能被修改,或者此变量被final修饰

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2151130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM面试知识点手册

第一部分&#xff1a;JVM 概述 1.1 JVM 简介 Java Virtual Machine&#xff08;JVM&#xff09; 是 Java 语言的核心组件&#xff0c;负责将 Java 程序编译后的字节码&#xff08;bytecode&#xff09;转换为机器指令&#xff0c;并在目标机器上执行。JVM 提供了硬件和操作系…

创客匠人案例故事|闭关 20 天,私域大爆发,高额发售秘诀是什么?

不是你的能力决定了你的命运&#xff0c;而是你的决定改变了你的人生 王龙老师心赏教养法创始人心赏家园家庭“心生态”发起人国家二级心理咨询师 他是一名致力于解决家庭困境的老师&#xff0c;通过心赏转化五步法&#xff0c;帮助身陷家庭困境的父母&#xff0c;解决自我关系…

Linux——k8s认识

计算资源隔离 - 更方便进行高并发架构的维护和升级 - 架构管理的灵活性更高&#xff0c;不再以单个节点的物理资源作为基础 技术&#xff1a; - 硬件辅助虚拟化 - 容器技术 在企业部署方案中&#xff0c;很少以单节点实现虚拟化和容器技术&#xff0c;一般以集群状态来运…

翻唱技巧:AU和Cubase翻唱录制对轨技巧

分享和记录一下个人翻唱的经验和技巧&#xff01;防止后续自己忘了&#xff01;同时如果有大佬看到&#xff0c;希望可以帮我指出其中的错误&#xff01;个人推荐用Cubase12录制翻唱&#xff0c;因为Cubase12可以做乐段的标记&#xff0c;翻唱时有助于学习一些歌曲的层次设计。…

C++对象拷贝时的优化编译

在现代编译器中&#xff0c;当我们在 C中进行对象的拷贝操作时&#xff0c;编译器并非只是机械地执行逐字节的复制。相反&#xff0c;它会进行优化&#xff0c;避免不必要的拷贝构造等等&#xff0c;这种优化包括“返回值优化”&#xff08;RVO&#xff09;&#xff0c;“拷贝省…

JavaSE——String类

一、字符串构造 注意&#xff1a;String是引用类型&#xff0c;内部并不存储字符串本身。 有三种方式&#xff1a; public class Test1 {public static void main(String[] args) {// 使用常量串构造String s1 "hello java";System.out.println(s1);// 直接newSt…

JavaEE:探索网络世界的魅力——玩转UDP编程

文章目录 UDPUDP的特点UDP协议端格式校验和前置知识校验和具体是如何工作的? UDP UDP的特点 UDP传输的过程类似于寄信. 无连接: 知道对端的IP和端口号就直接进行传输,不需要建立连接.不可靠: 没有确认机制,没有重传机制,如果因为网络故障导致该段无法到达对方,UDP协议也不会…

Linux:make,Makefile

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《Linux&#xff1a;make&#xff0c;Makefile》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞&…

技术成神之路:设计模式(十四)享元模式

介绍 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构性设计模式&#xff0c;旨在通过共享对象来有效地支持大量细粒度的对象。 1.定义 享元模式通过将对象状态分为内部状态&#xff08;可以共享&#xff09;和外部状态&#xff08;不可共享&#xff09;&#xf…

为什么我不建议你考CCNA/HCIA这种初级认证

CCNA和HCIA&#xff0c;这两个证书可能是许多刚入门的网络工程师第一个听说的认证。作为入门级网络认证&#xff0c;CCNA是思科公司推出的&#xff0c;提供了网络基础的全面知识&#xff0c;而HCIA则是华为的基础认证&#xff0c;覆盖了网络技术的基本原理。 这些认证的目的是帮…

2023-03 GESP Python一级试卷

一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 1.以下不属于计算机输入设备的有&#xff08; &#xff09;。 ​ A&#xff0e;键盘 ​ B&#xff0e;音箱 ​ C&#xff0e;鼠标 ​ D&#xff0e;传感器 2.计算机系统中存储的基本单位用 B 来表示&am…

用友U8二次开发工具KK-FULL-*****-EFWeb使用方法

1、安装: 下一步&#xff0c;下一步即可。弹出黑框不要关闭&#xff0c;让其自动执行并关闭。 2、服务配置&#xff1a; 输入服务器IP地址&#xff0c;选择U8数据源&#xff0c;输入U8用户名及账号&#xff0c;U8登录日期勾选系统日期。测试参数有效性&#xff0c;提示测试通过…

洞悉市场先机,Vatee万腾平台助力企业精准决策

在瞬息万变的商业环境中&#xff0c;每一个市场动向都可能成为企业兴衰的关键。因此&#xff0c;洞悉市场先机&#xff0c;做出精准决策&#xff0c;成为了企业持续发展和保持竞争力的核心要素。Vatee万腾平台&#xff0c;凭借其强大的数据分析能力和智能化技术&#xff0c;正成…

对象检测边界框损失 – 从IOU到ProbIOU

1.概述 目标检测损失函数的选择在目标检测问题建模中至关重要。通常&#xff0c;目标检测需要两个损失函数&#xff0c;一个用于对象分类&#xff0c;另一个用于边界框回归&#xff08;BBR&#xff09;。本文将重点介绍 IoU 损失函数&#xff08;GIoU 损失、DIoU 损失和 CIoU 损…

【补码运算】设x=FEH,当x分别为下列情况时写出其对应的十进制真值(写出计算过程):(1)为原码(2)为补码。

欢迎来到我的技术博客&#xff01; &#x1f389; 这里不仅有满满的编程干货和学习资源&#xff0c;我的某站账号也为你准备了更多实用的技术视频和知识分享。 &#x1f449; 点击关注我的小破站账号&#xff0c;获取更多编程技巧和学习资源&#xff01; 小破站主页 题目&…

搜索引擎onesearch3实现解释和升级到Elasticsearch v8系列(三)-文档

文档 文档服务负责写入&#xff0c;包括批量&#xff1b;id获取文档&#xff1b;nested写入 写入文档 写入文档主要是构建IndexRequest&#xff0c;索引请求 Elasticsearch v8构建文档索引请求简单很多&#xff0c;可以直接接受Map数据 批量写入文档 批量操作可以融合增删改…

肥胖成因:饮食之外,消耗吸收慢是关键因素

肥胖问题一直被现代社会所关注&#xff0c;不可否认&#xff0c;饮食是影响胖瘦的重要因素之一。高热量、高油脂的食物摄入过多&#xff0c;也确实会导致热量油脂过剩&#xff0c;堆积储存进身体内进而养肥身体。可在正常情况中&#xff0c;就算是消耗吸收率一般的人&#xff0…

从源码看透 Ptmalloc:堆内存分配与释放的背后

&#x1f6f8;0. 前言 内存管理是个很复杂的东西&#xff0c;一般的程序员在写应用层代码的时候根本就不会关注内存的使用&#xff0c;尤其是 GC 语言自带垃圾回收机制&#xff0c;很多同学都使用过 C 语言中的 malloc&#xff0c;但很少有人能知道 malloc 其实是个很复杂的实现…

tomcat服务搭建部署ujcms网站

tomcat服务搭建部署ujcms网站 关闭selinux和防火墙 setenforce 0 && systemctl stop firewalld安装java环境 #卸载原有java8环境 yum remove java*#上传java软件包&#xff0c;并解压缩 tar -xf openjdk-11.0.1_linux-x64_bin.tar.gz && mv jdk-11.0.1 jdk11…

Android Perfetto 学习

1、如何抓取性能日志 方式1、通过手机里的System Tracing抓取 1、点击Settings->System->Developer options->System Tracing->Record trace 打开 2、操作完成后&#xff0c;点击Settings->System->Developer options->System Tracing->Record trace…