java反射

jasmine 于 2019-02-06 发布

什么是反射

在程序动态运行时,动态加载并获取类的信息,从而操作类的属性和方法,本质是通过JVM的class对象的反编译,获取类的各种信息,不关注对象是谁

原理

反射原理

优缺点

优点:

缺点:

反射优化

如何提高反射性能:

反射应用场景

反射机制常用的类

基本使用

1、Java.lang.Class;

public class ClassTest {

    public static void main(String[] args) throws ClassNotFoundException{
        Person person = new Student();
        System.out.println("这个人是"+person.name);

        //方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());///result:  2101842856

        //方式二:forName获得
        Class c2 = Class.forName("com.jasmine.reflect.Student");
        System.out.println(c2.hashCode());///result:  2101842856

        //方式三:通过类名.Class获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());///result:  2101842856

        //方式四:基本内置类型的包装类都有一个Type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4.hashCode());///result:  1151020327


        //获得父类
        Person person1 = new Person();
        Class superclass1 = c1.getSuperclass();
        Class c5 = person1.getClass();
        System.out.println(superclass1.hashCode());///result:  1225616405
        System.out.println(c5.hashCode());///result:  1225616405
    }
}

class Person{
    public String name;

    public Person() {
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Student extends Person{

    public Student(){
        this.name = "学生";
    }
}

class Teacher extends Person{
    public Teacher(){
        this.name="老师";
    }
}

Java.lang.reflect.Constructor;

public class ConstructorTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        /**
         * 1、创建对象
         */
        Class personClazz = Class.forName("com.jasmine.reflect.dto.Person");//通过【Class.forName】创建Person对象

        /**
         * 2、获得类名
         */
        System.out.println("=============================获得类的名字");
        System.out.println(personClazz.getName());  //获取类的完整名字(即:包名+类名),结果为:reflection.User
        System.out.println(personClazz.getSimpleName());  //获取类的简单名字(即:类名),结果为:User
        System.out.println(personClazz.getSuperclass());  //获取父类
        System.out.println(personClazz.getSuperclass().getName());  //获取父类
        System.out.println(personClazz.getInterfaces());  //获取接口
        System.out.println(personClazz.getAnnotations());  //获取注解


        Class<?> aClass = Class.forName(personClazz.getSuperclass().getName());
        Constructor<?>[] constructors1 = aClass.getConstructors();
        for (Constructor constructor : constructors1) {
            System.out.println("获得父类的构造器"+constructor);
        }

        System.out.println("=============================获得构造器");
        Constructor[] constructors = personClazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("获得public的构造器"+constructor);
        }

        Constructor[] declaredConstructors = personClazz.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println("获得任意范围的构造器"+declaredConstructor);
        }
    }
}

Java.lang.reflect.Field;

public class FieldTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        /**
         * 1、创建对象
         */
        Class c1 = Class.forName("com.jasmine.reflect.dto.Person");//通过【Class.forName】创建Person对象

        System.out.println("=============================获得类的所有public属性");
        Field[] fields = c1.getFields();
        for (Field f1 : fields) {
            System.out.println(f1);  //结果为:只获得了Person类中的oublic属性
        }

        System.out.println("==============================获得类的所有任意属性");
        Field[] declaredFields = c1.getDeclaredFields();  //注:getDeclaredFields有s
        for (Field f2 : declaredFields) {
            System.out.println(f2);  //结果为:获得了Person类中的所有属性
        }

        System.out.println("=============================获得类的某个public属性");
        Field wangming = c1.getField("id");
        System.out.println(wangming);

        System.out.println("=============================获得类的某个任意属性");
        Field name = c1.getDeclaredField("name");
        System.out.println(name);
        com.jasmine.reflect.dto.Person person = (com.jasmine.reflect.dto.Person) c1.newInstance();
        name.setAccessible(true);
        name.set(person, "张三");
        System.out.println(person.getName());

    }
}

Java.lang.reflect.Method;

public class MethodTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        /**
         * 1、创建对象
         */
        Class c1 = Class.forName("com.jasmine.reflect.dto.Person");//通过【Class.forName】创建Person对象

        /**
         * 4、获得类的方法
         */
        System.out.println("=============================获得类的所有方法");
        Method[] ms = c1.getMethods();
        for (Method m : ms){
            System.out.println(m);  //获得和本类和父类的所有public方法:equals、toString、hashCode、get&set、notify、notifyAll
        }

        //又是相见恨晚哪!!!先实战用了,才在视频里学到这个。
        System.out.println("=============================获得指定方法");
        //前一个参数是方法名,后一个参数是方法需要传入的参数的类型(没有就填null)。要抛出异常
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        System.out.println("=============================执行指定方法");
        Method walk = c1.getMethod("walk", String.class);
        com.jasmine.reflect.dto.Person person = (com.jasmine.reflect.dto.Person) c1.newInstance();
        walk.invoke(person,"哈哈");
    }
}

Java.lang.reflect.Modifier;

public class ModifierTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("com.jasmine.reflect.dto.Person");//通过【Class.forName】创建Person对象
        Method[] methods = c1.getMethods();

        System.out.println("=============方法展示=============");
        for (Method method : methods) {
            System.out.println("方法名:" + method.getName());
            System.out.println("返回值类型:"+method.getReturnType().getName());

            Class[] params = method.getParameterTypes();
            if (params.length == 0) {
                System.out.println("该方法没有参数");
            }else {
                System.out.print("该方法的参数类别为:[");
                for (int i = 0; i < params.length; i++) {
                    if (i != 0) {
                        System.out.print(", ");
                        System.out.print(params[i].getName());
                    }
                }
                System.out.println("]");
                System.out.println("-----------------------------------");
            }
            int modifier  = method.getModifiers();

            if ((modifier & Modifier.STATIC) == Modifier.STATIC) {
                System.out.println("这是一个静态方法");
            }
            if ((modifier & Modifier.FINAL) == Modifier.FINAL) {
                System.out.println("这是一个FINAL方法");
            }
            if ((modifier & Modifier.ABSTRACT) == Modifier.ABSTRACT) {
                System.out.println("这是一个抽象方法");
            }
            if ((modifier & Modifier.SYNCHRONIZED) == Modifier.SYNCHRONIZED) {
                System.out.println("这是一个同步方法");
            }

            Class declaringClass = method.getDeclaringClass();
            System.out.println("方法声明在:"+declaringClass.getName()+"中");


            Class[] exceptions = method.getExceptionTypes();
            if (exceptions.length > 0) {
                System.out.println("该方抛出的异常有:[");
                for (int i = 0; i < exceptions.length; i++) {
                    if (i != 0) {
                        System.out.println(", ");
                        System.out.println(exceptions[i].getName());
                    }
                    System.out.println("]");
                }
                System.out.println("-------------------------------");
            }
        }
    }
}

泛型获取

public class MethodTest {
    //定义一个需要传入泛型参数的方法
    public void test01(Map<String, Person> map, List<Person> list) {
        System.out.println("test01");
    }

    //定义一个返回泛型的方法
    public Map<String, SecurityProperties.User> test02() {
        System.out.println("test02");
        return null;
    }

    public static void ttt() throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("泛型的样子是:" + genericParameterType);
        }
    }
}

result:
泛型的样子是java.util.Map<java.lang.String, com.jasmine.reflect.Person>
泛型的样子是java.util.List<com.jasmine.reflect.Person>

注解获取

public class Test10 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.jdsydwr.reflection.Student2");

        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        //获取注解的value
        TableName tableName = (TableName)c1.getAnnotation(TableName.class);
        String value = tableName.value();
        System.out.println(value);

        //获取类指定的注解
        Field f = c1.getDeclaredField("Name");
        FieldName annotation = f.getAnnotation(FieldName.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }



}

@TableName("db_student")
class Student2{

    @FieldName(columnName = "db_id",type = "int",length = 10)
    private int id;
    @FieldName(columnName = "db_age",type = "int",length = 10)
    private int age;
    @FieldName(columnName = "db_name",type = "String",length = 3)
    private String Name;

    public Student2() {
    }

    public Student2(int id, int age, String name) {
        this.id = id;
        this.age = age;
        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;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", Name='" + Name + '\'' +
                '}';
    }
}

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

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldName{
    String columnName();
    String type();
    int length();
}

new实例

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

        Class clz = Class.forName("entity.Person");
        Constructor cl = clz.getDeclaredConstructor();
        Object obj = cl.newInstance();


        Constructor c3 = clz.getDeclaredConstructor(String.class,String.class,String.class);
        c3.setAccessible(true);
        obj = c3.newInstance("new Person", "beijing", "Hello");
        System.out.println(obj);


        Object person  = clz.newInstance();

        Field name = clz.getDeclaredField("name");
        name.setAccessible(true);
        name.set(person,"张三");
        System.out.println("赋值后的 name:" +name.get(person));
    }
}

获取final属性值

public class Person extends Animal implements Fly {
    private final String food="cookie";
    public String getFood() {
        return food;
    }
}
public class FieldTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        System.out.println("=============================获取final属性");
        Field food = c1.getDeclaredField("food");
        System.out.println("111" + food);
        com.jasmine.reflect.dto.Person person2 = (com.jasmine.reflect.dto.Person) c1.newInstance();
        food.setAccessible(true);
        food.set(person2, "面包");
        System.out.println("222" + person2.getFood());///222cookie
        System.out.println("333" + food.get(person2));///333面包
    }
}