Java的反射机制、Lambda表达式和枚举

news2024/10/7 17:32:41

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,程序需要再运行时发现对象和类的真实信息,通过反射就可以判断出这个对象和类属于哪些类。

  1. 在日常的第三方应用开发过程中,可以利用Java的反射机制通过反射来获取所需要的私有成员或者方法(比较常见)

  2. 最重要的用途就是开发各种框架。

    例如,在spring中,我们把所有的类Bean交给spring容器管理,不管是xml配置还是注解配置Bean,当我们从容器中获取Bean来依赖注入时,容器就读取配置,而配置中给的就是类的信息,spring根据这些信息,动态的创建Bean

优点:

  1. 对于任意类都能知道它的属性和方法,对于任意对象都能调用它的任意方法
  2. 可以增加程序的灵活性和扩展性
  3. 已经运用在很多流行的框架如spring中

缺点:

  1. 会有效率问题,导致程序效率降低
  2. 代码可能比较复杂

反射相关的类及使用(重要!!)

在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{
    //私有属性name
    private String name = "school";
    //公有属性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 eating");
    }
    //公开不带参
    public void sleep(){
        System.out.println("i am sleeping");
    }
    //私有带参
    private void function(String str) {
        System.out.println(str);
    }

    @Override
    public 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)]

例子
通过反射创建对象
    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)]

反射私有构造方法创建对象
    //反射私有的构造方法
    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)]

反射私有属性
    //反射私有属性
    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)]

反射私有方法
    //反射私有方法
    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)]

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(){

            @Override
            public void test() {
                System.out.println("无参无返回值");
            }
        };
        noParameterNoReturn.test();

        NoParameterNoReturn noParameterNoReturn1=()->{
            System.out.println("L:无参无返回值");
        };
        noParameterNoReturn1.test();

        OneParameterNoReturn oneParameterNoReturn=new OneParameterNoReturn() {
            @Override
            public void test(int a) {
                System.out.println("一参无返回值");
            }
        };
        oneParameterNoReturn.test(1);

        OneParameterNoReturn oneParameterNoReturn1= (x)->{System.out.println("L:一参无返回值");};
        oneParameterNoReturn1.test(1);

        MoreParameterNoReturn moreParameterNoReturn=new MoreParameterNoReturn() {
            @Override
            public 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(){

            @Override
            public int test() {
                System.out.println("无参有返回值");
                return 0;
            }
        };
        noParameterReturn.test();

        NoParameterReturn noParameterReturn1=()->{
            System.out.println("L:无参有返回值");
            return 0;
        };
        noParameterNoReturn1.test();

        OneParameterReturn oneParameterReturn=new OneParameterReturn() {
            @Override
            public 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() {
            @Override
            public 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)]

用途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(){
            @Override
            public 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)]

可以被捕获的只能是常量或者没有被修改过的常量,否则就会直接报错:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YbB6npMV-1692022990157)(F:\typora插图\image-20230814212507835.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(){
            @Override
            public 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)]

用途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>() {
            @Override
            public 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)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3maQJlms-1692022990159)(F:\typora插图\image-20230814220253812.png)]

List接口

以sort方法为例:

//sort方法
list.sort((a,b)->{return b-a;});//修改排序规则为降序排序
System.out.println(list);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GdbrR2ok-1692022990159)(F:\typora插图\image-20230814222111073.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>() {
            @Override
            public 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)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOH0EkpR-1692022990160)(F:\typora插图\image-20230814222003571.png)]

3.枚举

枚举简介、优缺点

它是在JDK1.5之后引入的,主要用来将常量组织起来。通常应用在错误状态码,消息类型,颜色划分和状态机上等等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5cmNChqD-1692022990160)(F:\typora插图\image-20230814190715860.png)]

定义好的是枚举对象。

枚举类型实际上是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。

优点:

  1. 枚举常量更安全简单
  2. 枚举具有内置方法,更优雅

缺点:

  1. 没法继承,不能被实例化【原因就是它构造方法是私有的】,不可扩展

枚举的构造方法

默认是私有的,也只能是私有的,不能被继承,并且只能在定义枚举对象的时候被调用。

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)]

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.GREEN
        TestEnum 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)]

枚举与反射

能不能通过反射创建枚举实例?

不能!!看源码分析:

    //反射枚举 私有的构造方法
    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)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JeoUgxSk-1692022990162)(F:\typora插图\image-20230814203135715.png)]

通过查看源码我们发现,枚举在这里被过滤了。

总的来说,因为枚举的构造方法是私有的,所以不能实例化,另外反射拿到的类对象再去new实例的时候会因为枚举类型被过滤掉,所以枚举实现的单例模式是安全的。

所以枚举具有构造方法默认是私有的,并且都是默认继承java.lang.Enum这个类,可以避免反射和序列化问题,枚举常量更安全更简单,代码更加优雅。

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

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

相关文章

URLSearchParams:JavaScript中的URL查询参数处理工具

文章目录 导言&#xff1a;一、URLSearchParams的来历二、URLSearchParams的作用三、URLSearchParams的方法和属性四、使用示例五、注意事项六、结论参考资料 导言&#xff1a; 在Web开发中&#xff0c;处理URL查询参数是一项常见的任务。为了简化这一过程&#xff0c;JavaScr…

论文阅读——Adversarial Eigen Attack on Black-Box Models

Adversarial Eigen Attack on Black-Box Models 作者&#xff1a;Linjun Zhou&#xff0c; Linjun Zhou 攻击类别&#xff1a;黑盒&#xff08;基于梯度信息&#xff09;&#xff0c;白盒模型的预训练模型可获得&#xff0c;但训练数据和微调预训练模型的数据不可得&#xff…

龙迅LT86102UXE产品概括,HDMI2.0转一分二HDMI2.0/1.4,支持音频剥离,支持4K60HZ

LT86102UXE 1. 一般说明 龙迅 LT86102UXE HDMI2.0 分路器具有符合 HDMI2.0/1.4 规范的 1&#xff1a;2 分路器、最大 6Gbps 高速数据速率、自适应均衡 RX 输入和预加重 TX 输出&#xff08;用于支持长电缆应用&#xff09;、内部 TX 通道交换以实现灵活的 PCB 布线。 LT86102…

A Survey for In-context Learning

A Survey for In-context Learning 摘要&#xff1a; 随着大语言模型(LLMs)能力的增长&#xff0c;上下文学习(ICL)已经成为一个NLP新的范式&#xff0c;因为LLMs仅基于几个训练样本让内容本身增强。现在已经成为一个新的趋势去探索ICL来评价和extrapolate LLMs的能力。在这篇…

vue3+element-plus表格默认排序default-sort失效问题

场景 在使用动态数据渲染的场景&#xff0c;el-table设置默认属性default-sort失效。 原因 el-table的default-sort属性是针对静态数据的&#xff0c;如果是动态数据&#xff0c;default-sort则无法监听到。 案例&#xff1a;静态数据 <template><el-table:data&…

一文分析多少杠杆最高

在进行加杠杆操作时&#xff0c;合约产品通常会有一定的杠杆比例限制&#xff0c;这是由监管机构或交易平台设定的。杠杆比例限制的目的是为了控制风险&#xff0c;避免过度杠杆化导致的潜在损失过大。 不同的交易平台和合约产品可以有不同的杠杆比例限制。一般来说&#xff0…

堆叠注入进阶--(buuctf-随便注、GYCTF-black_list)【多方法详解】

了解一下 堆叠注入基础知识及其他题目&#xff1a; SQL-堆叠注入 终于有时间来填填坑了 Buuctf-随便注 算是堆叠注入中非常经典的题目了。 随便试试就能看到黑名单&#xff1a; 没了select&#xff0c;其实大概率就是堆叠注入 先探测一下&#xff1a; 1;show databases;…

Struts2一次请求参数问题的记录

最近&#xff0c;一次前端正常请求&#xff0c;但后台出现请求参数值的变化&#xff0c;导致报错&#xff0c;问题如下&#xff1a; 从入参request中查看请求参数&#xff0c;是一个Json字符串&#xff0c;其中有个description的键值对&#xff1b; 但是&#xff0c;接下来调用…

分布式websocket解决方案

1、websocket问题由来 websocket基础请自行学习,本文章是解决在分布式环境下websocket通讯问题。 在单体环境下,所有web客户端都是连接到某一个微服务上,这样消息都是到达统一服务端,并且也是由一个服务端进行响应,所以不会出现问题。 但是在分布式环境下,我们很容易发现…

【Vue】Vue2创建移动端项目实战教程,创建移动端项目保姆级教程,设置axios,utils工具包,vue.fonfig.js配置项 (下)

系列文章目录 这里是创建移动端项目 【Vue】Vue2.x创建项目全程讲解&#xff0c;保姆级教程&#xff0c;手把手教&#xff0c;Vue2怎么创建项目&#xff08;上&#xff09; 【Vue】Vue2创建移动端项目实战教程&#xff0c;创建移动端项目保姆级教程&#xff0c;接上一篇创建Vue…

解压版 MySQL 数据库的安装与配置

目录 1 下载2 安装3 配置3.1 添加环境变量3.2 新建配置文件3.3 初始化MySQL3.4 注册MySQL服务3.5 启动MySQL服务3.6 修改默认账户密码 4 登录MySQL5 卸载MySQL 安装环境:Win10 64位 软件版本:MySQL 5.7.24 解压版 1 下载 点击链接 进入如下界面 ❗️注意&#xff1a; 我们一般不…

JavaEE初阶:多线程 - 编程

1.认识线程 我们在之前认识了什么是多进程&#xff0c;今天我们来了解线程。 一个线程就是一个 "执行流". 每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间 "同时" 执行 着多份代码. 引入进程这个概念&#xff0c;主要是为了解决并发编程这样的…

JAVA集合-List

// 数组的缺点&#xff1a;每次使用都需要指定长度&#xff0c;掉率低&#xff0c;操作麻烦 // // 【java集合体系】&#xff1a;分类&#xff1a;6个接口&#xff0c;1个工具类 // 6个接口&#xff1a; 单列 :Collection,(父接口) // …

成功项目管理必备的五个关键因素

在任何组织中&#xff0c;良好的项目管理都是项目成功的首要标准。然而&#xff0c;一旦被淹没在无穷无尽的任务、持续的紧迫性和利益相关者相互冲突等情况中&#xff0c;管理好项目可能会让你感到力不从心。找出项目成功的关键因素并加以解决&#xff0c;就能避免一切失败。 …

浅谈学生宿舍安全用电管理存在的问题及防范措施

安科瑞 华楠 摘要&#xff1a;2009年&#xff0c;由一个小小的“热的快”引起的学院女生火灾事件&#xff0c;再一次敲响了大学生安全用电的警钟。而近年来随着教育事业的蓬勃发展和教育体制的推进&#xff0c;我国高等教育总规模在逐年增加。而目前高等学校能源使用主要是以电…

产品帮助中心的制作方法,保姆级0-1完整的实操教程!

帮助中心是一个产品的重要用户自助服务模块&#xff0c;包括各类产品相关信息&#xff0c;用以帮助用户快速理解和使用产品功能。对于我们产品开发和管理者而言&#xff0c;设计帮助中心的初衷是解决用户困惑&#xff0c;怎么设计帮助中心&#xff0c;才能让其价值尽可能的大&a…

【C语言】每日一题(寻找数组的中心下标)

寻找数组的中心下标&#xff0c;链接奉上 方法 暴力循环前缀和 暴力循环 ​​​​​​​思路&#xff1a; 依旧是我们的老朋友&#xff0c;暴力循环。 1.可以利用外层for循环&#xff0c;循环变量为数组下标&#xff0c;在循环内分别求出下标左边与右边的sum 2.在边界时讨论&…

伙伴云CEO戴志康:让数据和业务更好的互通展现,数字化与可视化同步进行

近日&#xff0c;零代码平台伙伴云产品「页面」功能正式上线&#xff0c;在【小伙开麦】直播间&#xff0c;CEO戴志康和产品经理共同为在线观众展示「页面」的功能与使用技巧&#xff0c;让小伙伴们大呼过瘾&#xff01;好玩、好用、好看的「页面」&#xff0c;到底有哪些亮点&…

动手学深度学习-pytorch版本(一):引言 预备知识

参考引用 动手学深度学习利用 Anaconda 安装 pytorch 和 paddle 深度学习环境 pycharm 安装 0. 环境安装 利用 Anaconda 安装 pytorch 和 paddle 深度学习环境 pycharm 安装 1. 引言 机器学习&#xff08;machine learning&#xff0c;ML&#xff09;是⼀类强⼤的可以从经…

苏宁API的详细介绍及应用领域分析

随着电子商务的快速发展&#xff0c;越来越多的企业开始关注并积极开发自己的API接口&#xff0c;以提供更加高效、便捷和个性化的服务。苏宁作为中国领先的零售企业之一&#xff0c;也不例外。 1. 苏宁API是什么&#xff1f; 苏宁API是苏宁开放平台提供的一组接口集合&#x…