javase复习——反射

概述

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

Class类

我们知道类是具有相同属性或者行为的一类事物,那么类本身也可以再被抽象,因为类们也有共同的属性和行为(比如类都有属性,都有构造器,都有方法,都能调用方法),所以把类们又抽象成了一个类Class。

众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。

Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。

在学习Class类的过程中我们还需要学习Field类,Method类,Constructor类

  • Field类:类属性的抽象
  • Method类:类方法的抽象
  • Constructor类:类构造器的抽象

获得一个类的Class的方法

  • 方法一:通过Class.forName(“类的全路径”)
    try {
        Class<Person> aClass = (Class<Person>) Class.forName("com.zdd.Servlet.Person");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
  • 方法二:通过类的名字打点class,如:Person.class
      Class<Person> personClass = Person.class;
  • 方式三:通过调用该类的对象调用getClass()方法
     Person person = new Person();
     person.getClass();

其中第二种和第三种式最常用的方法

常用方法

在这里插入图片描述
在这里插入图片描述

Method类反射调用

在这里插入图片描述

  • 如果底层方法是实例方法,第一个参数就是该对象实例,第二个参数是方法的参数列表,invoke的返回值就是实例方法的返回值。

  • 如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。

  • 如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。

假设有个Person类

public class Person {

    private String name;

    private Integer age;

    private Integer gender;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public Person() {
    }

    public Person(String name, Integer age, Integer gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }

    public static void selectTasks(){
        System.out.println("查找所有任务");
    }

    public void getTask(int i){
        System.out.println(name+"接收了任务"+i);
    }

    public void completeTask(){
        System.out.println(name+"完成了任务");
    }
}

用反射的方式调用Person的getTask方法,这个方法有1个参数

    public static void main(String[] args) {
        //创建实例对象
        Person person = new Person("zdd",18,1);
        //得到实例对象的Class类
        Class<? extends Person> personClass = person.getClass();
        Method[] methods = personClass.getDeclaredMethods();

        for (Method md : methods){
            if (md.getName().equals("getTask")){
                try {
                    md.invoke(person, 1);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }

    }

结果

zdd接收了任务1

用反射的方式调用Person的selectTasks方法,这个方法是一个静态方法

    public static void main(String[] args) {
        //创建实例对象
        Person person = new Person("zdd",18,1);
        //得到实例对象的Class类
        Class<? extends Person> personClass = person.getClass();
        Method[] methods = personClass.getDeclaredMethods();

        for (Method md : methods){
            if (md.getName().equals("selectTasks")){
                try {
                    md.invoke(null);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }

    }

结果

查找所有任务

用反射的方式调用Person的completeTask方法,这个方法没有参数

    public static void main(String[] args) {
        //创建实例对象
        Person person = new Person("zdd",18,1);
        //得到实例对象的Class类
        Class<? extends Person> personClass = person.getClass();
        Method[] methods = personClass.getDeclaredMethods();

        for (Method md : methods){
            if (md.getName().equals("completeTask")){
                try {
                    md.invoke(person);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }

    }

结果

zdd完成了任务

Field类要掌握的方法

在这里插入图片描述

Constructor类要掌握的方法

在这里插入图片描述

反射的一些操作示例

通过反射来拷贝对象

	public static Object copyObject(Object obj) throws Exception{
		//获得传递过来的对象的属性和构造器
		Class<? extends Object> class1 = obj.getClass();
		Field[] fields = class1.getDeclaredFields();
		Constructor<? extends Object> constructor = class1.getConstructor(new Class[]{});
		//创建一个对象
		Object instance = constructor.newInstance(new Object[]{});
		for(Field f :fields){
			//获得属性的name
			String fname = f.getName();
			//获得属性的类型
			Class<?> type = f.getType();
			//获得属性对应的set方法
			String setMethodName = "set"+fname.substring(0, 1).toUpperCase()+fname.substring(1);
			String getMethodName = "get"+fname.substring(0, 1).toUpperCase()+fname.substring(1);
			//获得get方法
			Method gmethod = class1.getDeclaredMethod(getMethodName, null);
			//调用get方法获得被拷贝的对象的一个属性值
			Object gresult = gmethod.invoke(obj, null);
			//获得set方法
			Method smethod = class1.getDeclaredMethod(setMethodName, new Class[]{gmethod.getReturnType()});
			smethod.invoke(instance, new Object[]{gresult});
		}			
		return instance;
	}

反射方式访问私有属性

	public static void main(String[] args) throws Exception {
		Class<?> class1 = Class.forName("cn.tx.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, "张三");
		
		//获得属性的类型
		Class<?> type = field.getType();
		System.out.println(type);
	}

反射方式访问私有方法

	public static void main(String[] args) throws Exception {
		Class<?> class1 = Class.forName("cn.tx.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[]{"张三"});
		
		//Method mget = class1.getDeclaredMethod("getName", new Class[]{});
		
		Method mget = class1.getDeclaredMethod("getName", null);
		Object invoke2 = mget.invoke(instance, new Object[]{});
		
		Method method2 = class1.getDeclaredMethod("printInfo", null);
		//破坏私有方法,让我们能调用
		method2.setAccessible(true);
		Object invoke3 = method2.invoke(null, null);
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值