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

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM