反射&&枚举

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

一、反射

1、定义

2、用途 

3、反射常用的类 

4、获取类对象的三种方式

5、反射使用实例

a、利用反射创建对象

b、利用反射获取到私有的构造方法

c、利用反射获取到私有方法 

d、利用反射获取到私有属性 

6、反射的优缺点

二、枚举

1、定义

2、举例 

3、常见方法 

4、枚举的优缺点 

5、利用枚举实现安全的单例模式

一、反射

1、定义

在Java的反射机制指的是在运行状态下对于任意一个类都能获取到它的属性和方法对于任何任意一个对象能调用它的所有属性和方法。对于拿到的信息也可以进行修改这种动态获取信息以及动态调用对象方法的功能就是反射机制。

2、用途 

  • 在开发过程中如果一个类的构造方法或对象的属性和方法是私有的那么就可以利用反射来动态获取信息及修改信息。
  • 反射在开发一些通用的框架时有很大的用途比如在spring中我们将所有的类Bean交给spring容器管理无论是XML配置Bean还是注解配置当我们从容器中获取Bean来依赖注入时容器会读取配置而配置中给的就是类的信息spring根据这些信息需要创建那些Beanspring就动态的创建这些类。

3、反射常用的类 

类名用途
Class类表示类的实体就是Java程序中的类和接口
Field类表示类的属性
Method类表示类的方法
Constructor类表示类的构造方法

4、获取类对象的三种方式

  • Class.forName("类的全路径名")。
  • 类名.class方法。
  • 对象.getClass()方法。

这三种方式得到的类对象地址是相同的类对象在内存中只存有一份。

5、反射使用实例

创建了一个Student类利用反射来获取Student类的相关信息。

public class Student {
    private int sno;
    private String name;

    private Student(int sno, String name) {
        this.sno = sno;
        this.name = name;
    }

    public Student() {
    }

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    private String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

a、利用反射创建对象

首先获取到类对象然后调用类对象的newInstance()方法获取到指定类的实例对象该方法是Object类然后向下转型为Student类的实例对象。 

public static Object getReflectObject(){
        try {
            Class<?> aClass = Class.forName("reflect.Student");
            Student student = (Student)aClass.newInstance();//创建类的实例
            System.out.println("学生类的实例对象" + student);
            return student;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

b、利用反射获取到私有的构造方法

首先获取到类对象然后调用其getDeclearedConstructor(int.class,String.class)获取到与传入参数匹配的构造方法然后利用setAccessible(true)设置权限为公有可以利用获取到的构造方法通过传入参数来创建对象。 

public static void getPriConstructor(){
        try {
            Class<?> sClass = Class.forName("reflect.Student");
            Constructor<?> dl = sClass.getDeclaredConstructor(int.class, String.class);
            dl.setAccessible(true);
            Student student=(Student)dl.newInstance(12,"王家和");
            System.out.println("构造对象"+student);
        } 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();
        }

    }

c、利用反射获取到私有方法 

先获取到类对象然后调用getDeclearedMethod("方法名"方法参数.class)获取到指定方法然后利用setAccessible(true)设置权限为公有再创建Student对象使用方法的invoke(对象方法参数)来执行方法。

public static void getPriMethod(){
        try {
            Class<?> sClass = Class.forName("reflect.Student");
            Method method = sClass.getDeclaredMethod("getName");
            method.setAccessible(true);
            System.out.println("私有方法"+method.getName());
            Student stu = (Student)sClass.newInstance();
            method.invoke(stu);
        } 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();
        }
    }

d、利用反射获取到私有属性 

先获取到类对象然后调用getDeclearedField("属性名")获取到指定属性然后利用setAccessible(true)设置权限为公有再创建Student对象使用属性的set(对象修改新值)来修改属性还可以利用get方法得到属性值。

public static void getPriField(){
        try {
            Class<?> sClass = Class.forName("reflect.Student");
            Field field=sClass.getDeclaredField("name");
            field.setAccessible(true);
            Student stu = (Student)sClass.newInstance();
            field.set(stu,"高山");
            String str=(String)field.get(stu);
            System.out.println("私有属性"+str);

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

6、反射的优缺点

优点

  • 可以获取到任何类的相关信息并能调用类的属性和方法。
  • 增加程序的灵活性和扩展性降低了耦合度提高了自适应能力。
  • 反射运用于许多框架。

缺点

  • 效率低。
  • 代码更加复杂。
  • 破坏了封装性。

二、枚举

1、定义

将一组常量组织起来创建出个类。

2、举例 

例如利用枚举可以定义一个天气类假设有晴天、雨天、雷电和多云天气。

public enum Weather {
    SUN,THUNDER,CLOUDY,RAINY;
}

枚举也可以定义构造方法枚举中所有的构造方法都是私有的由于任何枚举类都继承了Enum类所以在创建带参的构造方法时类中所有的对象都必须带参否则就定义一个无参的构造方法。

3、常见方法 

定义任何枚举类都会默认继承Enum类并继承Enum类的相关方法。

方法名称描述
values()以数组形式返回枚举类型的所有成员
ordinal()获取枚举成员的索引位置
valueOf()讲普通字符串装换为枚举实例
comPareTo()比较两个枚举成员在定义的顺序

注意在使用valueOf()方法时传入的参数并不是随便的字符串而是枚举类中有的。 

4、枚举的优缺点 

优点

  • 简单、安全。
  • 枚举具有内置方法代码更加优雅。

缺点

  • 不可继承无法拓展。

 5、利用枚举实现安全的单例模式

利用反射机制是无法获取到枚举类的信息所以使用枚举实现单例模式更加安全。

public enum TestEnum {
    INSTANCE;
    public TestEnum getInstance(){
        return INSTANCE;
    }
}

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6