zoukankan      html  css  js  c++  java
  • 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(){
        }
    
    }
  • 相关阅读:
    领域驱动设计概览
    淘宝大秒系统设计详解
    如何设计测试用例
    MySQL性能优化
    Nginx 负载均衡
    智慧园区该怎么建设
    Docker容器完整使用教程
    C#框架结构分层
    项目验收PPT
    这么少的字,也能做出这么好看的PPT
  • 原文地址:https://www.cnblogs.com/zengyu1234/p/15097028.html
Copyright © 2011-2022 走看看