Java中反射的一些操作(实例化对象、修改/获取成员属性、借助反射获取/调用方法、调用构造方法(创建实例))

反射进行操作必须先获取类对象

实例化对象

在这里插入图片描述
1、先获取类对象(如何获取参考Java中面向对象编程的一个重要特征-自省(反射)机制,获取类对象
在这里插入图片描述
2、通过newInstance()进行实例化(可以不使用new关键字进行实例化)
在这里插入图片描述

  //通过反射来实例化对象
    public static void testInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class catClass = Class.forName("Cat");//获得类对象

        Cat cat = (Cat) catClass.newInstance();

    }

修改/获取成员属性

在这里插入图片描述
1、先获取类对象
2、借助类对象,获取到指定的Field对象
反射操作借助setAccessable()可以打破private的访问权限,当然也破坏了封装
3、根据图纸来修改/获取对象的相关字段

在这里插入图片描述

import java.lang.reflect.Field;

class Cat {
    private String name;

    public void eat(String food) {
        System.out.println(name + "正在吃" + food);
    }
}
public class TestReflect {

    //通过反射来获取对象的属性
    public static void teatField() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //1、先获取类对象
        Class catClass = Class.forName("Cat");//获得类对象
        //2、根据类对象获取,获取指定的Field对象
        //field对象相当于从整个图纸中获取了一个局部的部分
        //括号中加上需要获取的属性的名字
        Field field = catClass.getDeclaredField("name");
        field.setAccessible(true);//专门处理private成员
        //3、根据图纸来修改或者获取对象的相关字段
        Cat cat = new Cat();//创建一个对象
        //通过get方法获取cat这个对象中一个名为name的属性
        String name = (String) field.get(cat);
        System.out.println(name);
        //通过set方法修改cat这个对象中一个名为name的属性
        field.set(cat,"mimi");
        String name1 = (String) field.get(cat);
        System.out.println(name1);
}

    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, ClassNotFoundException {
        teatField();
    }
  }

 结果:  
null
mimi

借助反射获取/调用方法

在这里插入图片描述

1、先获取类对象
2、根据类对象,根据名字获取到指定的Method对象

如果有多个重名方法,getMethod 从第二个参数开始,其实就是用来描述当前调用的方法应该是哪个版本,方法出现重载的时候可以根据参数列表的类型进行区分

3、借助Method对象来调用指定的方法(对于非静态方法,需要指定实例进行调用)

在这里插入图片描述
依然可以借助setAccessable()可以打破private的访问权限,访问私有的方法
在这里插入图片描述

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

class Cat {
    private String name = "mimi";

    public void eat(String food) {
        System.out.println(name + "正在吃" + food);
    }
    public void eat(String food1, String food2) {
        System.out.println(name + "正在吃" + food1 + "和" + food2);
    }
}
public class TestReflect {

    public static void testMethod() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1、先获取类对象
        Class catClass = Class.forName("反射的使用.Cat");//获得类对象
        //2、根据类对象,根据名字获取到指定的Method对象
        // getMethod 从第二个参数开始,其实就是用来描述当前eat对应的方法应该是哪个版本
        Method method = catClass.getMethod("eat",String.class);//调用一个参数的eat方法
        Method method1 = catClass.getMethod("eat",String.class,String.class);//调用两个个参数的eat方法
        //3、借助Method对象来调用指定的方法(对于非静态方法,需要指定实例进行调用)
        Cat cat = new Cat();
        method.setAccessible(true);
        method1.setAccessible(true);
        method.invoke(cat,"鱼");//前面是要调用的对象,后面是传入调用方法的参数
        method1.invoke(cat,"鱼","肉");

}

    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
        testMethod();

    }

}


结果:
mimi正在吃鱼
mimi正在吃鱼和肉

调用构造方法(也是在创建实例)

1、先获取类对象
2、借助类对象获取Constructor对象
3、根据Constructor 实例化对象

根据传入参数进行调用构造方法
在这里插入图片描述
newInstance()进行实例化只能调用默认的构造方法
依然可以借助setAccessable()可以打破private的访问权限,访问私有的方法

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

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Cat {
    private String name = "mimi";
    public void eat() {

    }

    public Cat(String name) {
        this.name = name;
    }

    public void eat(String food) {
        System.out.println(name + "正在吃" + food);
    }
    public void eat(String food1, String food2) {
        System.out.println(name + "正在吃" + food1 + "和" + food2);
    }
}
public class TestReflect {
    public static void testConstructor() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1、先获取类对象
        Class catClass = Class.forName("反射的使用.Cat");//获得类对象
        //2、借助类对象获取Constructor对象
        //获取到参数为一个String 的构造方法
        Constructor constructor = catClass.getConstructor(String.class);
        constructor.setAccessible(true);//访问私有的构造函数
        //3、根据Constructor 实例化对象
        Cat cat = (Cat) constructor.newInstance("小黑");
        cat.eat("猫粮");
    }

    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        testConstructor();

    }

}

结果:
小黑正在吃猫粮

总代码:

package 反射的使用;

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

class Cat {
    private String name = "mimi";

    public Cat() {

    }

    public Cat(String name) {
        this.name = name;
    }

    public void eat(String food) {
        System.out.println(name + "正在吃" + food);
    }
    public void eat(String food1, String food2) {
        System.out.println(name + "正在吃" + food1 + "和" + food2);
    }
}
public class TestReflect {

    //通过反射来获取对象的属性
    public static void teatField() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //1、先获取类对象
        Class catClass = Class.forName("反射的使用.Cat");//获得类对象
        //2、根据类对象获取,获取指定的Field对象
        //field对象相当于从整个图纸中获取了一个局部的部分
        //括号中加上需要获取的属性的名字
        Field field = catClass.getDeclaredField("name");
        field.setAccessible(true);//专门处理private成员
        //3、根据图纸来修改或者获取对象的相关字段
        Cat cat = new Cat();//创建一个对象
        //通过get方法获取cat这个对象中一个名为name的属性
        String name = (String) field.get(cat);
        System.out.println(name);
        //通过set方法修改cat这个对象中一个名为name的属性
        field.set(cat,"mimi");
        String name1 = (String) field.get(cat);
        System.out.println(name1);
    }
    //通过反射来实例化对象
    public static void testInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class catClass = Class.forName("反射的使用.Cat");//获得类对象
        Cat cat = (Cat) catClass.newInstance();

    }

    public static void testMethod() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
       //1、先获取类对象
       Class catClass = Class.forName("反射的使用.Cat");//获得类对象
       //2、根据类对象,根据名字获取到指定的Method对象
       // getMethod 从第二个参数开始,其实就是用来描述当前eat对应的方法应该是哪个版本

       Method method = catClass.getMethod("eat",String.class);//调用一个参数的eat方法
       Method method1 = catClass.getMethod("eat",String.class,String.class);//调用两个个参数的eat方法
       //3、借助Method对象来调用指定的方法(对于非静态方法,需要指定实例进行调用)
       Cat cat = new Cat();
       method.setAccessible(true);
       method1.setAccessible(true);
       method.invoke(cat,"鱼");//前面是要调用的对象,后面是传入调用方法的参数
       method1.invoke(cat,"鱼","肉");

   }
    public static void testConstructor() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1、先获取类对象
        Class catClass = Class.forName("反射的使用.Cat");//获得类对象
        //2、借助类对象获取Constructor对象
        //获取到参数为一个String 的构造方法
        Constructor constructor = catClass.getConstructor(String.class);
        constructor.setAccessible(true);//访问私有的构造函数
        //3、根据Constructor 实例化对象
        Cat cat = (Cat) constructor.newInstance("小黑");
        cat.eat("猫粮");
    }

    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        teatField();
        testMethod();
        testInstance();
        testConstructor();

    }

}

反射优点和缺点

优点:
1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法 2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
2. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。

缺点:
1、 使用反射会有效率问题。会导致程序效率降低。
2、 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值