枚舉類型概述
- Java中的枚舉類型屬於自定義引用類型,定義枚舉類型使用enum關鍵字修飾類。
- 枚舉類型通常包含一組常量數據值,適合某種事物固定的構成結構(如季節由’’四季組成)。
- 枚舉類型可以實現某個接口,但是枚舉類型不能繼承其他類同時枚舉類型也不能被其他類所繼承。
- 枚舉類型可以定義非抽象方法,方法必須在所有枚舉常量之后;枚舉類型中也可以定義內部類及內部接口。
枚舉類型的定義
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)對象,從而利用其反向獲取此類型定義的內部信息實現編程的一種機制。
反射編程通常屬於非常規操作,存在一定的安全問題。
反射編程在設計開發工具框架時使用較多,諸如spring,hibernate等java應用框架技術中使用比較頻繁。
反射編程比較普通的編程方式執行效率相對要低。
反射編程常用組件
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(){ } }