反射及其相关类

反射

    Java反射机制是在程序的运行过程中,对于任何一个类,都能够知道它的所有属性和方法;对于任意一个对象,都能够知道它的任意属性和调用它的任意方法,这个动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
    反射机制是Java的动态特性之一(动态语言:在程序运行时,可以改变程序的结构或变量的类型)。Java 不是动态语言,但具有一定的动态性,可以称为”准动态语言”,具备类似动态语言的特性。
    反射机制对程序的运行在性能上有一定的影响,速度慢,可以禁止安全检查(setAccessible 启用和禁用访问安全检查,true为不执行安全检查),可以提高反射的运行速度。
常用功能

  • 动态的加载类、动态的获取类的信息(属性,方法,构造器)
  • 判定对象所属的类
  • 动态构造对象
  • 动态调用类和对象的任意方法、构造器
  • 动态调用和处理属性
  • 获取泛型信息
  • 处理注解

反射的实现

    Java.lang.reflect包实现了反射机制。

获取对象信息

    public static void main(String[] args) {
        Class car = null;
        try {
            car = Class.forName("test.reflact.Car");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //获取对象的所有公共属性
        Field[] fields = car.getFields();
        //获取对象所有属性,不包含父类的
        Field[] declaredFields = car.getDeclaredFields();
    }

动态构造对象一

    public static void main(String[] args) throws ClassNotFoundException,
            IllegalAccessException, InstantiationException {
        Class car = Class.forName("test.reflact.Car");
        Car c = (Car) car.newInstance();
        c.setName("car");
        System.out.println(c);
    }

动态构造对象二

    public static void main(String[] args) throws ClassNotFoundException,
            NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class car = Class.forName("test.reflact.Car");
        Constructor constructor = car.getConstructor(String.class);
        Car c = (Car) constructor.newInstance("car");
        System.out.println(c);
    }

调用方法

    public static void main(String[] args) throws ClassNotFoundException,
            NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        Class car = Class.forName("test.reflact.Car");
        Method method = car.getMethod("toString");
        Object c = method.invoke(new Car("car"));
        System.out.println(c);
    }

反射操作泛型

  • ParameterizedType:表示一种参数化的类型 ,比如Collection<String>,可以获取 String信息
  • GenericArrayType:泛型数组类型
  • TypeVariable:各种类型变量的公共父接口
  • WildcardType:代表一种通配符类型表达式,比如? extends Number,? super Integer。(Wildcard 是一个单词,就是通配符)
package test.generic;

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 TestGeneric {
    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        //获取test01方法的泛型参数信息
        Class c = TestGeneric.class;
        Method test01 = c.getMethod("test01", Map.class, List.class, String.class);
        //获取带泛型参数的类型
        Type[] tytes = test01.getGenericParameterTypes();
        for (Type type : tytes) {
            System.out.println(type); 
            //1.java.util.Map<java.lang.String, java.lang.Integer>
            //2.java.util.List<java.lang.Integer>
            //3.class java.lang.String 这次不是泛型
            if (type instanceof ParameterizedType) {
                Type[] genericType = ((ParameterizedType) type).getActualTypeArguments();
                //遍历每一个泛型参数中泛型的类型
                for (Type genType : genericType) {
                    //1.1 : 泛型类型:class java.lang.String
                    //1.2 : 泛型类型:class java.lang.Integer
                    System.out.println("泛型类型:" + genType);
                    //2.1 : 泛型类型:class java.lang.Integer
                }
            }
        }
        System.out.println("------------------------------");
        //获取test02方法返回值的泛型信息
        Method m2 = c.getMethod("test02", null);
        Type returnType = m2.getGenericReturnType();
        System.out.println(returnType);//java.util.Map<java.lang.Integer, java.lang.Integer>
        //判断是否带有泛型
        if (returnType instanceof ParameterizedType) {
            Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();
            for (Type type : types) {
                System.out.println("返回值的泛型类型:" + type);
                //1.返回值的泛型类型:class java.lang.Integer
                //2.返回值的泛型类型:class java.lang.Integer
            }
        }
        System.out.println("------------------------------");
        Method m3 = c.getMethod("test03", null);
        Type returnType3 = m3.getGenericReturnType();
        System.out.println(returnType3);//class java.lang.String
        System.out.println(returnType3 instanceof ParameterizedType);//false
    }

    public void test01(Map<String, Integer> map, List<Integer> list, String s) {}
    public Map<Integer, Integer> test02() {return null;}
    public String test03() {return null;}
}

反射操作注解

package com.annotation.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import com.annotation.Field;
import com.annotation.Table;

public class Test {
	public static void main(String[] args) throws Exception {
		//(1)创建Student类的Class对象
		Class clazz=Class.forName("com.entity.Student");
		//(2)得到Student类的所有注解
		Annotation [] annotations=clazz.getDeclaredAnnotations();
		for (Annotation a : annotations) {
			System.out.println(a);
		}
		//(3)获取指定的注解
		System.out.println("\n----------------------------");
		//Table为类上的注解
		Table st=(Table) clazz.getDeclaredAnnotation(Table.class);
		System.out.println(st);
		
		//(4)获取属性的注解
		System.out.println("\n----------------------------");
		Field field=clazz.getDeclaredField("stuName");
		//Field为属性上的注解
		Field sf=field.getDeclaredAnnotation(Field.class);
		System.out.println(sf.columnName()+"--"+sf.type()+"--"+sf.length());
	}
}

Class类

    一个类被加载后,JVM 会创建一个对应类的 Class 对象,类的整个结构信息会被放到Class 对象中。这个Class 对象就像镜子一样,通过这面镜子,可以得到对应类的全部信息。
    
获取 Class对象的方式

  • 对象的getClass()方法:thread.getClass()
  • Thread.class
  • Class 类的静态方法 forName(….):Class.forName(java.lang.Thread)

Field、Method

Modifier、ClassLoader


版权声明:本文为gao_tianLiang原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。