浅析Java反射

反射

反射是不是在编译时,而是在运行时,动态地获取类型的信息。比如接口信息、成员变量信息、方法信息、构造函数信息。根据这些动态获取的信息创建对象、访问/修改成员、调用方法。

一般的数据操作是是依赖于数据类型的

  • 使用new关键字创建相应类型的对象 new Cat();
  • 根据类型来定义变量。类可以是基本类型、类、接口、数组 Cat cat;
  • 将特定类型的变量传递给方法。 cat.eat(new food());
  • 根据类型访问类型的参数、调用类型的方法 cat.run(); int size=cat.size;

而反射则是动态的获取类型,而不是一开始就知道是什么类型。根据动态获取的类型创建对象,还可以访问/修改这个类型的信息。

动态获取类型信息

每个已经加载的类在内存里都会有一份类信息,每个对象都会有指向它所属类信息的引用。这个类信息对应的类是 java.lang.Class
类加载器将 .class 文件加载到内存会生成一个描述 .class文件的对象,这个对象对应的类就是Class类,这个对象包括成员变量、构造方法、成员方法

  1. 通过实例对象获取类信息
    public final native Class<?> getClass();这个方法是Object类的方法,所以每个类型的对象都可以调用这个方法来获取自己所属类信息的引用。即获取Class类对象。

  2. 通过类名、接口名获取类信息


  • Class<Date> cls = Date.class;=》class java.lang.Integer
  • 接口
    Class<Comparator> cls = Comparator.class;=》interface java.util.Comparator
  • 基本类型和void类型
    Class<Integer> integerClass = int.class;
    Class<Void> voidClass = void.class;
  • 数组
    Class<? extends int[][]> clsss = is.getClass();=》class [[I
  • 枚举
    Size.SMALL.getClass()=》class reflect.Test$Szie
  1. 通过String来获取Class对象
  try {
            Class<?> clad = Class.forName("java.applet.Applet");
            System.out.println(clad.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 

类信息用处

  1. 获取名称信息
  2. 获取字段信息 =》Field 获取该类所有字段的名称、获取或修改指定字段的访问权限、值
Class clazz = Person.class;
Object obj = clazz.newInstance();

Field[] fields = clazz.getFields();
for(Field s:fields){
    System.out.println(s);
}
//public 父类 
Field field=clazz.getField("name");

field.set(obj, "haha");

System.out.println(obj);
//包括非public ,不包括父类的
Field field2=clazz.getDeclaredField("idcard");
field2.setAccessible(true);
field2.set(obj, "123456");
System.out.println(obj);
  1. 获取方法信息 =》Method 获取该类所有方法的名称、获取或修改指定方法的访问权限、调用指定方法
 为Person类增加成员方法

    public void show(){
        System.out.println("show 空参数");
    }
    public void show(int a){
        System.out.println("show   a:"+a);
    }   
    private void show(String s){
        System.out.println("show   s:"+s);
    }

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException,
            NoSuchMethodException, SecurityException, InstantiationException,
            IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchFieldException {


        Class clazz = Person.class;
        Object obj = clazz.newInstance();
        
        Method [] methods=clazz.getMethods();

        for(Method m:methods){
            System.out.println(m);
        }

        Method m=clazz.getMethod("show");
        m.invoke(obj);

        Method m1=clazz.getMethod("show",int.class);
        m1.invoke(obj,1);

        Method m2=clazz.getDeclaredMethod("show",String.class);
        m2.setAccessible(true);
        m2.invoke(obj,"smt");
    }
}


输出结果:
Person类无参数构造
public java.lang.String com.test.demo.Person.toString()
public void com.test.demo.Person.show(int)
public void com.test.demo.Person.show()
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 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()
show 空参数
show   a:1
show   s:smt
  1. 获取构造方法 =》Constructor 获取该类的构造方法、或者指定参数类型的构造方法、创建对象
public Person(){
        System.out.println("Person类无参数构造");
    }
    public Person(int a,int b,String s){
        System.out.println("Person类有参数构造:a:"+a+" b:"+b+" s:"+s);
    }

    private Person(int a){
        System.out.println("Person类有参数   私有 构造:a:"+a);
    }



package com.test.demo;

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

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        Class clazz=Person.class;
        
        Constructor [] conarr=clazz.getConstructors();

        for(Constructor con :conarr){
            System.out.println(con);
        }
        
        
        Constructor cc=clazz.getConstructor();
        Object oo=cc.newInstance();

        
        Constructor cc2=clazz.getConstructor(int.class,int.class,String.class);
        Object oo2=cc2.newInstance(1,2,"haha");

        
        Constructor cc3=clazz.getDeclaredConstructor(int.class);
        
        cc3.setAccessible(true);
        Object oo3=cc3.newInstance(1);

        clazz.newInstance();
    }
}

输出结果
public com.test.demo.Person()
public com.test.demo.Person(int,int,java.lang.String)
Person类无参数构造
Person类有参数构造:a:1 b:2 s:haha
Person类有参数   私有 构造:a:1
Person类无参数构造

反射举例

menu图标显示

  1. 获取menu对象
  2. 设置图标显示方法的访问权限
  3. 调用该方法,设Visbility为true
    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (menu != null) {
            if(menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
                try {
                    Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    method.setAccessible(true);
                    method.invoke(menu, true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    }
        return super.onMenuOpened(featureId, menu);
}

参考博客:https://juejin.im/entry/57c3dd6279bc440063e7d59f

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值