# java反射

1、反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。
2、在方法区存在的类对象(Class),当new对象时,通过方法区的类对象在堆里创建实例;即每个堆里的对象都有在方法区里对应的类对象
java反射机制是在运行状态中,对任意类都能够操作其属性和方法。
3、Java反射机制主要提供了以下功能:
      在运行时判断任意一个对象所属的类。
      在运行时构造任意一个类的对象。
     在运行时判断任意一个类所具有的成员变量和方法。
     在运行时调用任意一个对象的方法(动态代理)

## test所需类

/**
 * 战士类
 */
public class FighterEntity {
    protected String name;//姓名
    public String sex;//性别
    protected int age;//年龄
    private String star;//所属星球
    private String sects;//所属门派
    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

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

    public String getStar() {
        return star;
    }

    public void setStar(String star) {
        this.star = star;
    }

  /**
 * 类注解
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAnn {
    String value() default "";
} 

/**
 * 字段注解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnn {
    String value() default "";
}

 public String getSects() {
        return sects;
    }

    public void setSects(String sects) {
        this.sects = sects;
    }
}

@ClassAnn("类注解测试")
public class SaiyaEntity extends FighterEntity{
    @FieldAnn("字段注解测试")
    private String arms;

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

    private SaiyaEntity(String name,String arms){
        this.name = name;
        this.arms = arms;
    }

    public SaiyaEntity(){

    }

    public String getArms() {
        return arms;
    }

    public void setArms(String arms) {
        this.arms = arms;
    }

    //变身 无参 无返回值
    public void evolution(){
        System.out.println(getName()+"变身为超级赛亚人");
    }

    //变身 有参 无返回值
    public void evolution(int no){
        System.out.println(getName()+"变身为超级赛亚人"+no);
    }

    //变身 有参 有返回值
    public String getEvolution(int no){
        return getName()+"变身为超级赛亚人"+no;
    }

    private void isHungry() {
        System.out.println(getName()+"饿了");
    }
}

## 获取类对象方法

1、 通过类名获取

2、 通过类路径获取

3、通过实例对象获取

/**
     * 获取类名
     * @throws Exception
     */
    @Test
    public void getClassObjTest() throws Exception {
        //1、通过类名获取
        Class clazz1 = FighterEntity.class;
        System.out.println(clazz1.getCanonicalName());
        //2、通过类路径获取
        Class clazz2 = Class.forName("com.example.entity.FighterEntity");

        //3、通过实例对象获取
        FighterEntity kklt = new FighterEntity();
        Class clazz3 = kklt.getClass();
    }

## 类对象操作

@Test
    public void classOpt(){
        Class clazz = SaiyaEntity.class;
        //获取类名称
        String name = clazz.getName();
        System.out.println("类名称:"+name);

        //得到父类
        Class superClass = clazz.getSuperclass();
        System.out.println("父类名:"+superClass.getName());

        //获取类加载器
        ClassLoader classLoader = clazz.getClassLoader();

        //获取资源
        URL resource = clazz.getResource("");

        //判断一个类是不是接口
        boolean anInterface = clazz.isInterface();

        //判断一个类是否是数组
        boolean isArray = clazz.isArray();
        
        //......
    }

## 属性操作

1、 获取属性对象Field

- getField获取public属性(包含父类属性)
- getDeclaredField获取所有属性(不包含父类的属性)

2、 属性对象Field操作

- public属性可以直接操作(包含父类属性)
- 非public属性需要setAccessible(true)(不包含父类属性)

/**
     * 类属性操作
     */
    @Test
    public void classFieldOpt() throws Exception {

        Class clazz = SaiyaEntity.class;
        Field[] pubFields = clazz.getFields();//public属性 可以拿到父类
        System.out.println("public属性:");
        for(Field field : pubFields){
            System.out.println(field.getName());
        }

        Field[] allFields = clazz.getDeclaredFields();//所有属性 不能拿到父类的属性
        System.out.println("所有属性:");
        for(Field field : allFields){
            System.out.println(field.getName());
        }

        SaiyaEntity kklt = new SaiyaEntity();//创建赛亚人战士
        kklt.setName("卡卡罗特");
        //public field操作
        Field sexField = clazz.getField("sex");
        sexField.set(kklt,"男");
        System.out.println(kklt.getName() +"性别:"+kklt.getSex());
        System.out.println("反射获取"+kklt.getName() +"性别:"+sexField.get(kklt));

        Field armsField = clazz.getDeclaredField("arms");//武器属性
        armsField.setAccessible(true);//操作权限
        armsField.set(kklt,"金箍棒");
        System.out.println(kklt.getName() +"武器:"+kklt.getArms());
        System.out.println("反射获取"+kklt.getName() +"武器:"+armsField.get(kklt));

    }

## 方法操作

1、 获取方法对象

- getMethod获取public方法(包含父类方法)
- getDeclaredMethod获取所有方法(不包含父类的方法)
2、方法对象Method操作

- public方法可以直接操作(包含父类方法)
    - 非public方法需要setAccessible(true)(不包含父类方法)
    - 通过invoke()调用方法(4种情况)

- 无参,无返回值
        - 有参无返回值
        - 有参有返回值
        - 无参,有返回值

/**
     * 类方法操作
     */
    @Test
    public void classMethodOpt() {
        try {
            Class<?> clazz = SaiyaEntity.class;//获取类对象
            SaiyaEntity kklt = new SaiyaEntity();//创建赛亚人战士 卡卡罗特
            kklt.setName("卡卡罗特");
            kklt.setArms("金箍棒");
            System.out.println("----------------无参数 无返回值test");
            Method evolution1 = clazz.getMethod("evolution");//无参数 无返回值 调用
            evolution1.invoke(kklt);
            System.out.println("----------------无参数 无返回值test--------------------");

            System.out.println("----------------有参数 无返回值test");
            Method evolution2 = clazz.getMethod("evolution",int.class);//有参数 无返回值 调用
            System.out.println("参数个数:"+evolution2.getParameterCount());//方法参数个数
            System.out.println("参数类型数组:"+ Arrays.toString(evolution2.getParameterTypes()));//方法参数类型数组
            evolution2.invoke(kklt,2);
            System.out.println("----------------有参数 无返回值test--------------------");

            System.out.println("----------------有参数 有返回值test");
            Method getEvolution = clazz.getMethod("getEvolution",int.class);//有参数 有返回值 调用
            System.out.println("参数类型数组:"+ getEvolution.getReturnType().getName());//返回值类型
            String str = (String)getEvolution.invoke(kklt,2);
            System.out.println(str);
            System.out.println("----------------有参数 有返回值test--------------------------");

            System.out.println("----------------非public方法test");
            //非public方法
            Method isHungry = clazz.getDeclaredMethod("isHungry");
            isHungry.setAccessible(true);
            isHungry.invoke(kklt);
            System.out.println("----------------非public方法test-------------------------");

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


    }

## 构造器(特殊的方法)

### getConstructor获取public构造器

### getDeclaredConstructor获取所有构造器

### 创建对象newInstance()

### 非public方法需要setAccessible(true)

/**
     * 类构造器操作
     */
    @Test
    public void classConstructorOpt() {
        try {
            Class<?> clazz = SaiyaEntity.class;//获取类对象
            Constructor[] pubConstructors = clazz.getConstructors();
            for(Constructor obj : pubConstructors){
                System.out.println("构造器名称:"+obj.getName()+"----构造器参数:"+obj.getParameterCount());
            }

            Constructor pubConstructor = clazz.getConstructor();
            System.out.println("构造器名称:"+pubConstructor.getName()+"----构造器参数:"+pubConstructor.getParameterCount());

            Constructor[] constructors = clazz.getDeclaredConstructors();
            for(Constructor obj : constructors){
                System.out.println("构造器名称:"+obj.getName()+"----构造器参数:"+obj.getParameterCount());
            }


            //创建无参对象
            Constructor constructor1 = clazz.getDeclaredConstructor();
            Object obj1 = constructor1.newInstance();

            //创建有参对象
            Constructor constructor2 = clazz.getDeclaredConstructor(String.class,String.class);
            constructor2.setAccessible(true);
            Object obj2 = constructor2.newInstance("卡卡罗特","金箍棒");
            System.out.println();
        }catch (NoSuchMethodException e){
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

## 注解操作

/**
     * 注解操作
     */
    @Test
    public void classAnnotationOpt() {
        try {
            Class<?> clazz = SaiyaEntity.class;//获取类对象

           ClassAnn classAnn = clazz.getAnnotation(ClassAnn.class);//获取类注解
            System.out.println(classAnn.value());

            Field armsField = clazz.getDeclaredField("arms");
            FieldAnn fieldAnn = armsField.getAnnotation(FieldAnn.class);
            System.out.println(fieldAnn.value());


        }catch (NoSuchFieldException e){
            e.printStackTrace();
        }
    }

反射思维导图:

javaxml反射 java 反射_System