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实例。

    @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类的常用方法:

方法名

功能说明

static Class forName(String name)

返回指定类名 name 的 Class 对象

Object newInstance()

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

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    

 

转载于:https://my.oschina.net/u/3387320/blog/3001810

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值