一个类有多个组成部分,例如:成员变量,方法,构造方法等。
反射就是加载类,并解剖出类的各个组成部分。
>>编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?
开发过程中或做框架时,经常需要写配置文件,内部机制要通过反射机制来获取。
>>加载类
Java中有一个Class类用于代表某一个类的字节码。
Class类即然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName()
forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装
另外两种得到class对象的方式:
类名.class
对象.getClass()
>>解剖类
Class对象提供了如下常用方法:
Public Constructor getConstructor(Class<?>...?parameterTypes)
Public Method getMethod(String?name, Class<?>...?parameterTypes)
Public Field getField(String?name) public
public Constructor getDeclaredConstructor(Class... parameterTypes)
public Method getDeclaredMethod(String name,Class... parameterTypes)
public Field getDeclaredField(String name)
这些方法分别用于从类中解剖出构造函数、方法和成员变量(属性)。
解剖出的成员分别使用Constructor、 Method 、 Field 对象表示。
>>利用Constructor创建对象>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Constructor类提供了如下方法,用于创建类的对象:
public Object newInstance(Object... initargs),initargs用于指定构造函数接收的参数
//反射类无参的构造方法
//1.加载类
Class clazz = Class.forName("");
//2.反射出构造方法
Constructor c = clazz.getConstructor(null); //Person()
//3.创建类的对象
Person p = (Person) c.newInstance(null);
//反射类构造方法:public Person(String name)
Class clazz = Class.forName("");
Constructor c = clazz.getConstructor(String.class);
Person p = (Person) c.newInstance("xxx");
//public Person(String name,int arg)
Class clazz = Class.forName("");
Constructor c = clazz.getConstructor(String.class,int.class);
Person p = (Person) c.newInstance("xxx",12);
//public Person(String[] name,int arg)
Class clazz = Class.forName("");
Constructor c = clazz.getConstructor(String[].class,int.class);
Person p = (Person) c.newInstance(new String[]{"1","2"},12);
//private Person(List list)
Class clazz = Class.forName("");
Constructor c = clazz.getDeclaredConstructor(List.class);
c.setAccessible(true); //暴力反射
Person p = (Person) c.newInstance(new ArrayList());
>>利用Method执行方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Method对象提供了如下方法,用于执行它所代表的方法:
public Object invoke(Object obj,Object... args)
jdk1.4和jdk1.5的invoke方法的区别:
Jdk1.5:public Object invoke(Object obj,Object... args)
Jdk1.4:public Object invoke(Object obj,Object[] args),
>>利用Method执行main方法
问题:
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,
如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字
符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,
即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),
javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"}); ,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数
//反射类Person的方法
//public void run()
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getMethod("run", null);
method.invoke(p, null);
//jdk1.6----->class----->jdk1.5
//public void run(String name)
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getMethod("run", String.class);
method.invoke(p, "xxxx");
//public void run(String name,int arg){
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getMethod("run", String.class,int.class);
method.invoke(p, "xxxx",12);
//public int sum(int i,int j){
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getMethod("sum", int.class,int.class);
int value = (Integer) method.invoke(p, 12,13); //sum
// private String getString(String name){
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getDeclaredMethod("getString", String.class);
method.setAccessible(true);
String value = (String) method.invoke(p, "uuuu");
//private static void xx()
Class clazz = Class.forName("");
Method method = clazz.getDeclaredMethod("xx", null);
method.setAccessible(true);
method.invoke(null, null); //静态方法在调用时不需要对象
//public static void main(String[] args) {
Class clazz = Class.forName("");
Method method = clazz.getMethod("main", String[].class);
String args[] = {"1","2","3"};
//method.invoke(null, new Object[]{args}); //main(String s1,String s2,String s2)
method.invoke(null, (Object)args);
>>利用Field访问属性>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Field对象提供了如下方法,用于设置、获取对象属性的值:
Public void set(Object obj,Object value)
public Object get(Object obj)
//反射类Person的字段
Person p = new Person();
Class clazz = Class.forName("");
java.lang.reflect.Field f = clazz.getDeclaredField("age");
f.setAccessible(true);
f.set(p, 23);
int age = (Integer) f.get(p); //age
System.out.println(age);
反射就是加载类,并解剖出类的各个组成部分。
>>编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?
开发过程中或做框架时,经常需要写配置文件,内部机制要通过反射机制来获取。
>>加载类
Java中有一个Class类用于代表某一个类的字节码。
Class类即然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName()
forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装
另外两种得到class对象的方式:
类名.class
对象.getClass()
>>解剖类
Class对象提供了如下常用方法:
Public Constructor getConstructor(Class<?>...?parameterTypes)
Public Method getMethod(String?name, Class<?>...?parameterTypes)
Public Field getField(String?name) public
public Constructor getDeclaredConstructor(Class... parameterTypes)
public Method getDeclaredMethod(String name,Class... parameterTypes)
public Field getDeclaredField(String name)
这些方法分别用于从类中解剖出构造函数、方法和成员变量(属性)。
解剖出的成员分别使用Constructor、 Method 、 Field 对象表示。
>>利用Constructor创建对象>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Constructor类提供了如下方法,用于创建类的对象:
public Object newInstance(Object... initargs),initargs用于指定构造函数接收的参数
//反射类无参的构造方法
//1.加载类
Class clazz = Class.forName("");
//2.反射出构造方法
Constructor c = clazz.getConstructor(null); //Person()
//3.创建类的对象
Person p = (Person) c.newInstance(null);
//反射类构造方法:public Person(String name)
Class clazz = Class.forName("");
Constructor c = clazz.getConstructor(String.class);
Person p = (Person) c.newInstance("xxx");
//public Person(String name,int arg)
Class clazz = Class.forName("");
Constructor c = clazz.getConstructor(String.class,int.class);
Person p = (Person) c.newInstance("xxx",12);
//public Person(String[] name,int arg)
Class clazz = Class.forName("");
Constructor c = clazz.getConstructor(String[].class,int.class);
Person p = (Person) c.newInstance(new String[]{"1","2"},12);
//private Person(List list)
Class clazz = Class.forName("");
Constructor c = clazz.getDeclaredConstructor(List.class);
c.setAccessible(true); //暴力反射
Person p = (Person) c.newInstance(new ArrayList());
>>利用Method执行方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Method对象提供了如下方法,用于执行它所代表的方法:
public Object invoke(Object obj,Object... args)
jdk1.4和jdk1.5的invoke方法的区别:
Jdk1.5:public Object invoke(Object obj,Object... args)
Jdk1.4:public Object invoke(Object obj,Object[] args),
>>利用Method执行main方法
问题:
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,
如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字
符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,
即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),
javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"}); ,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数
//反射类Person的方法
//public void run()
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getMethod("run", null);
method.invoke(p, null);
//jdk1.6----->class----->jdk1.5
//public void run(String name)
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getMethod("run", String.class);
method.invoke(p, "xxxx");
//public void run(String name,int arg){
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getMethod("run", String.class,int.class);
method.invoke(p, "xxxx",12);
//public int sum(int i,int j){
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getMethod("sum", int.class,int.class);
int value = (Integer) method.invoke(p, 12,13); //sum
// private String getString(String name){
Person p = new Person();
Class clazz = Class.forName("");
Method method = clazz.getDeclaredMethod("getString", String.class);
method.setAccessible(true);
String value = (String) method.invoke(p, "uuuu");
//private static void xx()
Class clazz = Class.forName("");
Method method = clazz.getDeclaredMethod("xx", null);
method.setAccessible(true);
method.invoke(null, null); //静态方法在调用时不需要对象
//public static void main(String[] args) {
Class clazz = Class.forName("");
Method method = clazz.getMethod("main", String[].class);
String args[] = {"1","2","3"};
//method.invoke(null, new Object[]{args}); //main(String s1,String s2,String s2)
method.invoke(null, (Object)args);
>>利用Field访问属性>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Field对象提供了如下方法,用于设置、获取对象属性的值:
Public void set(Object obj,Object value)
public Object get(Object obj)
//反射类Person的字段
Person p = new Person();
Class clazz = Class.forName("");
java.lang.reflect.Field f = clazz.getDeclaredField("age");
f.setAccessible(true);
f.set(p, 23);
int age = (Integer) f.get(p); //age
System.out.println(age);