Java学习笔记—反射

一、反射的定义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
注:反射式框架的基石,大部分主流的框架都用到了反射技术

二、Class类

  • Class类位于java.lang包下
  • Class类代表着Java中所有的类,是类的再往上抽象

(一)获取Class类的三种方法

  • 方法一:通过Class.forName(“类的全路径”)
  • 方法二:通过类的名字打点class,如:Person.class
  • 方法三:通过调用该类的对象调用getClass()方法

示例:

public class Test
{
    public static void main(String[] args) throws ClassNotFoundException
    {

        // 【方法一】通过Class.forName("类的全路径")
        Class<?> clazz1 = Class.forName("java.lang.String");
        // 【方法二】通过类的名字打点class,如:String.class
        Class<?> clazz3 = String.class;
        // 【方法三】通过调用该类的对象调用getClass()方法
        String str = new String();
        Class<?> clazz2 = str.getClass();

        prints(clazz1);
        prints(clazz2);
        prints(clazz3);

    }

    /**
     * 打印类的所有方法
     * @param clazz
     */
    public static void prints(Class<?> clazz)
    {
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method m : declaredMethods)
        {
            System.out.println(m);
        }
    }

}

(二)Class类的常用方法

返回值方法声明用法说明
Constructor<T>getDeclaredConstructor(Class<?>… parameterTypes)获得构造器
FieldgetDeclaredField(String name)获得指定字段
Field[]getDeclaredFields()获得所有字段
MethodgetDeclaredMethod(String name, Class<?>… parameterTypes)获得指定方法
Method[]getDeclaredMethods()获得所有方法

示例:

package pl_reflect;

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

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Class<?> clazz = Class.forName("pl_reflect.Person");
        // 获得对象的一个属性
        Field field = clazz.getDeclaredField("address");
        System.out.println(field);

        // 获得一个具体的方法
        Method method = clazz.getDeclaredMethod("getName", new Class[] {});
        Method method1 = clazz.getDeclaredMethod("setName", new Class[] { String.class });
        System.out.println(method);
        System.out.println(method1);

        // 获得构造器
        Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[] {});
        System.out.println(constructor);

        Constructor<?> constructor2 = clazz
                .getDeclaredConstructor(new Class[] { Integer.class, String.class, String.class });
        System.out.println(constructor2);

    }

}

class Person
{

    private Integer id;
    private String name;
    private String address;

    public Person()
    {

    }

    public Person(Integer id, String name, String address)
    {
        super();
        this.id = id;
        this.name = name;
        this.address = address;
    }

    public Integer getId()
    {
        return id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getAddress()
    {
        return address;
    }

    public void setAddress(String address)
    {
        this.address = address;
    }

}

三、通过反射进行方法的调用

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Class<?> class1 = Class.forName("pl_reflect.Person");
        //获得构造器
        Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{});
        //根据类的默认构造器来获得一个对象
        Object instance=constructor.newInstance(new Object[]{});
        //获得方法
        Method method = class1.getDeclaredMethod("setName", new Class[]{String.class});
        //调用方法赋值
        Object invoke = method.invoke(instance, new Object[]{"张三"});
    }

}
  • 如果底层方法是实例方法,第一个参数就是该对象的实例,第二个参数是方法的参数列表,invoke的返回值就是实例方法的返回值
  • 如果底层方法是静态的,那么可以忽略指定的obj参数,该参数可以为null
  • 如果底层方法所需的形参数为0,则所提供的args数组长度可以为0或null

四、通过反射进行属性的设值

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Class<?> class1 = Class.forName("pl_reflect.Person");
        //获得构造器
        Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{});
        //根据类的默认构造器来获得一个对象
        Object instance=constructor.newInstance(new Object[]{});
        //根据属性名字来获得属性对象
        Field field = class1.getDeclaredField("name");
        //破坏掉私有属性
        field.setAccessible(true);
        //设置属性的值
        field.set(instance, "张三");

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值