一.加载一个类的几种方法
接口
IUser
package org.me.javaapp; /** * * @author Administrator */ public interface IUser { }
User.java
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.me.javaapp; public class User implements IUser{ private String name; private int id; /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the id */ public int getId() { return id; } /** * @param id the id to set */ public void setId(int id) { this.id = id; } }
主类
public static void main(String[] args) throws ClassNotFoundException{ try{ Class c1=Class.forName("org.me.javaapp.User"); Class c2=User.class; Object o1=c1.newInstance(); Object o2=c2.newInstance(); User u1=new User(); Class c3=u1.getClass(); /* this.getClass.getClassLoader(); // 使用当前类的ClassLoader Thread.currentThread().getContextClassLoader(); // 使用当前线程的ClassLoader ClassLoader.getSystemClassLoader(); // 使 用系统ClassLoader,即系统的入口点所使用的ClassLoader。(注意,system ClassLoader与根 ClassLoader并不一样。JVM下system ClassLoader通常为App ClassLoader) */ ClassLoader clo=Thread.currentThread().getContextClassLoader(); Class c4=clo.loadClass("org.me.javaapp.User"); Field[] fs = c1.getDeclaredFields(); for(Field field:fs){ System.out.println("获得属性的修饰符,例如public,static等等 >>"+Modifier.toString(field.getModifiers())); System.out.println("属性的类型的名字 >>"+field.getType()); System.out.println("属性的名字 >>"+field.getName()); } Method[] ms = c1.getDeclaredMethods(); for(Method field:ms){ System.out.println("获得方法的修饰符,例如public,static等等 >>"+Modifier.toString(field.getModifiers())); System.out.println("方法的参数个数 >>"+field.getParameterCount()); System.out.println("方法的名字 >>"+field.getName()); } System.out.println("c1的父类>>"+c1.getSuperclass()); Class[] cs=c1.getInterfaces(); for(Class field:cs){ System.out.println("接口的名字 >>"+field.getName()); } System.out.println(">>>>>>>>>>>"); } catch (Exception ex){ System.out.println(ex.toString()); } }
输出:
获得属性的修饰符,例如public,static等等 >>private
属性的类型的名字 >>class java.lang.String
属性的名字 >>name
获得属性的修饰符,例如public,static等等 >>private
属性的类型的名字 >>int
属性的名字 >>id
获得方法的修饰符,例如public,static等等 >>public
方法的参数个数 >>0
方法的名字 >>getName
获得方法的修饰符,例如public,static等等 >>public
方法的参数个数 >>0
方法的名字 >>getId
获得方法的修饰符,例如public,static等等 >>public
方法的参数个数 >>1
方法的名字 >>setName
获得方法的修饰符,例如public,static等等 >>public
方法的参数个数 >>1
方法的名字 >>setId
c1的父类>>class java.lang.Object
接口的名字 >>org.me.javaapp.IUser
参考:JAVA中的反射机制
获取方法,和构造方法,不再详细描述,只来看一下关键字:
方法关键字
含义
getDeclaredMethods()
获取所有的方法
getReturnType()
获得方法的放回类型
getParameterTypes()
获得方法的传入参数类型
getDeclaredMethod("方法名",参数类型.class,……)
获得特定的方法
构造方法关键字
含义
getDeclaredConstructors()
获取所有的构造方法
getDeclaredConstructor(参数类型.class,……)
获取特定的构造方法
父类和父接口
含义
getSuperclass()
获取某类的父类
getInterfaces()
获取某类实现的接口
ClassLoader主要对类的请求提供服务,当JVM需要某类时,它根据名称向ClassLoader要求这个类,然后由ClassLoader返回这个类的class对象。
java中的反射总结 【举例不错,很全面】
二.Invoke
一个方法可以生成多个Method对象,但只有一个root对象,主要用于持有一个MethodAccessor对象,这个对象也可以认为一个方法只有一个,相当于是static的,因为Method的invoke是交给MethodAccessor执行的。
package org.me.javaapp; public class Child extends Person{ public void say(String s) { System.out.println("Hello invork>>>"+s); } public void add(int a,int b) { a+=b; System.out.println("a+b="+a); } }
invoke调用
package org.me.test; import java.lang.reflect.Method; import org.junit.Test; public class TestInvoke { @Test public void testSingleton() throws Exception { Class<?> clz = Class.forName("org.me.javaapp.Child"); Object o = clz.newInstance(); Method m = clz.getMethod("add", int.class,int.class); m.invoke(o, 1,2); m = clz.getDeclaredMethod("say", String.class); m.invoke(o,"http://blog.csdn.net/unix21/"); } }
参考:
getMethod方法第一个参数指定一个需要调用的方法名称
第二个参数是需要调用方法的参数类型列表,是参数类型!如无参数可以指定null。
参数必须和方法中一样int和Integer,double和Double被视为不同的类型。
反射中getMethods 与 getDeclaredMethods 的区别
public Method[] getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。
public Method[] getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
当然也包括它所实现接口的方法。
JAVA深入研究——Method的Invoke方法【非常深入,讲了实现细节】
可以看到Method.invoke()实际上并不是自己实现的反射调用逻辑,而是委托给sun.reflect.MethodAccessor来处理。
每个实际的Java方法只有一个对应的Method对象作为root。这个root是不会暴露给用户的,而是每次在通过反射获取Method对象时新创建Method对象把root包装起来再给用户。
在第一次调用一个实际Java方法对应得Method对象的invoke()方法之前,实现调用逻辑的MethodAccessor对象还没创建;
等第一次调用时才新创建MethodAccessor并更新给root,然后调用MethodAccessor.invoke()真正完成反射调用。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
三.Class<?>与Class
Class<?> clz = Class.forName("org.me.javaapp.Child"); Class clzz = Class.forName("org.me.javaapp.Child"); Object o = clzz.newInstance(); Method m = clz.getMethod("add", int.class,int.class); m.invoke(o, 1,2); m = clz.getDeclaredMethod("say", String.class); m.invoke(o,"http://blog.csdn.net/unix21/");效果是一样的。