文章目錄
1.Java反射
- 機制是運行狀態中,對於任意一個類都能夠知道這個類的所有屬性和方法(包括私有的);對於任意一個對象,都能調用他的任意方法和屬性;這種動態獲取信息及動態調用對象方法的功能稱爲Java的反射機制。
1.1 用途
-
在運行時判斷任意一個對象所屬的類。
-
在運行時構造任意一個類的對象。
-
在運行時判斷任意一個類所具有的成員變量和方法。
-
在運行時調用任意一個對象的方法。
-
生成動態代理。**
2. 反射相關的類
類名 | 用途 |
---|---|
java.lang.Class | 代表類 |
java.lang.reflect.Field | 代表類的成員變量 |
java.lang.reflect.Method | 代表類的方法 |
java.lang.reflect.Constructor | 代表類的構造 |
2. Class類
在Java程序中獲得Class對象通常有如下三種方式:
1.使用Class類的forName(String clazzName)靜態方法。該方法需要傳入字符串參數,該字符串參數的值是某個類的全限定名(必須添加完整包名)。
2.調用某個類的class屬性來獲取該類對應的Class對象。
3.調用某個對象的getClass()方法。該方法是java.lang.Object類中的一個方法。
3. Field
Field[] allFields = class2.getDeclaredFields();//獲取class對象的所有屬性
Field[] publicFields = class2.getFields();//獲取class對象的public屬性
Field ageField = class2.getDeclaredField("age");//獲取class指定屬性,可以獲得私有屬性
Field desField = class2.getField("des");//獲取class指定的public屬性
4. Method
Method[] methods = class2.getDeclaredMethods();//獲取class對象的所有聲明方法
Method[] allMethods = class2.getMethods();//獲取class對象的所有public方法 包括父類的方法
Method method = class2.getMethod("info", String.class);//返回次Class對象對應類的、帶指定形參列表的public方法
Method declaredMethod = class2.getDeclaredMethod("info", String.class);//返回次Class對象對應類的、帶指定形參列表的方法
5. Constructor
Constructor<?>[] allConstructors = class2.getDeclaredConstructors();//獲取class對象的所有聲明構造函數
Constructor<?>[] publicConstructors = class2.getConstructors();//獲取class對象public構造函數
Constructor<?> constructor = class2.getDeclaredConstructor(String.class);//獲取指定聲明構造函數
Constructor publicConstructor = class2.getConstructor(String.class);//獲取指定聲明的public構造函數
6. 通過反射 生成實例對象
-
1.使用Class對象的newInstance()方法來創建該Class對象對應類的實例。這種方式要求該Class對象的對應類有默認構造器,而執行newInstance()方法時實際上是利用默認構造器來創建該類的實例。
-
2.先使用Class對象獲取指定的Constructor對象,再調用Constructor對象的newInstance()方法來創建該Class對象對應類的實例。通過這種方式可以選擇使用指定的構造器來創建實例。
7. 調用方法
-
1.通過Class對象的getMethods()方法或者getMethod()方法獲得指定方法,返回Method數組或對象。
-
2.調用Method對象中的Object invoke(Object obj, Object… args)方法。第一個參數對應調用該方法的實例對象,第二個參數對應該方法的參數。
8. 示例代碼:
8.1 反射
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
/**
* 反射:
* 在類加載過程中,獲取類的屬性和方法構造方法等信息,可以調用其方法。
*
*
* 克隆: 我們學習數據庫: 數據庫提供 《驅動器》driver DriverManager 這個驅動器不允許new。
* 會學習: Tomcat 內部組件需要反射。
* 會學習: 框架: 內部組件也需要反射。
*
* 通過反射:得到類的包名以及類名。
* Properties
*
*
*/
public class Demo01 {
public static void main(String[] args) throws Exception, IOException {
Properties pro = new Properties();
pro.load(new FileInputStream("aa.properties"));
System.out.println(pro.get("name"));
String str = (String) pro.get("name");
Class c= Class.forName(str);
Object obj = c.newInstance();
Foo foo = (Foo)obj;
System.out.println(foo.a);
foo.show();
/**
* Class 是每個類的字節碼對象。
*/
String str1 = "abc";// str1 Object "abc" Object
Class c1 = str1.getClass();
Class c2 = "abc".getClass();
System.out.println(c1==c2);
;Class c3 = String.class;
Class c4 = Class.forName("java.lang.String");
System.out.println(c3==c4);
}
}
8.2 反射是什麼
1
package am;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import javax.activation.FileDataSource;
/**
* 反射是什麼:
* java中的反射:就是在類的加載過程中,發現類的屬性和方法構造方法等信息。可以獲得類的屬性值,可以調用類的方法。
*
*
* 反射獲得類的對象。
*
*/
public class Demo01 {
public static void main(String[] args) throws Exception{
// 通過反射,獲取類的對象。
Object obj = create("am.Foo");;
Foo foo = (Foo)obj;
System.out.println(foo.a);
double dou = foo.show(12, "hello");
System.out.println(dou);
System.out.println("======================================");
// 獲得類的屬性
showField(obj);
System.out.println("======================================");
double a = (double)getFieldValue(obj, "b");
System.out.println(a);
System.out.println("========================================");
// 通過反射調用方法。
Object ob = getMethodValue(obj,"show",new Class[]{int.class,String.class},new Object[]{23,"abc"});
double douValue = (double)ob;
System.out.println(douValue);
}
//通過反射調用方法,哪個對象,什麼名稱,參數類型,參數值
public static Object getMethodValue(Object obj,String method,Class[] paramType,Object[] param)
throws Exception{
Class cla = obj.getClass();
Method me = cla.getDeclaredMethod(method, paramType);
Object o = me.invoke(obj, param);
return o;
}
// 獲取類的屬性值:
public static Object getFieldValue(Object obj,String name)throws Exception{
Class cla = obj.getClass();// 獲取字節碼對象。
Field field = cla.getDeclaredField(name);// 通過屬性的名稱。獲取當前屬性。
Object result = field.get(obj);
return result;
}
// 通過反射,可以獲得類的屬性信息以及方法信息。
public static void showField(Object obj){
// java中對屬性類。 Field 方法類:Method
Class cla = obj.getClass();
System.out.println("獲取類名:"+cla.getName());
System.out.println("======================================");
// 獲取類的屬性:
Field[] fields = cla.getDeclaredFields();// 獲取公開的屬性。
for(Field field : fields){
System.out.println("獲取類的屬性類型"+field.getType());
System.out.println("獲取類的屬性名稱:"+field.getName());
}
System.out.println("======================================");
// 獲取類的方法。
Method[] methods = cla.getDeclaredMethods();
for(Method method : methods){
System.out.println("獲取方法的返回值類型:"+method.getReturnType());
System.out.println("獲取方法名稱:"+method.getName());
System.out.println("獲取方法的參數類型。"+Arrays.toString(method.getParameterTypes()));
}
System.out.println("=======================================");
// 獲取類的構造方法:
Constructor[] cons = cla.getDeclaredConstructors();
for(Constructor con : cons){
System.out.println("構造方法的名字:"+con.getName());
System.out.println("構造方法參數類型:"+Arrays.toString(con.getParameterTypes()));
}
}
// 如何反射類的實例。
public static Object create(String name) throws Exception{
// 反射的方法。Class.forName();
Class cla = Class.forName(name);
// 如何獲得Object類型對象。
Object obj = cla.newInstance();
return obj;
}
}
// 模擬類。
class Foo{
int a = 10;
double b = 20;
public double show(int p,String str){
System.out.println("調用方法傳入的值是:"+str);
return a+b+p;
}
public Foo(){
}
public Foo(int a,int b){
}
}
2
package am1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class ReFactory {
// 兩個方法。通過key 返回value。
public static String getVal(String name,String fileName){
Properties pro = new Properties();
try {
pro.load(new FileInputStream(fileName));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String value = pro.getProperty(name);
return value;
}
// 反射方法。
public static Object getObj(String name){
Class forName;
Object obj = null;
try {
forName = Class.forName(name);
obj = forName.newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
}
}
8.3 反射 代碼塊
1
* Object 超類,所有
* 類的超類。 對象。
* Class 字節碼對象,永遠唯一。
、
```java
public class Demo {
public static void main(String[] args) throws Exception {
String str1 = "abc";
Class class1 = str1.getClass();
Class class2 = "abc".getClass();
System.out.println(class1==class2);
Foo foo = new Foo();
Foo foo2 = new Foo();
Class cFoo1 = foo.getClass();
Class cFoo2 = foo2.getClass();
System.out.println("******"+(foo==foo2));
System.out.println("%%%%%%%%%%%%%"+(cFoo1==cFoo2));
// 使用Class 對象進行 Object對象的反射。
String fooName = "am.Foo";
// Class.forName 就是反射。通過名稱反射出字節碼對象。
Class forName = Class.forName(fooName);
Object obj = forName.newInstance();
Foo foo3 = (Foo)obj;
System.out.println(foo3.a);
Class forName1 = Class.forName(fooName);
Object obj1 = forName1.newInstance();
Foo foo4 = (Foo)obj1;
System.out.println(foo4.a);
System.out.println(foo3==foo4);
System.out.println(forName==forName1);
}
}
class Foo{
public int a = 10;
}
2
/**
*
* 反射:
* 在開發中,框架插件數據庫等等第三方應用會提供包。比如數據庫驅動包。無法使用object創建對象。
* 可以使用包名類名進行反射。從而得到對象。
* 需要將第三方應用的包名.類名進行統一管理。所以使用properites文件進行管理。
*
*/
public class Demo02 {
public static void main(String[] args) throws Exception, Exception {
// Properties 對象。
Properties pro = new Properties();
pro.load(new FileInputStream("db.properties"));
// 通過文件的加載,可以獲得key value
System.out.println(pro.getProperty("name"));
// 通過名稱進行反射。
Class forName = Class.forName(pro.getProperty("name"));
Object obj = forName.newInstance();
Student student = (Student)obj;
System.out.println(student.a);
student.show();
}
}
3
package am;
public class Student {
public int a = 10;
public void show(){
System.out.println("hello student"+a);
}
}