A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Camwly 中级黑马   /  2015-11-30 23:38  /  330 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  什么时反射,根据个人理解,就是通过一个类的字节码获取和使用这个类里面的方法、字段、构造方法等。
  所以反射,首先是要获得类的字节码。其中获取字节码的方法有3种:
  1.使用Class类的forName(String className)静态方法,className表示全限定名;如String的全限定名:java.lang.String。
  2.调用某个对象的getClass()方法。该方法属于Object类。如Class<?> clz=new String().getClass。
  3.调用某个类的class属性获取Class对象,如Date.class会返回Date类对应的Class对象(其实就是得到一个类的一份字节码文件);
  接下来就是如何通过一个类的字节码获取和使用这个类里面的方法、字段、构造器。这就要涉及到java里提供的类:Constructor类、Method、Field、Annotation等类。
  先说Constructor类,Constructor类用于描述类中的构造方法。
  Class类中用于处理Constructor类的方法:
  Constructor<T> getConstructor(Class<?>... parameterTypes);返回该Class对象表示类的指定的public构造方法;
  Constructor<?>[] getConstructors();返回该Class对象表示类的所有public构造方法;
  Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);返回该Class对象表示类的指定的构造方法,和访问权限无关;
  Constructor<?>[] getDeclaredConstructors();返回该Class对象表示类的所有构造方法,和访问权限无关;
  newInstance();利用构造方法创建对象。(该方法属于Constructor类)
  例子代码如下:
package bokedemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Class<ConstrutorDemo> clz=ConstrutorDemo.class;
        //获取参数为int的构造器
        Constructor<ConstrutorDemo> constructor=clz.getConstructor(int.class);
        System.out.println(constructor);
        //获取public修饰的构造方法
        Constructor<?>[] constructors=clz.getConstructors();
        for (Constructor<?> constructor2 : constructors) {
                System.out.println(constructor2);
        }
        //获取参数String被private修饰的构造方法
        Constructor<ConstrutorDemo> constructorprivate=clz.getDeclaredConstructor(String.class);
        System.out.println(constructorprivate);
        //获取所有构造方法包括private修饰的构造方法
        Constructor<?>[] constructorsall=clz.getDeclaredConstructors();
        for (Constructor<?> constructor2 : constructorsall) {
                System.out.println(constructor2);
        }
        //设置使用时不检查该构造方法是否为私有
        constructorprivate.setAccessible(true);
        //利用获得的Constructor对象获得相应类的对象
        ConstrutorDemo cdemo=constructorprivate.newInstance("hao");
}
}
class ConstrutorDemo
{
        public ConstrutorDemo(){
                System.out.println("public no param");
        }
        public ConstrutorDemo(int i){
                System.out.println("public has param");
        }
        private ConstrutorDemo(String str){
                System.out.println("private has param");
        }
}
  接着是Method类,Method类用于描述类中的方法。
  Class类中用于Method类的方法有:
  Method getMethod(String name, Class<?> ... parameterTypes):返回该Class对象表示类和其父类的指定的public方法;
  Method[] getMethods():返回该Class对象表示类和其父类的所有public方法;
  Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回该Class对象表示类的指定的方法。和访问权限无关,但不包括继承的方法;
  Method[] getDeclaredMethods(): 获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;
  invoke(Object obj,Object ... args):obj表示调用底层方法的对象,后面的args表示传递的实际参数。如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 如果底层方法所需的形参个数为 0,则所提供的 args 数组长度可以为 0 或 null(不写,null,或 new Object[]{})。(该方法属于Method)
  例子代码如下:
package bokedemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectDemo {
public static void main(String[] args) throws Exception{
        //获取字节码
        Class<?> clz=MethodDemo.class;
        MethodDemo mdemo=(MethodDemo) clz.newInstance();
        //通过反射获得参数为int和String的public修饰的名为methodpublic的方法。
        Method method=clz.getMethod("methodpublic", new Class<?>[]{int.class,String.class});
        //通过反射调用参数为int和String的public修饰的名为methodpublic的方法。
        method.invoke(mdemo, new Object[]{1,"hao"});
        //通过反射获取所有的public修饰的方法包括从父类继承的public方法。
        Method[] methods=clz.getMethods();
        for (Method method2 : methods) {
                System.out.println(method2);
        }
        //通过反射获得参数为int被private修饰的名为methodprivate的方法。
        Method methodprivate=clz.getDeclaredMethod("methodprivate", int.class);
        //设置使调用时不被检查
        methodprivate.setAccessible(true);
        //通过反射调用参数为int被private修饰的名为methodprivate的方法。
        methodprivate.invoke(mdemo, new Object[]{1});
        // 获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;
        Method[] methodall=clz.getDeclaredMethods();
        for (Method method2 : methodall) {
                System.out.println(method2);
        }
       
}
}
class MethodDemo
{
        public void methodpublic()
        {
                System.out.println("methodpublic1 no param");
        }
        public void methodpublic(int i)
        {
                System.out.println("methodpublic1 has one param int");
        }
        public void methodpublic(int i,String str)
        {
                System.out.println("methodpublic1 has two param int and string");
        }
        private void methodprivate()
        {
                System.out.println("methodprivate no param");
        }
        private void methodprivate(int i)
        {
                System.out.println("methodprivate has one param int");
        }
        private void methodprivate(int i,String str)
        {
                System.out.println("methodprivate has two param int and string");
        }
}
  然后是Field类,Field类用于描述类中的字段。
  Class类中用于处理Field类的主要方法:
  Field getField(String name) :返回该Class对象表示类和其父类的指定的public字段;  
  Field[] getFields() :返回该Class对象表示类和其父类的所有public字段;
  Field getDeclaredField(String name):返回该Class对象表示类的指定的字段和访问权限无关,但不包括继承的字段;
  Field[] getDeclaredFields():返回当前Class对象中公共、保护、默认(包)访问和私有字段,但不包括继承的字段;
  get(Object object):返回指定字段的值。(该方法属于Field)
  Setxxx(Object obj,xxx val):将obj对象的该Field字段设置成val值,此处的xxx表示8个基本数据类型。若该字段的类型是引用数据类型则使用,void set(Object obj, Object value);(该方法属于Field)
  最后是Annotation类,Annotation类用于描述类中的注释。
  Class类中用于处理Annotation类的主要方法:
  <A extends Annotation> A  getAnnotation(Class<A> annotationClass):如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null;
Annotation[] getAnnotations():返回此元素上存在的所有注释;
Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释;
boolean isAnnotationPresent(Class<? extends Annotation> clz) :如果clz注释存在于此元素上,则返回 true,否则返回 false ;


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马