Java的反射机制、Lambda表达式和枚举
Java的反射机制、Lambda表达式和枚举
文章目录
- Java的反射机制、Lambda表达式和枚举
- 1.反射机制
- 反射的概念、用途、优缺点
- 反射相关的类及使用(重要!!)
- 相关类
- Class类:代表类实体,表示类和接口
- Field类:代表类的成员变量/类的属性
- Method类:代表类的方法
- Constructor类:代表类的构造方法
- 获取类中注解相关的方法(了解)
- 使用
- 获取Class对象的三种方式
- 例子
- 通过反射创建对象
- 反射私有构造方法创建对象
- 反射私有属性
- 反射私有方法
- 2.Lambda表达式
- Lambda是什么、语法
- 基本使用
- 用途1:变量捕获
- 匿名内部类变量捕获
- Lambda表达式变量捕获
- 用途2:在集合中的使用
- Collection接口
- List接口
- Map接口
- 3.枚举
- 枚举简介、优缺点
- 枚举的构造方法
- 创建与使用
- 枚举与反射
1.反射机制
反射的概念、用途、优缺点
Java的反射机制就是在运行状态中,对于任意一个类都能知道它所有属性和方法,对于任意一个对象都能调用它的任意方法和属性,并进行部分类型信息的修改,这种动态获取信息以及动态调用对象方法的功能叫做Java的反射机制。
Java程序中很多对象在运行时会出现两种基本类型:运行时类型(RTTI)和编译时类型。
例如Person p=new Student(),这句代码中p在编译时就是Person,运行时就是Student,程序需要再运行时发现对象和类的真实信息,通过反射就可以判断出这个对象和类属于哪些类。
-
在日常的第三方应用开发过程中,可以利用Java的反射机制通过反射来获取所需要的私有成员或者方法(比较常见)
-
最重要的用途就是开发各种框架。
例如,在spring中,我们把所有的类Bean交给spring容器管理,不管是xml配置还是注解配置Bean,当我们从容器中获取Bean来依赖注入时,容器就读取配置,而配置中给的就是类的信息,spring根据这些信息,动态的创建Bean
优点:
- 对于任意类都能知道它的属性和方法,对于任意对象都能调用它的任意方法
- 可以增加程序的灵活性和扩展性
- 已经运用在很多流行的框架如spring中
缺点:
- 会有效率问题,导致程序效率降低
- 代码可能比较复杂
反射相关的类及使用(重要!!)
在Java中,实现反射都要依赖于Class类。
这是因为,Java文件被编译后,生成.class文件,JVM需要去解读.class文件,被编译后的Java文件.class也被JVM解析成一个对象,这个对象就是java.lang.Class。
这样当程序运行时,每个Java文件最终都变成了Class类对象的一个实例。
因此,将反射机制应用到这个实例上时,就可以获取或添加改变这个类的属性和方法时,这个类就会成为一个动态的类。
注意:所有和反射相关的包都在 import java.lang.reflect 包下面
相关类
所有的这些类都是加了declared能够访问的范围是更大的。
Class类:代表类实体,表示类和接口
| 方法 | 用途 |
|---|---|
| getClassLoader() | 获取类的加载器 |
| getDeclaredClasser() | 返回一个数组,数组中包含这个类中所有的类和接口类的对象 |
| forName(String className) | 根据类名返回类的对象 |
| newInstance | 创建类的实例 |
| getName() | 获取类的完整路径名字 |
Field类:代表类的成员变量/类的属性
| 方法 | 用途 |
|---|---|
| getField(String name) | 获取某个公有的属性对象 |
| getFields() | 获取所有公有的属性对象 |
| getDeclaredField(String name) | 获取某个属性对象 |
| getDeclaredFields() | 获取所有属性对象 |
Method类:代表类的方法
| 方法 | 用途 |
|---|---|
| getMethod(String name,Class…<?> parameterTypes) | 获取该类某个公有的方法 |
| getMethods() | 获取该类所有公有的方法 |
| getDeclaredMethod(String name,Class…<?> parameterTypes) | 获取该类某个方法 |
| getDeclaredMethods() | 获取该类所有方法 |
Constructor类:代表类的构造方法
| 方法 | 用途 |
|---|---|
| getConstructor(Class…<?> parameterTypes) | 获取该类中与参数类型匹配的公有构造方法 |
| getConstructors() | 获取该类中所有公有构造方法 |
| getDeclaredConstructor(Class…<?> parameterTypes) | 获取该类中与参数类型匹配的构造方法 |
| getDeclaredConstructors() | 获取该类所有构造方法 |
获取类中注解相关的方法(了解)
| 方法 | 用途 |
|---|---|
| getAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的公有注解对象 |
| getAnnotations() | 返回该类中所有公有注解对象 |
| getDeclaredAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的所有注解对象 |
| getDeclaredAnnotations() | 返回该类中所有的注解对象 |
使用
在进行反射之前,需要做的第一步就是拿到当前需要反射的类的Class对象,然后根据Class对象的核心方法,达到反射的目的(获取或修改相关信息)。
获取Class对象的三种方式
第一种:使用Class.forName(“类的全路径名”);【使用的比较多的】
第二种:使用.class方法(适合在编译时就已经明确要操作的Class)
第三种:使用类对象的getClass()方法
class Student{//私有属性nameprivate String name = "school";//公有属性agepublic 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 eating");}//公开不带参public void sleep(){System.out.println("i am sleeping");}//私有带参private void function(String str) {System.out.println(str);}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
public class Reflect {public static void main(String[] args) throws ClassNotFoundException {Student student=new Student();//获取Class对象的三种方法//1.通过getClass方法Class<?> c1=student.getClass();//2.通过类名.class获取Class<?> c2=Student.class;//3.通过Class.forName(全路径)[需要处理异常——自己处理or交给JVM处理]Class<?> c3=Class.forName("Student");//在当前类System.out.println(c1.equals(c2));System.out.println(c1.equals(c3));System.out.println(c3.equals(c2));}
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L1k8pGSJ-1692022990152)(F:\typora插图\image-20230814163231771.png)]](https://img-blog.csdnimg.cn/59c9d481171f46dca632554ef1918ab0.png)
例子
通过反射创建对象
public static void reflectNewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException {Class<?> c3 = Class.forName("Student");Student student = (Student) c3.newInstance();System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象reflectNewInstance();}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5bQEkcyf-1692022990153)(F:\typora插图\image-20230814185543613.png)]](https://img-blog.csdnimg.cn/d26cb1a1c36d44568512bdda19bbe01e.png)
反射私有构造方法创建对象
//反射私有的构造方法public static void reflectPrivateConstructor() {try {Class<?> c3=Class.forName("Student");Constructor<?> constructor=c3.getDeclaredConstructor(String.class,int.class);//设置为true之后可以修改访问权限constructor.setAccessible(true);Student student=(Student) constructor.newInstance("zhangsan",17);System.out.println(student);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}}//反射私有属性public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
// reflectNewInstance();//通过反射得到私有构造方法创建对象reflectPrivateConstructor();}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VPH9W8nv-1692022990153)(F:\typora插图\image-20230814185524760.png)]](https://img-blog.csdnimg.cn/1b51d37011ad4824b97e2960b8ba7b84.png)
反射私有属性
//反射私有属性public static void reflectPrivateField(){try {Class<?> c3=Class.forName("Student");Field field=c3.getDeclaredField("name");field.setAccessible(true);//修改属性的访问权限Object objectStudent=c3.newInstance();Student student=(Student)objectStudent;field.set(student,"张三");String name=(String)field.get(student);System.out.println("反射私有属性修改名字为:"+name);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchFieldException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
// reflectNewInstance();//通过反射得到私有构造方法创建对象
// reflectPrivateConstructor();//反射私有属性reflectPrivateField();}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y0bNue4Y-1692022990154)(F:\typora插图\image-20230814185447879.png)]](https://img-blog.csdnimg.cn/e03783c11ca6419c8cb4582e5471e236.png)
反射私有方法
//反射私有方法public static void reflectPrivateMethod(){try {Class<?> c3=Class.forName("Student");Method method= c3.getDeclaredMethod("function",String.class);method.setAccessible(true);Object object=c3.newInstance();Student student=(Student) object;method.invoke(student,"给私有function函数传的参数");} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
// reflectNewInstance();//通过反射得到私有构造方法创建对象
// reflectPrivateConstructor();//反射私有属性
// reflectPrivateField();//反射私有方法reflectPrivateMethod();}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bEQRVbm2-1692022990155)(F:\typora插图\image-20230814185425769.png)]](https://img-blog.csdnimg.cn/32d4ba56645048f5820b1330230ef466.png)
2.Lambda表达式
相当于只有一个抽象方法的接口的简化。
Lambda是什么、语法
它是JavaSE8中的一个新的特性,Lambda表达式允许我们通过表达式代替功能接口。Lambda 表达式(Lambda expression),基于数学中的λ演算得名,也可称为闭包(Closure)。
基本语法: **(parameters) -> expression** 或 **(parameters) ->{ statements; }**
parameters:就是函数式接口里的形参列表。这里的参数类型可以明确的生命也可以由JVM隐含判断。当只有一个推断类型时可以省略圆括号。
->:被用于的意思
方法体:可以是表达式也可以是代码块,是函数式接口方法的实现,可返回可不返回
// 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)
函数式接口:一个接口有且只有一个抽象方法
如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。
定义方法:
@FunctionalInterface interface NoParameterNoReturn {//注意:只能有一个方法void test(); }@FunctionalInterface interface NoParameterNoReturn {void test();default void test2() {System.out.println("JDK1.8新特性,default默认方法可以有具体的实现");} }
基本使用
@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 LambdaDemo {public static void main(String[] args) {//匿名内部类,重写了实现接口的方法NoParameterNoReturn noParameterNoReturn=new NoParameterNoReturn(){@Overridepublic void test() {System.out.println("无参无返回值");}};noParameterNoReturn.test();NoParameterNoReturn noParameterNoReturn1=()->{System.out.println("L:无参无返回值");};noParameterNoReturn1.test();OneParameterNoReturn oneParameterNoReturn=new OneParameterNoReturn() {@Overridepublic void test(int a) {System.out.println("一参无返回值");}};oneParameterNoReturn.test(1);OneParameterNoReturn oneParameterNoReturn1= (x)->{System.out.println("L:一参无返回值");};oneParameterNoReturn1.test(1);MoreParameterNoReturn moreParameterNoReturn=new MoreParameterNoReturn() {@Overridepublic void test(int a,int b) {System.out.println("多参无返回值");}};moreParameterNoReturn.test(1,2);MoreParameterNoReturn moreParameterNoReturn1=(x,y)->{System.out.println("L:多参无返回值");};moreParameterNoReturn1.test(1,2);//匿名内部类,重写了实现接口的方法NoParameterReturn noParameterReturn=new NoParameterReturn(){@Overridepublic int test() {System.out.println("无参有返回值");return 0;}};noParameterReturn.test();NoParameterReturn noParameterReturn1=()->{System.out.println("L:无参有返回值");return 0;};noParameterNoReturn1.test();OneParameterReturn oneParameterReturn=new OneParameterReturn() {@Overridepublic int test(int a) {System.out.println("一参有返回值");return 0;}};oneParameterNoReturn.test(1);OneParameterReturn oneParameterReturn1= (x)->{System.out.println("L:一参有返回值");return x;};oneParameterNoReturn1.test(1);MoreParameterReturn moreParameterReturn=new MoreParameterReturn() {@Overridepublic int test(int a,int b) {System.out.println("多参有返回值");return a+b;}};moreParameterReturn.test(1,2);MoreParameterReturn moreParameterReturn1=(x,y)->{System.out.println("L:多参有返回值");return x+y;};moreParameterNoReturn1.test(1,2);}
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MamGMkbA-1692022990156)(F:\typora插图\image-20230814211545477.png)]](https://img-blog.csdnimg.cn/738d8292fe2a484ba43629b9f3b207ba.png)
用途1:变量捕获
变量捕获可以使我们更好的理解Lambda表达式的作用域,Java中的匿名内部类和Lambda表达式会存在变量捕获。
匿名内部类变量捕获
@FunctionalInterface
interface Test{void test();
}
public class LambdaDemo2 {//匿名内部类变量捕获public static void test01() {int a=100;final int b=10;
// int c=100;
// c=20;Test t=new Test(){@Overridepublic void test() {System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+a);System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+b);
// System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+c);}};t.test();}public static void main(String[] args) {test01();}
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qf6me7pW-1692022990156)(F:\typora插图\image-20230814212621312.png)]](https://img-blog.csdnimg.cn/f2abba84038040a7b15c0296a7542eda.png)
可以被捕获的只能是常量或者没有被修改过的常量,否则就会直接报错:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YbB6npMV-1692022990157)(F:\typora插图\image-20230814212507835.png)]](https://img-blog.csdnimg.cn/fa7e1be6db5345fdafd14850934a04d9.png)
Lambda表达式变量捕获
@FunctionalInterface
interface Test{void test();
}
public class LambdaDemo2 {//匿名内部类变量捕获public static void test01() {int a=100;final int b=10;
// int c=100;
// c=20;Test t=new Test(){@Overridepublic void test() {System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+a);System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+b);
// System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+c);}};t.test();}//Lambda表达式的变量捕获public static void test02() {int a=100;final int b=10;Test t=()->{System.out.println("L的变量捕获:(常量或者没有被改变过值的变量)"+a);System.out.println("L的变量捕获:(常量或者没有被改变过值的变量)"+b);};t.test();}public static void main(String[] args) {
// test01();test02();}
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A25c1hwX-1692022990158)(F:\typora插图\image-20230814213242215.png)]](https://img-blog.csdnimg.cn/41ddfbca50bf4cddbda184a2fd66f4c4.png)
用途2:在集合中的使用
Collection接口
以实现Collection接口方法(实现了Iterable接口)的forEach方法为例
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;public class LambdaDemo3 {public static void main(String[] args) {ArrayList<Integer> list=new ArrayList<>();list.add(1);list.add(19);list.add(17);list.add(16);list.add(12);list.add(12);//使用foreach迭代器System.out.println("迭代器:");for (int x:list) {System.out.print(x+" ");}System.out.println();//使用匿名内部类方式System.out.println("匿名内部类:");list.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.print(integer+" ");}});System.out.println();System.out.println("Lambda表达式:");//使用Lambda表达式方式list.forEach((i)->{System.out.print(i+" ");});}
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BB0YzdBe-1692022990158)(F:\typora插图\image-20230814214622693.png)]](https://img-blog.csdnimg.cn/371243cd433f4b15bc73446d22292e80.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3maQJlms-1692022990159)(F:\typora插图\image-20230814220253812.png)]](https://img-blog.csdnimg.cn/ef5a00624ce44f439779fcceee13760c.png)
List接口
以sort方法为例:
//sort方法
list.sort((a,b)->{return b-a;});//修改排序规则为降序排序
System.out.println(list);
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GdbrR2ok-1692022990159)(F:\typora插图\image-20230814222111073.png)]](https://img-blog.csdnimg.cn/c0dad0186b1f46d1bab8a92a746d19d2.png)
Map接口
import java.util.HashMap;
import java.util.function.BiConsumer;public class LambdaDemo4 {public static void main(String[] args) {//Map接口的forEach方法HashMap<Integer,String> map=new HashMap<>();map.put(1,"张三");map.put(2,"李四");map.put(3,"王五");//匿名内部类map.forEach(new BiConsumer<Integer, String>() {@Overridepublic void accept(Integer integer, String s) {System.out.println(integer+":"+s);}});//Lambda表达式map.forEach((integer,s)->{System.out.println("L:"+integer+":"+s);});}
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n4pi9BTf-1692022990160)(F:\typora插图\image-20230814221619947.png)]](https://img-blog.csdnimg.cn/7b10b14baed14bc6957c828f7b261fed.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOH0EkpR-1692022990160)(F:\typora插图\image-20230814222003571.png)]](https://img-blog.csdnimg.cn/9176d1b45d644bef9ba1124fbb748414.png)
3.枚举
枚举简介、优缺点
它是在JDK1.5之后引入的,主要用来将常量组织起来。通常应用在错误状态码,消息类型,颜色划分和状态机上等等。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5cmNChqD-1692022990160)(F:\typora插图\image-20230814190715860.png)]](https://img-blog.csdnimg.cn/d67676ccfce84a9e92cca285d6edfc5a.png)
定义好的是枚举对象。
枚举类型实际上是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。
优点:
- 枚举常量更安全简单
- 枚举具有内置方法,更优雅
缺点:
- 没法继承,不能被实例化【原因就是它构造方法是私有的】,不可扩展
枚举的构造方法
默认是私有的,也只能是私有的,不能被继承,并且只能在定义枚举对象的时候被调用。
public enum TestEnum {RED,BLACK,WHITE,BLUE("BLUE",4),PINK;TestEnum(){}private String color;private int ri;TestEnum(String color,int ri){this.color=color;this.ri=ri;}
}
创建与使用
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VlSmSsUO-1692022990161)(F:\typora插图\image-20230814191135595.png)]](https://img-blog.csdnimg.cn/f6bfcd7e129f46e08e7a115ca438aa03.png)
public enum TestEnum {RED,BLACK,WHITE;public static void main(String[] args) {test01();test02();test03();}//测试枚举的switch用法public static void test01() {TestEnum testEnum = TestEnum.BLACK;switch(testEnum){case RED:System.out.println("red");break;case BLACK:System.out.println("black");break;case WHITE:System.out.println("white");break;default:System.out.println("没有当前颜色");break;}}//以数组形式返回枚举类型的所有成员public static void test02() {TestEnum[] testEnum=TestEnum.values();for (int i = 0; i < testEnum.length; i++) {System.out.println("testEnum[i]:"+testEnum[i]);}}public static void test03(){//将普通字符串转换成枚举实例
// TestEnum testEnum=TestEnum.valueOf("GREEN");//需要是已经定义的,否则报错 No enum constant TestEnum.GREENTestEnum testEnum=TestEnum.valueOf("RED");System.out.println(testEnum);//获取枚举成员的索引位置int index=TestEnum.BLACK.ordinal();System.out.println("BLACK:"+index);//比较两个枚举成员在定义时的顺序,默认拿序号比较System.out.println(BLACK.compareTo(RED));}}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O9jTvwqk-1692022990161)(F:\typora插图\image-20230814193300309.png)]](https://img-blog.csdnimg.cn/bbc3416c00b340eba6cd5738699132e4.png)
枚举与反射
能不能通过反射创建枚举实例?
不能!!看源码分析:
//反射枚举 私有的构造方法public static void reflectEnumPrivateConstructor() throws Exception {Class<?> c3=Class.forName("TestEnum");Constructor<?> constructor=c3.getDeclaredConstructor(String.class,int.class);//设置为true之后可以修改访问权限constructor.setAccessible(true);TestEnum testEnum=(TestEnum) constructor.newInstance("GREY",10);System.out.println(testEnum);}public static void main(String[] args) throws Exception {//通过反射创建对象
// reflectNewInstance();//通过反射得到私有构造方法创建对象
// reflectPrivateConstructor();//反射私有属性
// reflectPrivateField();//反射私有方法
// reflectPrivateMethod();//反射枚举类型私有方法reflectEnumPrivateConstructor();}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sGdNuURh-1692022990162)(F:\typora插图\image-20230814195547404.png)]](https://img-blog.csdnimg.cn/a43e0c79c8ce492396650d5d53f6080d.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JeoUgxSk-1692022990162)(F:\typora插图\image-20230814203135715.png)]](https://img-blog.csdnimg.cn/0c4b9337677d424c9ef086395970e132.png)
通过查看源码我们发现,枚举在这里被过滤了。
总的来说,因为枚举的构造方法是私有的,所以不能实例化,另外反射拿到的类对象再去new实例的时候会因为枚举类型被过滤掉,所以枚举实现的单例模式是安全的。
所以枚举具有构造方法默认是私有的,并且都是默认继承java.lang.Enum这个类,可以避免反射和序列化问题,枚举常量更安全更简单,代码更加优雅。
相关文章:
Java的反射机制、Lambda表达式和枚举
Java的反射机制、Lambda表达式和枚举 文章目录 Java的反射机制、Lambda表达式和枚举1.反射机制反射的概念、用途、优缺点反射相关的类及使用(重要!!)相关类Class类:代表类实体,表示类和接口Field类…...
数据结构:堆的实现
1.堆的概念 如果有一个关键码的集合 K { k1 ,k2 ,k3 ,…,kn },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并且 k(i) < k(i*21) 和 k(i) < k(i*22), i 0 ÿ…...
zabbix-6.4 监控 MySQL
目录 1、rpm安装zabbix_agentd服务 2、编写zabbix_agentd.conf文件 3、编写模板文件 4、创建mysql用户并赋权限 5、创建.my.cnf文件 6、将规则添加到SELinux策略中 注意: 若模板无法读取.my.cnf 信息,从而导致监控报错,可以尝试修改模…...
深入探索:解读创意的力量——idea的下载、初步使用
目录 编辑 1.IDEA的简介 2.IDEA的下载 2.1下载路径https://www.jetbrains.com/zh-cn/idea/download/?sectionwindows编辑 2.2下载的步骤 3 idea的初步使用 3.1新建一个简单的Java项目 3.1.1首先需要创建一个新的工程 3.1.2创建一个新的项目(模块&am…...
Redis详解
Redis 简介 Redis(Remote Dictionary Server)是一个开源的高性能键值对存储数据库,最初由 Salvatore Sanfilippo 开发,它在内存中存储数据,并提供了持久化功能,可以将数据保存到磁盘中,是一种N…...
【Linux】高级IO
目录 IO的基本概念 钓鱼五人组 五种IO模型 高级IO重要概念 同步通信 VS 异步通信 阻塞 VS 非阻塞 其他高级IO 阻塞IO 非阻塞IO IO的基本概念 什么是IO? I/O(input/output)也就是输入和输出,在著名的冯诺依曼体系结构当中…...
动态HTTP代理与竞争情报收集的关联
Hey,各位爬友们!作为一名专业的爬虫HTTP代理提供者,今天我要和大家聊一聊动态HTTP代理与竞争情报收集之间的关联。在这篇文章中,我将向大家解释怎么使用动态HTTP代理完成在竞争中的情报收集,并分享一些实用的技巧。 首…...
kafka基本概念及操作
kafka介绍 Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的 (replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各…...
分享个试卷去笔迹什么软件,几个步骤轻松擦除
试卷擦去笔迹是一项非常关键的技能,它可以帮助你更好地管理你的笔记和文件。不管是小伙伴们想重新测试试卷或者是将试卷输出为电子版,都可以实现的。在这篇文章中,我将分享一些方法和软件,帮助你更好地进行试卷擦除。有需要的小伙…...
ClickHouse(十八):Clickhouse Integration系列表引擎
进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容! 🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…...
日常BUG——代码提交到了本地但是没有push,删除了本地分支如何恢复
😜作 者:是江迪呀✒️本文关键词:日常BUG、BUG、问题分析☀️每日 一言 :存在错误说明你在进步! 一、问题描述 代码在本地提交了,但是没有push到远程,然后删除了本地的分支。想要恢…...
Markdown语法
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Markdown语法目录 前言1.标题2.文本样式3.列表四.图片5.链接6.目录7.代码片7.表格8.注脚9.注释10.自定义列表11.LaTeX数学公式12.插入甘特图13.插入UML图14.插入Merimaid流程…...
vue3表格,编辑案例
index.vue <script setup> import { onMounted, ref } from "vue"; import Edit from "./components/Edit.vue"; import axios from "axios";// TODO: 列表渲染 const list ref([]); const getList async () > {const res await ax…...
SQL Server Reporting Services 报错:报表服务器无法访问服务帐户的私钥
解决这个问题,有小伙伴提到可以使用命令 exec DeleteEncryptedContent 但这对这边的环境时行不通的,我在【服务账户】的配置和【数据库】的配置中到使用了域账户,试了几次都不行。改成使用内置账户就好了。具体原因还没扒拉(欢迎…...
QT报表Limereport v1.5.35编译及使用
1、编译说明 下载后QT CREATER中打开limereport.pro然后直接编译就可以了。编译后结果如下图: 一次编译可以得到库文件和DEMO执行程序。 2、使用说明 拷贝如下图编译后的lib目录到自己的工程目录中。 release版本的重新命名为librelease. PRO文件中配置 QT …...
互联网发展历程:从中继器口不够到集线器的引入
互联网的发展,就像一场不断演进的技术盛宴,每一步的变革都在推动着我们的世界向前。然而,在网络的早期,一项重要的技术问题曾困扰着人们:当中继器的接口数量不足时,如何连接更多的设备?这时&…...
vue+flask基于知识图谱的抑郁症问答系统
vueflask基于知识图谱的抑郁症问答系统 抑郁症已经成为当今社会刻不容缓需要解决的问题,抑郁症的危害主要有以下几种:1.可导致病人情绪低落:抑郁症的病人长期处于悲观的状态中,感觉不到快乐,总是高兴不起来。2.可导致工…...
操作格子---算法集
问题描述 有 n 个格子,从左到右放成一排,编号为 1-n。 共有 m 次操作,有 3 种操作类型: 1.修改一个格子的权值。 2.求连续一段格子权值和。 3.求连续一段格子的最大值。 对于每个 2、3 操作输出你所求出的结果。 输入格式 第一行 …...
科研绘图chapter1:绘图原则与配色基础
本系列会持续更新,主要参考datawhale的开源课程。详见: https://github.com/datawhalechina/paper-chart-tutorial 文章目录 1.1 科研论文配图的绘制基础1.2 科研论文配图的配色基础1.2.1 配色模式1.2.2 色环配色原则1.3 配色工具/网站 1.1 科研论文配图…...
Linux下grep通配容易混淆的地方
先上一张图: 我希望找到某个版本为8的一个libXXX.8XXX.so ,那么应该怎么写呢? 先看这种写法对不对: 是不是结果出乎你的意料之外? 那么我们来看一下规则: 这里的 "*" 表示匹配前一个字符的零个或多个 于是我们就不难理解了: lib*8*.so 表示 包…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
