java基础-反射3(反射,反射创建对象,操作对象属性,调用对象方法)

java基础-反射3(反射,反射创建对象,操作对象属性,调用对象方法)

前面通过学习,我们了解的运行时类型信息的基本原理,以及通过Class对象和反射来获取运行时类型信息。下面来了解通过反射来创建对象,以及操作对象的属性和方法

首先还是创建一个person类


@Service
public class Person1 extends PersronParent implements PersonInterfance ,Cloneable{
    public  String name;
    public  double weight;
    protected  double height;
    private Integer age;

    public Person1(){}

    protected Person1(String name){
    }
    public void publicShow() throws Exception{
        System.out.println("publicShow()");
    }
    protected void disPlay(){
        System.out.println("disPlay()");

    }

    private String privateShow(String paramter1,String paramter2) throws NullPointerException{
        StringBuffer stringBuffer  = new StringBuffer(paramter1);
        return stringBuffer.append(paramter2).toString();
    }
    @Deprecated
    private int testParamter(String paramter1,String paramter2) throws NullPointerException{
        return 1;
    }

    @Deprecated
    public int testPublicParamter(String paramter1,String paramter2) throws NullPointerException{
        return 1;
    }

    @Override
    public void parentSay(){
        super.parentSay();
    }

    public String getName() {
        return name;
    }

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

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public Integer getAge() {
        return age;
    }

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

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

通过反射来创建对象

通常在java中我们有以下4中方式创建对象

  1. 通过new 关键字 创建对象
  2. 通过Object clone();方法
  3. 通过反序列化
  4. 通过反射创建

这里我们来了解通过反射来创建对象和调用方法

首先我们来看通过反射来创建对象
我们通过newInstance()来创建对象,如果对于无参数的构造方法我们直接用Class的对象的newInstance()就可以创建对象
如果对于有参数的构造方法,我们需要先获取带参数的构造器(注意权限修饰符),然后通过构造器的newInstance()方法创建对象。

public class TestReflect {

    public static void main(String[] agrs){

            Class<Person> personClass = Person.class;
            try {
                /**
                 * 通过无参数的构造方法创建对象
                 */
                Person personOne =   personClass.newInstance();
                /**
                 * 通过有参数的构造方法创建对象
                 */
                Constructor constructor = personClass.getDeclaredConstructor(String.class);
                Person personTwo =   (Person) constructor.newInstance("带参数");

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

    }

}

运行结果如下
这里写图片描述

这样我们就可以通过反射来创建对象。
通过反射创建对象后可以通过反射来给操作对象的属性

通过反射操作对象属性

上一篇文章说过,类的属性在反射中使用java.lang.reflect.Field表示,当然也使用这个类来操作对象的属性,在java中属性的访问涉及到权限修饰的修饰,具体如下:
这里写图片描述

所以在操作对象的属性的需要注意对目标类属性访问的权限,如下
如果当前类对目标对象有访问的权限(如目标类属性为public)

  1. 通过Class对象的getField()获取Field。
  2. 然后通过Field的set()方法对目标对象赋值。

如果当前类对目标对象没有访问的权限(如目标类属性为private)

  1. 通过Class对象的getDeclaredField()获取Field。
  2. 调用Field 的setAccessible(true)方法,设置为可访问(如果不设置为true,则在当前类中不能访问目标类的属性,在为目标对象赋值时会报错)
  3. 然后通过Field的set()方法对目标对象赋值。
  4. 调用Field 的setAccessible(false)方法复原。

具体操作如下

public class TestFileId2 {
    public static void main(String agrs[]) throws NoSuchFieldException {
        try {
            //获取Class 对象
            Class<Person> personClass  = Person.class;
            //创建目标对象(注意,我们这里直接用的object,更体现了运行时类型信息)
            Object person = personClass.newInstance();
            //在没有通过反射赋值之前
            System.out.println("person对象在没有赋值之前");
            System.out.println(person.toString());
            System.out.println();

            System.out.println("当前类可以操作目标类的属性:比如public权限的属性");
            //获取有权限操作的属性(当前类可以操作目标对象的属性:比如public)
            Field name = personClass.getField("name");
            //为person 对象 的 name属性赋值为 TestName
            name.set(person,"TestName");
            System.out.println(person.toString());
            System.out.println();

            System.out.println("当前类不能够操作目标类的属性:比如private权限的属性");
            Field age = personClass.getDeclaredField("age");
            //为person 对象 的 age 属性设置为可访问
            age.setAccessible(true);
            //为person 对象 的 age属性赋值为 10
            age.set(person,10);
            age.setAccessible(false);
            System.out.println(person.toString());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下
这里写图片描述

通过反射调用对象方法

反射能够操作对象的属性,当然也可以操作对象的方法,方法通过java.lang.reflect.Method表示,由于访问权限的限制,对于方法也有如下操作
如果当前类对目标对象有访问的权限(如目标类方法为public)

  1. 通过Class对象的getMethod()获取Method。
  2. 然后通过Method的invoke()方法对目标对象赋值。

如果当前类对目标对象没有访问的权限(如目标类方法为private)

  1. 通过Class对象的getDeclaredMethod()获取Method。
  2. 调用Method的setAccessible(true)方法,设置为可访问(如果不设置为true,则在当前类中不能访问目标类的方法,在调用目标类的方法时会报错)
  3. 然后通过Method的invoke()方法对目标对象赋值。
  4. 调用Method的setAccessible(false)方法复原。

具体操作如下:

public class TestMethod2 {
    public static void main(String agrs[]) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        try {
            //获取Class 对象
            Class<Person> personClass = Person.class;
            //创建目标对象
            Object person = null;
            person = personClass.newInstance();

            System.out.println("当前类可以操作目标类的方法:比如public权限的方法");
            //获取有权限操作的方法(当前类可以操作目标对象的方法:比如public)
            Method publicShow = personClass.getMethod("publicShow");
            //通过Method 的invoke 调用person 的 publicShow方法
            publicShow.invoke(person);


            System.out.println("当前类不能够操作目标类的方法:比如private权限的方法");
            Method privateShow = personClass.getDeclaredMethod("privateShow", String.class, String.class);
            //为person 对象 的 privateShow 方法设置为可访问
            privateShow.setAccessible(true);
            //通过Method 的invoke 调用person 的 privateShow方法
            String result = (String) privateShow.invoke(person, "参数1", "参数2");
            System.out.println(result);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

}

运行结果如下:
这里写图片描述

以上就是通过反射操作对象的基本方式。

反射的基础知识就是以上几篇文章,反射相对于其他知识来说比较简单,但是反射应用很多,比如很多框架,以及java中的动态代理等都涉及到了,所以反射在java中还是很重要的。

猜你喜欢

转载自blog.csdn.net/hubin916/article/details/78771893
今日推荐