Java中的反射(Reflection)

反射是Java被视为准动态语言的关键,反射机制允许程序在执行期间借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及其方法(包括private关键字修饰的)

想要获取或操作类创建的对象的内部属性及其方法,首先就要获取该类的Class对象,该类的Class对象是在初始化的时候创建的

1、获得类的Class对象

public class TestReflection {
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一:通过实例化对象获得
        Class c1 = new TestReflection().getClass();
        //方式二:forName方法获得
        Class c2 = Class.forName("com.hu.www.reflection.TestReflection");
        //方式三:通过类名获得
        Class c3 = TestReflection.class;
        //输出并对比它们的hashCode
       	System.out.println(c1.hashCode() +"\n"+ c2.hashCode() +"\n"+ c3.hashCode());
    }
}

得到的3个hashCode都是相同的,说明一个类只有一个Class对象

2、获取运行时类的完整结构

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//获取类的信息
public class TestReflection {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class aClass = Class.forName("com.hu.www.reflection.User");

        //1、获得类的名字
        System.out.println(aClass.getName());                   //获得包名 + 类名
        System.out.println(aClass.getSimpleName());             //获得类名

        Field[] declaredFields = aClass.getDeclaredFields();    //可以找到所有的属性,包括私有的
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        //2、获得指定属性值
        Field name = aClass.getDeclaredField("name");           //可以找到private修饰的属性
        System.out.println(name);

        //3、获得类的所有方法
        methods = aClass.getDeclaredMethods();                  //获得本类的所有方法,包括私有的
        for (Method method : methods) {
            System.out.println("getDeclaredMethods:\t" + method);
        }

        //4、获得指定方法
        Method getName = aClass.getMethod("getName", null);
        Method setName = aClass.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        //5、获得指定的构造器
        Constructor[] constructors = aClass.getConstructors();
        Constructor[] declaredConstructors = aClass.getDeclaredConstructors();
        Constructor constructor = aClass.getConstructor(String.class, int.class, int.class);
        System.out.println(constructor);
    }
}

class User{
    private String name;
    private int id;
    private int age;

    public User() {
    }

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

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

3、创建运行时类的对象并调用方法和属性

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

//通过反射动态地创建对象
public class TestReflection {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //获得Class对象
        Class aClass = Class.forName("com.hu.www.reflection.User");

        //1、通过Class对象调用newInstance方法创建对象
        User user1 = (User)aClass.newInstance();
        System.out.println(user1);

        //2、通过Class对象获取构造器对象,构造器对象再调用newInstance方法创建对象
        Constructor constructor = aClass.getConstructor(String.class, int.class, int.class);
        User user2 = (User)constructor.newInstance("Hu", 001, 18);
        System.out.println(user2);

        //3、通过反射调用普通方法
        User user3 = (User)aClass.newInstance();
        //该类的Class对象通过反射获取方法
        Method setName = aClass.getMethod("setName", String.class);
        //获取到的方法对象调用invoke方法激活
        setName.invoke(user3,"Hu");
        System.out.println(user3.getName());

        //4、通过反射调用属性
        User user4 = (User)aClass.newInstance();
        //该类的Class对象通过反射获取属性
        Field name = aClass.getDeclaredField("name");
        //关闭权限检测
        name.setAccessible(true);
        //获取到的属性对象调用set方法设置,不能直接操作私有属性,需要关闭程序的安全检测
        name.set(user4,"hu");
        System.out.println(user4.getName());
    }
}

class User{
    private String name;
    private int id;
    private int age;

    public User() {
    }

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

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

4、反射操作泛型

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

//通过反射获取泛型
public class TestReflection {
    
    public void test01(Map<String,User> map,List<User> list){
        System.out.println("test01");
    }

    public Map<String,User> test02(){
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        //1、获取参数的泛型信息
        //通过反射获取方法
        Method method = TestReflection.class.getMethod("test01", Map.class, List.class);
        //方法对象调用getGenericParameterTypes方法获取泛型类型
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            //循环输出所有泛型类型
            System.out.println(genericParameterType);
            //判断泛型的类型是否为ParameterizedType--参数化类型
            if (genericParameterType instanceof ParameterizedType){         
                //泛型类型为参数化类型,强转为ParameterizedType--参数化类型;并使用getActualTypeArguments方法获取它的真实参数信息
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    //循环输出所有泛型的真实类型
                    System.out.println(actualTypeArgument);
                }
            }
        }

        System.out.println("-----------------------------------------------------");

        //2、获取返回值的泛型信息
        //通过反射获取方法
        method = TestReflection.class.getMethod("test02",null);
        //方法对象调用getGenericReturnType方法获取泛型类型
        Type genericReturnType = method.getGenericReturnType();     
        //判断泛型的类型是否为ParameterizedType--参数化类型
        if (genericReturnType instanceof ParameterizedType){         
            //泛型类型为参数化类型,强转为ParameterizedType--参数化类型;并使用getActualTypeArguments方法获取它的真实参数信息
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                //循环输出所有泛型的真实类型
                System.out.println(actualTypeArgument);
            }
        }
    }
}

5、反射操作注解

package com.hu.www.reflection;

import java.lang.annotation.*;
import java.lang.reflect.Field;

//联系反射操作注解
public class TestReflection12 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //创建Student2类的Class对象
        Class aClass = Class.forName("com.hu.www.reflection.Student");

        //通过反射获得注解
        Annotation[] annotations = aClass.getAnnotations();
        //获得Student2类的注解
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //获得Student2类的注解value的值
        TableHu tableHu = (TableHu)aClass.getAnnotation(TableHu.class);
        System.out.println(tableHu.value());

        //获得类指定属性的注解
        Field field = aClass.getDeclaredField("name");
        FieldHu annotation = field.getAnnotation(FieldHu.class);
        //获得Student2类的name属性的注解信息
        System.out.println("列名:" + annotation.columnName());
        System.out.println("类型:" + annotation.type());
        System.out.println("长度:" + annotation.length());
    }
}

@TableHu("db_student")
class Student{
    @FieldHu(columnName = "db_id",type = "int",length = 10)
    private int id;
    @FieldHu(columnName = "db_age",type = "int",length = 10)
    private int age;
    @FieldHu(columnName = "db_name",type = "varchar",length = 3)
    private String name;

    public Student(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableHu{
    String value();
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldHu{
    String columnName();
    String type();
    int length();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一只嘻嘻嘻

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

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

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

打赏作者

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

抵扣说明:

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

余额充值