本篇内容主要讲解“如何使用反射调用方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何使用反射调用方法”吧!
在一个类中除了有继承的关系外,最为重要的操作就是类中的结构处理了,而类中的结构首先需要观察的就是构造方法的使用问题,实际上在之前通过反射实例化对象的时候就已经接触到构造方法的问题了:
实例化方法替代:clazz.getDeclaredConstructor().newInstance()
所有类的构造方法的获取都可以直接通过Class类来完成,该类中定义有如下的几个方法:
获取所有构造方法:
public Constructor<?>[] getDeclaredConstructors() throws SecurityException
获取指定构造方法:
public Constructor<T> getConstructor() throws SecurityException
获取所有构造方法:
public Constructor<?>[] getConstructors()throws SecurityException
获取指定构造方法:
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
范例:修改Person类的定义
AbstractBase:
public abstract class AbstractBase {public AbstractBase() {}public AbstractBase(String msg) {} }
Person:
public class Person extends AbstractBase implements IChannelService,IMessageService {public Person() {}public Person(String name, int age) { }
范例:获取构造
JavaAPIDemo
public class JavaAPIDemo {public static void main(String[] args) { Class<?> cls = Person.class;//获取指定类的Class对象Constructor<?>[] constructors = cls.getDeclaredConstructors(); //获取全部构造for (Constructor<?> cons : constructors) { System.out.println(cons); } } }//执行结果:public cn.mldn.vo.Person()//public cn.mldn.vo.Person(java.lang.String,int)
此时获取的是类中的全部构造方法,但是也可以获取一个指定参数的构造。例如:现在的Person类之中有两个构造方法:
修改Person:
public class Person extends AbstractBase implements IChannelService,IMessageService {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age; }public String getName() {return name; }public void setName(String name) {this.name = name; } @Overridepublic String toString() {return "姓名:" + this.name + "、年龄:" + this.age; } }
此时调用Person类中的有参构造方法进行Person类对象实例化,此时必须指明要调用的构造,而后通过Constructor类中提供的实例化方法操作:
public T newInstance(Object... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
范例:调用指定构造实例化对象
import java.lang.reflect.Constructor;public class JavaAPIDemo {public static void main(String[] args) throws Exception { Class<?> cls = Person.class; Constructor<?> constructor = cls.getConstructor(String.class, int.class);Object obj = constructor.newInstance("小强", 78); System.out.println(obj); //姓名:小强、年龄:78} }
虽然程序代码本身允许开发者调用有参构造,但是如果从实际的开发角度出发,所有使用反射的类中最好使用无参构造,因为这样的实例化可以达到统一性。
在进行反射处理的时候也可以通过反射来获取类之中的全部方法,但是需要提醒的是,如果想通过反射调用这些方法,必须有一个前提条件:类之中要提供实例化对象。
在Class类中提供了如下的操作可以获取方法对象:
获取全部方法:
public Method[] getMethods() throws SecurityException
获取指定方法:
public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
获取本类全部方法:
public Method[] getDeclaredMethods() throws SecurityException
获取本类指定方法:
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
范例:获取全部方法
import java.lang.reflect.Method;public class JavaAPIDemo {public static void main(String[] args) throws Exception {Class<?> cls = Person.class; {Method methods [] = cls.getMethods();//获取全部方法(包括父类中的方法)for (Method met : methods){System.out.println(met); } }System.out.println("---------------难以忘怀的愚人节的分割线-----------") { // 获取本类方法Method methods [] = cls.getDeclaredMethods();for (Method met : methods){System.out.println(met); } } }
执行结果:
但是需要注意的是,这时的方法信息的获取是依靠Method类提供的toString()方法完成的,很多时候也可以由用户来拼凑方法信息的展示形式。
范例:自定义方法信息显示
import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class JavaAPIDemo { public static void main(String[] args) throws Exception { Class<?> cls = Person.class; // 获取指定类的Class对象Method methods[] = cls.getMethods(); for (Method met:methods){int mod=met.getModifiers();//修饰符System.out.print(Modifier.toString(mod)+">);System.out.print(met.getReturnType().getName()+" ");System.out.print(met.getName()+"("); Class<?> params [] = met.getParameterTypes();//获取参数类型for (int x = 0; x < params.length; x ++) {System.out.print(params[x].getName() + " " + "arg-" + x);if(x < params.length - 1) {System.out.println(","); } }System.out.print(")");class<?> exp [] = met.getExceptionTypes();if(exp.length > 0) {System.out.print("throws"); } for(int x = 0 ; x < exp.length ; x ++) {System.out.print(exp[x].getName());if(x < exp.length - 1) {System.out.println(","); } }System.out.println(); //换行} } }
这种代码只需要清楚可以根据反射获取方法的结构即可,不需要过多深入了解,但在Method类中有一个致命的重要方法:
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
在Person类里面为name属性追加有setter、getter方法。
public class Person extends AbstractBase implements IChannelService,IMessageService {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age; }public String getName() {return name; }public void setName(String name) {this.name = name; }// 其他操作代码略}
需要通过反射机制来实现Person类之中的setter与getter方法的调用处理。
范例:在不导入指定类开发包的情况下实现属性的配置
public class JavaAPIDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mladn.vo.Person"); //获取指定类的Class对象// String attribute = "name"; //要操作的类属性String value = "小强子"; //要设置的属性内容//1.任何情况下如果要想保存类中的属性或者调用类中的方法都必须保证存在有实例化对象,既然不允许导入包,那么就反射实例化Object obj = cls.getDeclaredConstructor().newInstance(); //调用无参构造实例化//2.如果要想进行方法的调用,那么一定要获取方法的名称String setMethodName = "setName"; //方法名称 Method method = cls.getDeclaredMethodsetMethodName, String.class); //获取指定的方法method.invoke(obj, value); //等价于:Person对象.setName(value);String getMethodName="getName";method=cls.getDeclaredMethod(getMethodName); //getter没有参数System.out.println(getMethod.invoke(obj);); //等价于:Person对象.getName();} }
利用此类操作整体的形式上不会有任何明确的类对象产生,一切都是依靠反射机制处理的,这样的处理避免了与某一个类耦合问题。
到此,相信大家对“如何使用反射调用方法”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。