Java枚举和反射

枚举类型概述

  1. Java中的枚举类型属于自定义引用类型,定义枚举类型使用enum关键字修饰类。
  2. 枚举类型通常包含一组常量数据值,适合某种事物固定的构成结构(如季节由’’四季组成)
  3. 枚举类型可以实现某个接口,但是枚举类型不能继承其他类同时枚举类型也不能被其他类所继承。
  4. 枚举类型可以定义非抽象方法,方法必须在所有枚举常量之后;枚举类型中也可以定义内部类及内部接口。

 

枚举类型的定义

public enum SignalLamp{

/* 枚举中的常量 */

RED,

GREEN,

BLUE;

}

 

枚举常用方法

public final int compareTo(E o) 比较枚举值大小,小于参数返回负数,大于参数返回正数,相等返回0

public final String name() 获取枚举的名称字符串形式

public final int ordinal() 获取枚举所在枚举集合中位置的索引,索引默认从0开始

public static E[ ] values() 获取所有枚举数组形式

public static E valueOf(String name)根据参数获取枚举常量对象

 

总结,想定义一组常量表示某种特定事物时,可以使用枚举。

 

反射概述

Java中的反射编程是通过在JVM运行时获取某个类型的字节码(Class)对象,从而利用其反向获取此类型定义的内部信息实现编程的一种机制。

反射编程通常属于非常规操作,存在一定的安全问题。

反射编程在设计开发工具框架时使用较多,诸如springhibernatejava应用框架技术中使用比较频繁。

反射编程比较普通的编程方式执行效率相对要低。

 

反射编程常用组件

javalang.Class 字节码类型

java.lang.reflect.Constructor 构造器类型

java.lang.reflect.Method 方法类型

java.lang.reflect.Field 属性类型

java.lang.reflect.Modifier 访问修饰符类型

 

Class

Class类的实例表示正在运行的Java应用程序中的类和接口,是字节码的实例。Class没有公共构造方法。Class对象是在加载类时由Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的。任何一个java对象都可以获得一个和其相关的Class对象。利用Class对象可以获得此类的信息;所有同一类型的实例共享一个字节码对象

 

public static Class<?> forName(String className) //表示给定一个字符串,这个字符串是某个引用类的字符串描述,它包含整个类的绝对路径包名,加载此类会返回一个字节码对象

 

public Field getField(String name) //返回一个Field实例,返回一个字段

 

public Field[] getField() //返回所有字段

 

public Field getDeclaredField(String name) //按照给定名称获取一个私有字段

 

public Method getMethod(String name,Class<?>... parameterTypes) //获取类中的方法,第一个参数是名称,第二个是字节码类型,第三个是可变数组

 

public Method[] getMethods() //获取类中的所有方法

 

public Constructor<T> getConstructor(Class<?>... parameterTypes) //获取类中的构造器

 

public Constructor<?>[ ] getConstructors() //获取所有构造器

 

public native int getModifiers() //获取当前类的访问标识符,native表示本地方法

 

public ClassLoader getClassLoader() //获取类加载器

 

Constructor

Constructor类表示某个类的构造方法实例类型。利用Constructor可以创建Constructor所在类的实例并对此类进行初始化等操作。

Constructorm没有公有的构造方法,所以不能实例化它,可以通过某个类的Class实例获得一个Constructor实例

 

public T newInstance(Object...initargs) //获取某一个对象类型的实例

 

public void setAccessible(boolean flag) //设置构造器可访问或者不可访问

 

public int getModifiers() //获取访问级别

 

public Parameter[] getParameters() //获取当前构造器的参数列表

 

public int getParameterCount() //返回参数的个数

 

Field

Field提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

Field提供了对字段的反射操作动作,使编程中访问属性字段更加灵活。

 

读取配置文件的方法,参考了这篇博文:https://www.cnblogs.com/jona-test/p/11399218.html

/**
 * 将reflectTask 应用程序导入Eclipse 集成开发工具中,调整导入可能产生的错误(jar 文件导入路径可能发生错误);
 * 按照以下所述完成实践任务.程序中Env 类为读取../conf/dbconf.properties 属性文件的组件, 应在Env中编写
 * 读取dbconf.properties 文件的功能实现代码.
 *
 * 程序中DataSourceSupport 类是为程序提供数据源的组件,其中私有方法getDataSource 返回BasicDataSource
 * 类型的数据源对象; DataSourceSupport 类中的成员属性,构造方法及getDataSource 皆是私有的访问级别,不能在
 * 此类之外为私有属性赋值, 创建此类的对象和调用私有的getDataSource 方法.
 * 为了能够实现对DataSourceSupport 的创建,为私有属性赋值并实现调用getDataSource私有方法. 定义了
 * ReflectSupport 类, 此类是本任务最核心的编码任务, 在ReflectSupport类中应利用java反射编程机制, 实现
 * 以下操作:
 *     1 获取ReflectSupport 字节码(Class 实例)对象;
 *     2 获取ReflectSupport 的构造器, 应在运行时动态改变ReflectSupport构造器的访问级别;
 *     3 利用构造器创建ReflectSupport 实例;
 *     4 为ReflectSupport实例的私有属性赋值(属性值来源于Env读取的dbconf.properties文件配置)
 *     5 获取getDataSource 方法实例,并修改其访问级别
 *     6 实现动态调用getDataSource私有方法返回BasicDataSource对象
 *
 * 在TestReflect类中的main方法中编写测试代码,完成上述任务的测试.
 */

package com.xzit.db;

import org.apache.commons.dbcp2.BasicDataSource;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;


/**
 * 此类实现以反射编程方式提供获取DataSourceSupport实例
 * 为私有属性赋值(属性值来自dbconf.properties 属性文件定义)
 * 实现调用私有方法(方法名称来自dbconf.properties 属性文件定义)
 * @author Administrator
 *
 */
public final class ReflectSupport {
    
    /*
     * 请定义一个合适的方法实现功能
     * */
    public static void main(String[] args) {
        try {

            //使用Class类通过反射的方式new一个已有的DataSourceSupport类的对象stuCla
            /**
             * 1 获取ReflectSupport 字节码(Class 实例)对象;
             */
            Class<?> c = Class.forName("com.xzit.db.DataSourceSupport");

            /**
             * 2 获取ReflectSupport 的构造器, 应在运行时动态改变ReflectSupport构造器的访问级别;
             */
            //如果目标类构造器是私有的,那就动态的改变它的访问级别
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            //通过newInstance方法new一个DataSourceSupport类的默认构造器,强转成DataSourceSupport类型的对象data
            DataSourceSupport data = (DataSourceSupport) con.newInstance();

            /**
             * 4 为ReflectSupport实例的私有属性赋值(属性值来源于Env读取的dbconf.properties文件配置)
             */
            Env env = new Env();                        //实例化Env类
            env.read();                                    //调用读取配置文件的方法read

            //获取不可见的字段属性
            Field jdbcUrl= c.getDeclaredField("jdbcUrl");
            Field jdbcDriverClass= c.getDeclaredField("jdbcDriverClass");
            Field jdbcUserName= c.getDeclaredField("jdbcUserName");
            Field jdbcPassword= c.getDeclaredField("jdbcPassword");

            /* 运行时动态改变私有字段的访问级别 */
            jdbcUrl.setAccessible(true);
            jdbcDriverClass.setAccessible(true);
            jdbcUserName.setAccessible(true);
            jdbcPassword.setAccessible(true);

            //为私有字段赋值,值取自Env读取的dbconf.properties文件配置
            jdbcUrl.set(data,env.getJdbcUrl());
            jdbcDriverClass.set(data,env.getJdbcDriverClass());
            jdbcUserName.set(data,env.getJdbcUserName());
            jdbcPassword.set(data,env.getJdbcPassword());

            //输出值检验一下:
            System.out.println("jdbcUrl= "+jdbcUrl.get(data));
            System.out.println("jdbcDriverClass= "+jdbcDriverClass.get(data));
            System.out.println("jdbcUserName= "+jdbcUserName.get(data));
            System.out.println("jdbcPassword= "+jdbcPassword.get(data));


            /**
             * 5 获取getDataSource 方法实例,并修改其访问级别
             */
            Method getData = c.getDeclaredMethod("getDataSource");
            getData.setAccessible(true);//运行时更改此方法的访问级别

            /**
             * 6 实现动态调用getDataSource私有方法返回BasicDataSource对象
             */
            BasicDataSource big = (BasicDataSource)getData.invoke(data);
            //返回一个MaxIdle值检验一下确实是调用成功了
            System.out.println(big.getMaxIdle());


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/**
 * 程序中Env 类为读取../conf/dbconf.properties 属性文件的组件,
 * 应在Env中编写读取dbconf.properties 文件的功能实现代码.
 */

package com.xzit.db;

import java.util.Properties;
import java.util.ResourceBundle;

/**
 * 此类实现对dbconf.properties 文件信息的读取
 * @author Administrator
 *
 */
public final class Env extends Properties {
    private String className;
    private String jdbcUrl;
    private String jdbcDriverClass;
    private String jdbcUserName;
    private String jdbcPassword;
    private String actionMethod;

    /*
     * 请编写实现代码
     * */
    public void read(){
        //使用getBundle()方法,读取指定路径下的配置文件
        ResourceBundle resourceBundle = ResourceBundle.getBundle("com.xzit.conf.dbconf");

        //获取资源dbconf中的className字段的值
        className = resourceBundle.getString("className");

        //获取资源dbconf中的jdbcUrl字段的值
        jdbcUrl = resourceBundle.getString("jdbcUrl");

        //获取资源dbconf中的jdbcDriverClass字段的值
        jdbcDriverClass = resourceBundle.getString("jdbcDriverClass");

        //获取资源dbconf中的jdbcUserName字段的值
        jdbcUserName = resourceBundle.getString("jdbcUserName");

        //获取资源dbconf中的jdbcDriverClass字段的值
        jdbcPassword= resourceBundle.getString("jdbcPassword");

        //获取资源dbconf中的actionMethod字段的值
        actionMethod = resourceBundle.getString("jdbcDriverClass");

    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    public void setJdbcUrl(String jdbcUrl) {
        this.jdbcUrl = jdbcUrl;
    }

    public String getJdbcDriverClass() {
        return jdbcDriverClass;
    }

    public void setJdbcDriverClass(String jdbcDriverClass) {
        this.jdbcDriverClass = jdbcDriverClass;
    }

    public String getJdbcUserName() {
        return jdbcUserName;
    }

    public void setJdbcUserName(String jdbcUserName) {
        this.jdbcUserName = jdbcUserName;
    }

    public String getJdbcPassword() {
        return jdbcPassword;
    }

    public void setJdbcPassword(String jdbcPassword) {
        this.jdbcPassword = jdbcPassword;
    }

    public String getActionMethod() {
        return actionMethod;
    }

    public void setActionMethod(String actionMethod) {
        this.actionMethod = actionMethod;
    }



}
package com.xzit.db;

import org.apache.commons.dbcp2.BasicDataSource;

/**
 * 提供获取目标数据源的通用组件
 * @author Administrator
 *
 */
public class DataSourceSupport{
    
    private String jdbcUrl;// 连接目标数据源的url
    private String jdbcDriverClass;// 数据源jdbc驱动类名称
    private String jdbcUserName;// 登录数据库的用户名称
    private String jdbcPassword;// 登录数据库用户的密码
    
    /**
     * 提供返回BasicDataSource对象的方法
     * @return BasicDataSource
     */
    private BasicDataSource getDataSource(){
        BasicDataSource ds = new BasicDataSource();
        ds.setUrl(jdbcUrl);
        ds.setDriverClassName(jdbcDriverClass);
        ds.setUsername(jdbcUserName);
        ds.setPassword(jdbcPassword);
        return ds;
    }
    /**
     * 私有构造器
     */
    private DataSourceSupport(){
    }

}
原文地址:https://www.cnblogs.com/zengyu1234/p/15097028.html