Java-反射

一个类有多个组成部分,例如:成员变量,方法,构造方法等。
反射就是加载类,并解剖出类的各个组成部分。


>>编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?
  开发过程中或做框架时,经常需要写配置文件,内部机制要通过反射机制来获取。
 
>>加载类
  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);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值