反射

Class类

  • jvm通过类加载器defineClass构造方法产生class对象(同一个类加载器只产生一个class类对象)

反射

  • Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制
  • 也就是说反射通过class类对象,获得类运行状态下的属性和方法

用法

public class Country {
    private final static int KEY=200;
    private static String CODE="00";
    public String name;
    private int population;

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

    private Country(int population) {
        this.population = population;
    }

    public Country(String name, int population) {
        this.name = name;
        this.population = population;
    }

    public String getName() {
        return name;
    }

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

    private int getPopulation() {
        return population;
    }

    private void setPopulation(int population) {
        this.population = population;
    }
    class China{
        private int population;

        public China(int population) {
            this.population = population;
        }

        public int getPopulation() {
            return population;
        }

        public void setPopulation(int population) {
            this.population = population;
        }
    }
}
  • 获取class
        /**
         * 获取class对象
         */
        Class country1=Country.class;//ClassLoader 进行类加载但是不初始化。
        Class country2=new Country().getClass();//获取的是已经被加载且初始化过后实例化运行中类的 Class 实例。
        try {
            Class country3=Class.forName("Country");//ClassLoader 进行类加载然后进行类的初始化
            System.out.println(country1);
            System.out.println(country2);
            System.out.println(country3);
            } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 

运行结果:

class Country
class Country
class Country
  • 获取变量
    返回一个 Field 对象,只能获取当前类或者其父类指定的 public 成员。
    public Field getField(String name)
    返回一个 Field 对象数组,只能获取当前类或者其父类所有 public 成员。
    public Field[] getFields()
    返回一个 Field 对象,只能返回当前类指定的所有类型成员(public、procted、private)。
    public Field getDeclaredField(String name)
    返回一个 Field 对象数组,只能返回当前类指所有类型成员(public、procted、private)。
    public Field[] getDeclaredFields()
            /**
             * 获取变量
             */

            //返回一个 Field 对象,只能获取当前类或者其父类指定的 public 成员。
            Field name = country3.getField("name");
            System.out.println(name);
            //返回一个 Field 对象数组,只能获取当前类或者其父类所有 public 成员。
            Field[] fields = country3.getFields();
            for (Field field:fields){
                System.out.println(field);
            }
            //返回一个 Field 对象,只能返回当前类指定的所有类型成员(public、procted、private)
            Field population = country3.getDeclaredField("population");
            System.out.println(population);
            //返回一个 Field 对象数组,只能返回当前类指所有类型成员(public、procted、private)。
            Field[] declaredFields = country3.getDeclaredFields();
            for (Field field:declaredFields){
                System.out.println(field);
            }

运行结果:

public java.lang.String Country.name
public java.lang.String Country.name
private int Country.population
private static final int Country.KEY
private static java.lang.String Country.CODE
public java.lang.String Country.name
private int Country.population
  • 获取构造方法

    返回一个 Constructor 对象,代表指定类的指定 public 构造方法。
    public Constructor getConstructor(Class<?>… parameterTypes)
    返回一个 Constructor 对象数组,代表指定类的所有 public 构造方法。
    public Constructor<?>[] getConstructors()
    返回一个 Constructor 对象,代表指定类的指定构造方法(不限制修饰符)。
    public Constructor getDeclaredConstructor(Class<?>… parameterTypes)
    返回一个 Constructor 对象数组,代表指定类的所有构造方法(不限制修饰符)。
    public Constructor<?>[] getDeclaredConstructors()

            /**
             * 获取构造方法
             */
            //返回一个 Constructor 对象,代表指定类的指定 public 构造方法。
            Constructor constructor=country3.getConstructor(String.class);
            System.out.println(constructor);
            //返回一个 Constructor 对象数组,代表指定类的所有 public 构造方法。
            Constructor[] constructors = country3.getConstructors();
            for (Constructor constructor1:constructors){
                System.out.println(constructor1);
            }
            //返回一个 Constructor 对象,代表指定类的指定构造方法(不限制修饰符)。
            Constructor constructor1 = country3.getDeclaredConstructor( int.class);
            System.out.println(constructor1);
            //返回一个 Constructor 对象数组,代表指定类的所有构造方法(不限制修饰符)。
            Constructor[] declaredConstructors = country3.getDeclaredConstructors();
            for (Constructor constructor2:declaredConstructors){
                System.out.println(constructor2);
            }

运行结果:


			public Country(java.lang.String,int)
			public Country(java.lang.String)
			public Country()
			private Country(int)
			public Country(java.lang.String,int)
			private Country(int)
			public Country(java.lang.String)
			public Country()
  • 获取方法

    返回一个 Method 方法,只能获取当前类或者其父类指定的 public 方法。
    public Method getMethod(String methodName,Class class)
    返回一个 Method 方法数组,只能获取当前类或者其父类所有 public 方法。
    public Method[] getMethods()
    返回一个 Method 方法,只能返回当前类指定的所有类型方法(public、procted、private)。
    public Method getDeclaredMethod(String name,Class class)
    返回一个 Method 方法数组,只能返回当前类指所有类型方法(public、procted、private)。
    public Method[] getDeclaredMethods()

            /**
             * 获取方法
             */
            //返回一个 Method 方法,只能获取当前类或者其父类指定的 public 方法。
            Method getName = country3.getMethod("setName",String.class);
            System.out.println(getName);
            //返回一个 Method 方法数组,只能获取当前类或者其父类所有 public 方法。
            Method[] methods = country3.getMethods();
            for (Method method:methods){
                System.out.println(method);
            }
            //返回一个 Method 方法,只能返回当前类指定的所有类型方法(public、procted、private)。
            Method getPopulation = country3.getDeclaredMethod("getPopulation");
            System.out.println(getPopulation);
            //返回一个 Method 方法数组,只能返回当前类指所有类型方法(public、procted、private)。
            Method[] declaredMethods = country3.getDeclaredMethods();
            for (Method method:declaredMethods){
                System.out.println(method);
            }

运行结果:

public void Country.setName(java.lang.String)
public java.lang.String Country.getName()
public void Country.setName(java.lang.String)
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 void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
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()
private int Country.getPopulation()
public java.lang.String Country.getName()
public void Country.setName(java.lang.String)
private int Country.getPopulation()
private void Country.setPopulation(int)

  • 修改变量
    修改私有变量+setAccessible(true);
    修改final 变量+ Field modifiersField = Field.class.getDeclaredField(“modifiers”);
    modifiersField.setAccessible(true);
    modifiersField.setInt(filed, filed.getModifiers()&~Modifier.FINAL);
            Class country = Class.forName("Country");
            //实例化对象
            Country newInstance = (Country) country.newInstance();
            //可以携带参数
            Country newInstance1= (Country) country.getConstructor(形参).newInstance(实参);
            /**
             * 修改变量
             *
             */
            // 修改public 变量
            Field name = country.getField("name");
            System.out.println(newInstance.name);
            name.set(newInstance,"china");
            System.out.println(newInstance.name);

            //修改 private 变量
            Field population = country.getDeclaredField("population");
            System.out.println(newInstance.getPopulation1());
            //私有变量要加权限
            population.setAccessible(true);
            population.set(newInstance,100);
            System.out.println(newInstance.getPopulation1());
            //修改静态变量
            Field code = country.getDeclaredField("CODE");
            code.setAccessible(true);
            String codef = (String) code.get(newInstance);
            System.out.println(codef);
            code.set(newInstance,"123");
            String codea = (String) code.get(newInstance);
            System.out.println(codea);
            //修改常量
            Field key = country.getDeclaredField("KEY");
            key.setAccessible(true);
            //去除final修饰符的影响,将字段设为可修改的
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(key, key.getModifiers()&~Modifier.FINAL);
            key.set(null,456);
            int keya = (int) key.get(newInstance);
            System.out.println(keya);

运行结果:

null
china
0
100
00
123
456
  • 调用方法
    public Object invoke(Object obj,Object… args):
    私有方法+.setAccessible(true);
            Class country = Class.forName("Country");
            //实例化对象
            Country newInstance = (Country) country.newInstance();
            Country newInstance1= (Country) country.getConstructor().newInstance();
            /**
             * 调取方法
             *
             */
            //public 方法
            System.out.println(newInstance.getName());
            Method setName = country.getMethod("setName", String.class);
            setName.invoke(newInstance,"jpy");
            System.out.println(newInstance.getName());
            //私有方法
            System.out.println(newInstance.getPopulation1());
            Method setPopulation = country.getDeclaredMethod("setPopulation", int.class);
            setPopulation.setAccessible(true);
            setPopulation.invoke(newInstance,1000000);
            System.out.println(newInstance.getPopulation1());
  • 反射内部类
    注意,内部内中存在外部类的引用,所以在构造方法记得把外部类引用加上
            Class country = Class.forName("Country");
            //实例化对象
            Country newInstanceOut = (Country) country.newInstance();
            //内部类反射名字需要使用$分隔,编译后生成的规则
            Class china = Class.forName("Country$China");
            Method setPopulation = china.getDeclaredMethod("setPopulation", int.class);
            //特别注意!!!!内部类newInstance的第一个参数必须是外部类实例的引用
            Constructor constructor =china.getDeclaredConstructor(Country.class,int.class);
            Country.China newInstanceInt= (Country.China)constructor.newInstance(newInstanceOut,66666);
            System.out.println(newInstanceInt.getPopulation());
            setPopulation.invoke(newInstanceInt,888888);
            System.out.println(newInstanceInt.getPopulation());

应用

  • 动态代理模式

public class NoOpProxy implements InvocationHandler {
    private WeakReference<Object> view;
    public NoOpProxy(Object view) {
        this.view = new WeakReference<>(view);
    }
    @Override
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
    if(view == null || view.get() == null) {
        LogUtil.e("mvp mView is null");
        return null;
    }
    
    return method.invoke(view.get(), args);
    }
}
Proxy.newProxyInstance(getClass().getClassLoader(), interfaces, new NoOpProxy(mView));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值