JAVA反射知识基本了解

JAVA反射机制是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。java

新建测试类:
public class Dog implements Animal  {

    private String name;

    String color;

    @Override
    public void say() {
        System.out.println("dog..say..");
    }

    public void run(){
        System.out.println("dog..run..");
    }

    public void eat(String S){
        System.out.println("dog..eat.."+S);
    }


    //....

    public Dog() {
    }

    public Dog(String name, String color) {
        this.name = name;
        this.color = color;
    }
}

第一步:理解class类

1.Class是一个类,封装了当前对象所对应的类的信息
2.一个类中有属性,方法,构造器等,好比说有一个Person类,一个Order类,这些都是不一样的类,如今须要一个类,用来描述类,这就是Class,
它应该有类名,属性,方法,构造器等。Class是用来描述类的类。
3.对于每一个类而言,JRE 都为其保留一个不变的 Class 类型的对象。
4.Class 对象只能由系统创建对象,一个类(而不是一个对象)在 JVM 中只会有一个Class实例。bootstrap

@Test
    public void test5(){
        Class clazz1=Dog.class;
        Class clazz2=Dog.class;
        System.out.println(clazz1);
        System.out.println(clazz2);
        System.out.println(clazz1==clazz2);//true
    }

获取Class对象的三种方式
1.经过类名获取      类名.class    
Class clazz=Dog.class;
2.经过对象获取      对象名.getClass()
Dog dog=new Dog();
Class clazz=dog.getClass();
3.经过全类名获取    Class.forName(全类名)    
Class clazz=Class.forName("com.utils.Dog");数组

Class类的经常使用方法:ide

方法名函数

功能说明工具

static Class forName(String name)测试

返回指定类名 name 的 Class 对象ui

Object newInstance()this

调用缺省构造函数,返回该Class对象的一个实例spa

Object newInstance(Object []args)

调用当前格式构造函数,返回该Class对象的一个实例

getName()

返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称

Class getSuperClass()

返回当前Class对象的父类的Class对象

Class [] getInterfaces()

获取当前Class对象的接口

ClassLoader getClassLoader()

返回该类的类加载器

Class getSuperclass()

返回表示此Class所表示的实体的超类的Class

 第二步:ClassLoader

类装载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构。

 

 

第三步:反射概述


Reflection(反射)是Java被视为动态语言的关键,反射机制容许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操做任意对象的内部属性及方法。
Java反射机制主要提供了如下功能:
在运行时构造任意一个类的对象
在运行时获取任意一个类所具备的成员变量和方法
在运行时调用任意一个对象的方法(属性)
生成动态代理

1.获取对象中的method
    public  void test() throws Exception {

        //获取Dog.class的对象
        Class dogClass=Dog.class;

        //获取Dog.class全部的方法,包括父类方法,不包括私有方法
        //Method[] methods=dogClass.getDeclaredMethods();

        //获取Dog.class全部的方法,包括私有方法,不包括父类方法
        Method[] methods=dogClass.getDeclaredMethods();
        for(Method method:methods){
            System.out.println(method.getName());
        }

        //返回该Class对象的一个实例
        Object objects= dogClass.newInstance();

        //获取无参方法 say( )
        Method method=dogClass.getDeclaredMethod("say");

        //第一个参数表示执行哪一个对象的方法,剩下的参数是执行方法时须要传入的参数
        method.invoke(objects,null);

        //获取带参方法 eat( ),参数类型为String.class
        method=dogClass.getDeclaredMethod("eat",String.class);

        method.invoke(objects,"骨头");

    }

 

2.获取对象中的field
  
    public void test() throws Exception{

        Class clazz=Dog.class;

        //获取全部字段属性,包括私有,不包括继承
        Field fields[]= clazz.getDeclaredFields();
        for (Field field:fields){
            System.out.println(field.getName()+"---"+field.getType());
        }

        //获取全部继承字段属性
        fields = clazz.getFields();
        for (Field field:fields){
            System.out.println(field.getName()+"---"+field.getType());
        }

        //获取非私有字段属性
        Field field=clazz.getDeclaredField("color");
        Object object=new Dog();
        //设置字段属性值
        field.set(object,"red");
        System.out.println("field.get(object)="+field.get(object));

        //获取私有字段属性
        field=clazz.getDeclaredField("name");
        object=new Dog();
        field.setAccessible(true);
        //设置字段属性值
        field.set(object,"tom");
        System.out.println("field.get(object)="+field.get(object));
    }

 

3.获取对象的构造方法
    public void test() throws Exception{

        Class clazz=Dog.class;

        //获取全部构造函数
        Constructor[] constructors= clazz.getConstructors();
        for (Constructor constructor:constructors){
            System.out.println(constructor);
        }

        //获取无参构造方法
        Constructor constructor= clazz.getConstructor(new Class[]{});
        System.out.println("无参构造 "+constructor);

        constructor=clazz.getConstructor(new Class[]{String.class,String.class});
        System.out.println("带参构造 "+constructor);
    }

 

5.看到这里,咱们本身动手设计一个工具方法。 
    //自定义反射方法  类对象和类方法名做为参数,执行方法
    public Object myInvoke(Class object,String methodName,Object...args) throws Exception, InstantiationException {

        //把参数转化为对应的class对象
        Class[] argsClass=new Class[args.length];
        for (int i=0;i<args.length;i++){
            argsClass[i]=args[i].getClass();
            System.out.println(argsClass[i]);
        }

        //获取方法
        Method method=object.getDeclaredMethod(methodName,argsClass);

        //执行方法
        return  method.invoke(object.newInstance(),args);
    }

测试:
 public void test() throws Exception {
        Object args[]=new Object[]{};
        Object result= myInvoke(Dog.class,"say",args);
        System.out.println("result="+result);
    }

 

6.咱们再设计一个工具方法,不但能访问当前类的私有方法,还要能访问父类的私有方法
通常使用getDeclaredMethod获取方法(由于此方法能够获取类的私有方法,可是不能获取父类方法),如何获取父类方法呢?
    public Method getMethodForClass(Class clazz,String methodName,Class[] parameterTypes) throws NoSuchMethodException {

        for(;clazz != Object.class; clazz = clazz.getSuperclass()){
            try {
                Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
                if(method==null){
                    continue;
                }
                return method;
            } catch (Exception e) {
                System.out.println(e);
            }
        }

        return clazz.getDeclaredMethod(methodName, parameterTypes);
    }

 

第四步:文章小结 1. Class: 是一个类; 一个描述类的类.封装了描述方法的 Method,描述字段的 Filed,描述构造器的 Constructor 等属性.   2. 如何获得 Class 对象: 2.1 Person.class 2.2 person.getClass() 2.3 Class.forName("com.atguigu.javase.Person")    3. 关于 Method: 3.1 如何获取 Method: 1). getDeclaredMethods: 获得 Method 的数组. 2). getDeclaredMethod(String methondName, Class ... parameterTypes)    3.2 如何调用 Method 1). 若是方法是 private 修饰的, 须要先调用 Method 的 setAccessible(true), 使其变为可访问 2). method.invoke(obj, Object ... args);    4. 关于 Field: 4.1 如何获取 Field: getField(String fieldName) 4.2 如何获取 Field 的值:  1). 若是Field是 private 修饰的, 须要先调用 Field 的 setAccessible(true),setAccessible(true) 2). field.get(Object obj) 4.3 如何设置 Field 的值: field.set(Obejct obj, Object val)    5. 了解 Constructor    

相关文章
相关标签/搜索