【Java反射机制】_Java反射机制的深入研究笔记
来源:互联网 发布:提高口语 知乎 编辑:程序博客网 时间:2024/05/18 03:28
【Java反射机制】_Java反射机制的深入研究笔记
本章目标:
使用反射调用类中的指定方法
使用反射完成setter及getter方法的调用
使用反射直接操作类中的属性
使用反射操作数组
public Method getMethod(String name,Class<?>...parameterTypes)throws NoSuchMethodException,SecurityException
通过getMethod方法得到一个方法的Method对象,之后通过此Method对象来执行方法,但是在方法调用的时候,因为会牵扯到方法中的参数的问题,所以通过getMethod取得的时候,必须设置好需要的参数类型。
调用sayChina()方法,因为此方法中没有任何的参数。
执行调用的方法:
public Object invoke(Object obj,Object... args)throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
执行的时候还需要传递参数进去,而且需要实例化对象。
如果现在要调用的方法中存在了参数,则必须设置参数的类型及内容。
Setter及getter方法是一个标准的属性的访问方法,如果一个类的属性被封装,则必须通过setter及getter方法设置和取得,实际上此方法的操作之所以要这样规定,主要原因是由于反射机制可以给予支持的。
通过反射可以调用setter及getter方法。
如果要想调用setter,例如:name属性设置,则setName()方法写,方法的第二个单词的首字母要大写。
如果现在假设要操作一个类中的属性,则也可以通过Filed完成,则不必麻烦的通过setter及getter。得到公共属性:
public Field getField(String name) throws NoSuchFieldException,SecurityException
得到本类属性:
public Field getDeclaredField(String name) throws NoSuchFileException,SecurityException
取得属性内容:
public Object get(Object obj) throws IlleaglArgumentException,IllegalAccessException
设置属性内容:
public void set(Object obj,Object value) throws IlleaglArgumentException,IllegalAccessException
在访问私有属性的时候,必须让这个属性可见:
public void setAccessible(boolean flag) throws SecurityException
将其内容设置成true即可。
但是,观察,以上的操作中是否需要类的setter及getter方法支持呢?证明以上的操作调用与setter及getter无关,但是为了保证程序的安全性,最好还是通过setter及getter方法完成调用。
反射机制不光只能用在类中,也可以应该在任意的引用数据类型上,当然,这就包含了数组,数组使用Array类完成。
Class类中存在以下一个方法:
public Class<?> getComponentType()
得到数组指定下标的内容:
public static Object get(Object array,int index) throws IllegalArgumentException,ArrayIndexOutOfBoundsException
修改内容:
public static void set(Object array,int index,Object value) throws IllegalArgumentException,ArrayIndexOutOfBoundsException
开辟新数组:
public static Object newInstance(Class<?> componentType,int ....dimensions) throws IllegalArgumentException,NegativeArraySizeException
取得数组信息并修改数组内容:
本章目标:
使用反射调用类中的指定方法
使用反射完成setter及getter方法的调用
使用反射直接操作类中的属性
使用反射操作数组
3.1、通过反射调用类中的方法
public Method getMethod(String name,Class<?>...parameterTypes)throws NoSuchMethodException,SecurityException
通过getMethod方法得到一个方法的Method对象,之后通过此Method对象来执行方法,但是在方法调用的时候,因为会牵扯到方法中的参数的问题,所以通过getMethod取得的时候,必须设置好需要的参数类型。
package org.lxh.demo15 ;interface China{ // 定义China接口 public static final String NATIONAL = "China" ; // 定义全局常量 public static final String AUTHOR = "李兴华" ; // 定义全局常量 public void sayChina() ; // 无参的,没有返回值的方法 public String sayHello(String name,int age) ; // 定义有两个参数的方法,并返回内容}public class Person implements China{ private String name ; private int age ; public Person(){ // 无参构造 } public Person(String name){ this.name = name ; // 设置name属性 } public Person(String name,int age){ this(name) ; this.age = age ; } public void sayChina(){ // 覆写方法 System.out.println("作者:" + AUTHOR + ",国籍:" + NATIONAL) ; } public String sayHello(String name,int age){ return name + ",你好!我今年:" + age + "岁了!" ; } public void setName(String name){ this.name = name ; } public void setAge(int age){ this.age = age ; } public String getName(){ return this.name ; } public int getAge(){ return this.age ; }};
调用sayChina()方法,因为此方法中没有任何的参数。
执行调用的方法:
public Object invoke(Object obj,Object... args)throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
执行的时候还需要传递参数进去,而且需要实例化对象。
package org.lxh.demo15.invokedemo;import java.lang.reflect.Method;public class InvokeSayChinaDemo{ public static void main(String args[]){ Class<?> c1 = null; try{ c1 = Class.forName("org.lxh.demo15.Person"); //实例化Class对象 }catch(Exception e){} try{ Method met = c1.getMethod("sayChina"); //找到sayChina()方法 met.invoke(c1.newInstance()); //调用方法 }catch(Exception e){ e.printStackTrace(); } }}
如果现在要调用的方法中存在了参数,则必须设置参数的类型及内容。
package org.lxh.demo15.invokedemo ;import java.lang.reflect.Method ;public class InvokeSayHelloDemo{ public static void main(String args[]){ Class<?> c1 = null ; try{ c1 = Class.forName("org.lxh.demo15.Person") ; // 实例化Class对象 }catch(Exception e){} try{ Method met = c1.getMethod("sayHello",String.class,int.class) ; // 找到sayChina()方法 String rv = null ; rv = (String)met.invoke(c1.newInstance(),"李兴华",30) ; // 调用方法 System.out.println(rv) ; }catch(Exception e){ e.printStackTrace() ; } }};
3.2、通过反射调用类setter及getter
Setter及getter方法是一个标准的属性的访问方法,如果一个类的属性被封装,则必须通过setter及getter方法设置和取得,实际上此方法的操作之所以要这样规定,主要原因是由于反射机制可以给予支持的。
通过反射可以调用setter及getter方法。
如果要想调用setter,例如:name属性设置,则setName()方法写,方法的第二个单词的首字母要大写。
package org.lxh.demo15.invokedemo ;import java.lang.reflect.Method ;public class InvokeSetGetDemo{ public static void main(String args[]){ Class<?> c1 = null ; Object obj = null ; try{ c1 = Class.forName("org.lxh.demo15.Person") ; // 实例化Class对象 }catch(Exception e){} try{ obj = c1.newInstance() ; }catch(Exception e){} setter(obj,"name","李兴华",String.class) ; // 调用setter方法 setter(obj,"age",30,int.class) ; // 调用setter方法 System.out.print("姓名:") ; getter(obj,"name") ; System.out.print("年龄:") ; getter(obj,"age"); } /** Object obj:要操作的对象 String att:要操作的属性 Object value:要设置的属性内容 Class<?> type:要设置的属性类型 */ public static void setter(Object obj,String att,Object value,Class<?> type){ try{ Method met = obj.getClass().getMethod("set"+initStr(att),type) ; // 得到setter方法 met.invoke(obj,value) ; // 设置setter的内容 }catch(Exception e){ e.printStackTrace() ; } } public static void getter(Object obj,String att){ try{ Method met = obj.getClass().getMethod("get"+initStr(att)) ; // 得到setter方法 System.out.println(met.invoke(obj)) ; // 调用getter取得内容 }catch(Exception e){ e.printStackTrace() ; } } public static String initStr(String old){ // 将单词的首字母大写 String str = old.substring(0,1).toUpperCase() + old.substring(1) ; return str ; }};
3.3、通过反射调用属性
如果现在假设要操作一个类中的属性,则也可以通过Filed完成,则不必麻烦的通过setter及getter。得到公共属性:
public Field getField(String name) throws NoSuchFieldException,SecurityException
得到本类属性:
public Field getDeclaredField(String name) throws NoSuchFileException,SecurityException
取得属性内容:
public Object get(Object obj) throws IlleaglArgumentException,IllegalAccessException
设置属性内容:
public void set(Object obj,Object value) throws IlleaglArgumentException,IllegalAccessException
在访问私有属性的时候,必须让这个属性可见:
public void setAccessible(boolean flag) throws SecurityException
将其内容设置成true即可。
package org.lxh.demo15.invokedemo ;import java.lang.reflect.Field ;public class InvokeFieldDemo{ public static void main(String args[]) throws Exception{ Class<?> c1 = null ; Object obj = null ; c1 = Class.forName("org.lxh.demo15.Person") ; // 实例化Class对象 obj = c1.newInstance() ; Field nameField = null ; Field ageField = null ; nameField = c1.getDeclaredField("name") ; // 取得name属性 ageField = c1.getDeclaredField("age") ; // 取得name属性 nameField.setAccessible(true) ; // 此属性对外部可见 ageField.setAccessible(true) ; // 此属性对外部可见 nameField.set(obj,"李兴华") ; // 设置name属性内容 ageField.set(obj,30) ; // 设置age属性内容 System.out.println("姓名:" + nameField.get(obj)) ; System.out.println("年龄:" + ageField.get(obj)) ; }};
但是,观察,以上的操作中是否需要类的setter及getter方法支持呢?证明以上的操作调用与setter及getter无关,但是为了保证程序的安全性,最好还是通过setter及getter方法完成调用。
3.3、通过反射操作数组
反射机制不光只能用在类中,也可以应该在任意的引用数据类型上,当然,这就包含了数组,数组使用Array类完成。
Class类中存在以下一个方法:
public Class<?> getComponentType()
得到数组指定下标的内容:
public static Object get(Object array,int index) throws IllegalArgumentException,ArrayIndexOutOfBoundsException
修改内容:
public static void set(Object array,int index,Object value) throws IllegalArgumentException,ArrayIndexOutOfBoundsException
开辟新数组:
public static Object newInstance(Class<?> componentType,int ....dimensions) throws IllegalArgumentException,NegativeArraySizeException
取得数组信息并修改数组内容:
package org.lxh.demo15.invokedemo ;import java.lang.reflect.Array ;public class ChangeArrayDemo{ public static void main(String args[]) throws Exception{ int temp[] = {1,2,3} ;// 声明一整型数组 int newTemp[] = (int []) arrayInc(temp,5) ; // 重新开辟空间5 print(newTemp) ; System.out.println("\n-------------------------") ; String t[] = {"lxh","mldn","mldnjava"} ; String nt[] = (String [])arrayInc(t,8) ; print(nt) ; } public static Object arrayInc(Object obj,int len){ Class<?> c = obj.getClass() ; Class<?> arr = c.getComponentType() ; // 得到数组的 Object newO = Array.newInstance(arr,len) ; // 开辟新的大小 int co = Array.getLength(obj) ; System.arraycopy(obj,0,newO,0,co) ; // 拷贝内容 return newO ; } public static void print(Object obj){ // 数组输出 Class<?> c = obj.getClass() ; if(!c.isArray()){ // 判断是否是数组 return; } Class<?> arr = c.getComponentType() ; System.out.println(arr.getName()+"数组的长度是:" + Array.getLength(obj)) ; // 输出数组信息 for(int i=0;i<Array.getLength(obj);i++){ System.out.print(Array.get(obj,i) + "、") ; // 通过Array输出 } }};
- 【Java反射机制】_Java反射机制的深入研究笔记
- 【Java反射机制】_Java反射机制的深入研究笔记
- Java 反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java 反射机制深入研究
- Java 反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java 反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java 反射机制深入研究
- Java反射机制深入研究
- java反射机制深入研究
- 结构化面试题目
- 游戏版本比较的算法
- 获取客户端天气
- html 表格属性
- UVa 133 - The Dole Queue
- 【Java反射机制】_Java反射机制的深入研究笔记
- poj 1129 (类似poj 1419)
- MySQL 内部函数简介
- Firebug 控制台详解
- 关于工资的三个秘密
- [转]如何建立个人品牌
- IOS之地图和定位应用开发
- VB.NET异步委托调用实现串口的自收自发
- Android 实现文件打开方式可供选择功能