【java系列】java反射使用和实践

大家好,我是walker
一个从文科自学转行的程序员~
爱好编程,偶尔写写编程文章和生活
欢迎关注公众号【I am Walker】,一块学习编程~

什么是反射机制?

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

反射的使用

案例,以该类作为实验对象

package reflectTest;

import lombok.Data;

@Data
public class Person {

    private String name;
    private Integer age;
    private String sex;
    /**
     * 新增身高体重
     */
    public String height;
    public String weight;

    /**
     * 默认构造器
     */
    public Person(){}


    /**
     * 含一个参数的构造器
     */
    public Person(String name){
        this.name=name;
    }

    /**
     * 含有多个参数的构造器
     */
    public Person(String name,Integer age,String sex){
        this.name=name;
        this.age=age;
        this.sex=sex;
    }

    /**
     * 私有构造器
     */
    private Person(String name,Integer age){
        this.name=name;
        this.age=age;
    }
}

获取类对象

方式有下面三种:
1、类.class
2、对象.getClass()
3、Class.forName(“全路径”)

package reflectTest;

public class CreateClass {


    public static void main(String[] args) throws ClassNotFoundException {
        //方式一:类.class
        Class<Person> personClass = Person.class;
        System.out.println(personClass);

        //方式二:对象.getClass()
        Class<? extends Person> aClass = new Person().getClass();
        System.out.println(aClass);
        //Class.forName("全路径")
        Class<?> aClass1 = Class.forName("reflectTest.Person");
        System.out.println(aClass1);

    }


}

输出结果:

class reflectTest.Person
class reflectTest.Person
class reflectTest.Person

利用反射创建对象

使用反射创建对象一般有2种方式,

方式一:类对象.newInstance()

package reflectTest;

import lombok.SneakyThrows;

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

public class ReflectDemo {


    @SneakyThrows
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        ReflectDemo reflectDemo = new ReflectDemo();
        reflectDemo.createObj();
    }

    /**
     * 利用反射创建对象
     *
     */
    public void createObj() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        /**
         * 方式一:类对象.newInstance()
         */
        //1、获取Class
        Class<Person> personClass = Person.class;
        //2、对象.newInstance()
        Person person = personClass.newInstance();
        System.out.println(person);
    }


}

不过使用这种方式创建的对象,具有一定的局限性,获取的对象只能是使用无参构造器所创建的,如果要创建较为复杂的对象,应该使用构造器对象去创建对象

方式二:构造器对象.newInstance()

涉及到构造器,那么我们先做几种情况的处理,
首先对于构造器的参数,包含无参和有参
以及对于访问权限,包含私有的和公有的,如下:
image.png

之后可以使用getConstructorsgetDeclaredConstructors查看一下我们定义的构造方法
getConstructors:获取公有的构造方法
getDeclaredConstructors:获取所有构造方法
getConstructor:获取单个公有的构造方法
getDeclaredConstructor获取单个构造方法,可以是私有的和受保护的

  /**
     * 测试获取所有的构造器
     */
    public void getConstructors(){
        Class<Person> personClass = Person.class;
        Constructor<?>[] constructors = personClass.getConstructors();
        System.out.println("getConstructors==>");
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }

        System.out.println("getDeclaredConstructors==>");
        for (Constructor<?> declaredConstructor : personClass.getDeclaredConstructors()) {
            System.out.println(declaredConstructor);
        }

    }

调用之后的返回结果:

getConstructors==>
public reflectTest.Person(java.lang.String,java.lang.Integer,java.lang.String)
public reflectTest.Person(java.lang.String)
public reflectTest.Person()
getDeclaredConstructors==>
private reflectTest.Person(java.lang.String,java.lang.Integer)
public reflectTest.Person(java.lang.String,java.lang.Integer,java.lang.String)
public reflectTest.Person(java.lang.String)
public reflectTest.Person()
使用实践
package reflectTest;

import lombok.SneakyThrows;

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

public class ReflectDemo {


    @SneakyThrows
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        ReflectDemo reflectDemo = new ReflectDemo();
        reflectDemo.createObj2();
    }


    /**
     * 利用构造器创建对象
     * 方式二:构造器对象.newInstance()
     */
    public void createObj2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<Person> personClass = Person.class;
        /**
         * 获取默认构造器
         */
        Constructor<Person> constructor = personClass.getConstructor();
        Person person2 = constructor.newInstance();
        System.out.println(person2);

        /**
         * 获取含单个参数构造器
         * public reflectTest.Person(java.lang.String)
         */
        Constructor<Person> constructor1 = personClass.getConstructor(String.class);
        Person walker = constructor1.newInstance("walker");
        System.out.println(walker);


        /**
         * 获取含多个参数构造器
         * public reflectTest.Person(java.lang.String,java.lang.Integer,java.lang.String)
         */
        Constructor<Person> constructor2 = personClass.getConstructor(String.class, Integer.class, String.class);
        Person person = constructor2.newInstance("walker", 18, "男");
        System.out.println(person);


        /**
         * 获取私有构造器
         * private reflectTest.Person(java.lang.String,java.lang.Integer)
         */
        Constructor<Person> constructor3 = personClass.getDeclaredConstructor(String.class, Integer.class);
        constructor3.setAccessible(true);
        Person walker1 = constructor3.newInstance("walker", 18);
        System.out.println(walker1);


    }






}

注意:
如果是private构造方法的话,是无法使用getConstructor去获取构造器的,否则只会抛出异常,当然单纯使用getDeclaredConstructor也是无法创建对象的,因为是私有的构造方法,抛出异常如下:

Class reflectTest.ReflectDemo can not access a member of class reflectTest.Person with modifiers "private

解决方式:
设置成可进入的状态

constructor3.setAccessible(true);

属性与变量

/**
         * 测试获取属性
         */
        public void getField() throws NoSuchFieldException {
            Class<Person> personClass = Person.class;
            Field[] declaredFields = personClass.getDeclaredFields();
            System.out.println("所有属性");
            for (Field declaredField : declaredFields) {
                System.out.println(declaredField);
            }
            Field[] fields = personClass.getFields();
            System.out.println("公有属性");
            for (Field field : fields) {
                System.out.println(field);
            }

            System.out.println("获取单个属性");
            //获取公有的变量,如果是非公有的,则会抛出异常
            System.out.println(personClass.getField("weight"));
            //获取单个变量,任意声明的属性都可以
            System.out.println(personClass.getDeclaredField("name"));
        }

返回结果:

所有属性
private java.lang.String reflectTest.Person.name
private java.lang.Integer reflectTest.Person.age
private java.lang.String reflectTest.Person.sex
public java.lang.String reflectTest.Person.height
public java.lang.String reflectTest.Person.weight
公有属性
public java.lang.String reflectTest.Person.height
public java.lang.String reflectTest.Person.weight
获取单个属性
public java.lang.String reflectTest.Person.weight
private java.lang.String reflectTest.Person.name

总结:
getDeclaredFields:获取所有属性
getFields: 获取所有公有属性
getDeclaredField: 获取任意声明的单个属性
getField:获取单个公有属性,如果没有会抛出异常

修改对象的变量

public void set(Object obj, Object value):用于修改指定对象的属性

        /**
         * 获取变量并修改
         */
        public void getValiableAndChange() throws NoSuchFieldException, IllegalAccessException {
            Person person = new Person();
            person.setName("walker");
            person.setAge(18);
            System.out.println("修改前:"+person);
            Field name = person.getClass().getDeclaredField("name");
            /**
             * obj:被修改对象,value:值
             * public void set(Object obj, Object value)
             * throws IllegalArgumentException, IllegalAccessException
             */
            /**
             * 因为name属性是private修饰的,所以如果没有设置”accessible”,就会抛出该异常
             * Class reflectTest.ReflectDemo can not access a member of class reflectTest.Person with modifiers "private"
             */
            name.setAccessible(true);
            name.set(person,"shen");

            System.out.println("修改后:"+person);

        }

返回结果:

修改前:Person(name=walker, age=18, sex=null, height=null, weight=null)
修改后:Person(name=shen, age=18, sex=null, height=null, weight=null)

成员方法

getMethods:获取所有公有方法
getDeclaredMethods:获取所有方法
getMethod:获取单个公有方法
getDeclaredMethod:获取单个任意方法

/**
         * 获取方法
         */
        public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            Class<Person> aClass = Person.class;
            Method[] methods = aClass.getMethods();
            System.out.println("获取公有方法");
            for (Method method : methods) {
                System.out.println(method);
            }
            System.out.println("获取全部方法");
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                System.out.println(declaredMethod);
            }

            /**
             * 获取公有方法并调用
             *
             * public Method getMethod(String name, Class<?>... parameterTypes)
             */
            Person person = new Person();
            Method testPublic = aClass.getMethod("testPublic", String.class);
            testPublic.invoke(person,"walker");


            /**
             * 获取私有方法,并调用
             */
            /**
             * public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
             */
            Method testPrivate = aClass.getDeclaredMethod("testPrivate", String.class);
            /**
             * 该方法为私有方法,若想调用,需要设置为accessable
             */
            testPrivate.setAccessible(true);
            testPrivate.invoke(person,"hello");

        }

返回结果:

获取公有方法
public boolean reflectTest.Person.equals(java.lang.Object)
public java.lang.String reflectTest.Person.toString()
public int reflectTest.Person.hashCode()
public java.lang.String reflectTest.Person.getName()
public void reflectTest.Person.setName(java.lang.String)
public void reflectTest.Person.testPublic(java.lang.String)
public void reflectTest.Person.setAge(java.lang.Integer)
public java.lang.Integer reflectTest.Person.getAge()
public java.lang.String reflectTest.Person.getSex()
public void reflectTest.Person.setWeight(java.lang.String)
public java.lang.String reflectTest.Person.getWeight()
public void reflectTest.Person.setSex(java.lang.String)
public java.lang.String reflectTest.Person.getHeight()
public void reflectTest.Person.setHeight(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
获取全部方法
public boolean reflectTest.Person.equals(java.lang.Object)
public java.lang.String reflectTest.Person.toString()
public int reflectTest.Person.hashCode()
public java.lang.String reflectTest.Person.getName()
public void reflectTest.Person.setName(java.lang.String)
public void reflectTest.Person.testPublic(java.lang.String)
public void reflectTest.Person.setAge(java.lang.Integer)
public java.lang.Integer reflectTest.Person.getAge()
public java.lang.String reflectTest.Person.getSex()
private void reflectTest.Person.testPrivate(java.lang.String)
public void reflectTest.Person.setWeight(java.lang.String)
public java.lang.String reflectTest.Person.getWeight()
public void reflectTest.Person.setSex(java.lang.String)
public java.lang.String reflectTest.Person.getHeight()
public void reflectTest.Person.setHeight(java.lang.String)
protected boolean reflectTest.Person.canEqual(java.lang.Object)
公有方法,输出结果为:walker
私有方法,输出结果为:hello

Process finished with exit code 0

参考:
Java 反射 -超详细讲解(附源码)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WalkerShen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值