Java 反射机制学习

Java的反射机制

Java 反射机制
    1.Java反射机制是什么?
    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
    2.Java反射机制的作用:
    (1)获得动态加载类的修饰符,包名,类名,使用的接口,继承的父类
    (2)动态获取类的所有属性名,修饰符,属性类型
    (3)动态获取所有定义的构造器,构造器使用的参数数量和参数类型
    (4)动态获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型
    (5)动态调用加载类的方法
    3.Java中Class类的获取:
    Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。然而,class类就是Java反射的根源。
   
    Class类的获取:
    1.通过每个类的隐含的静态成员变量获取
    2.通过对象的getClass()方法获取
    3.通过Class.forName("全名")方式获取

// 第一种方式:通过每个类的隐含的静态成员变量获取
		Class<? extends Student> class1 = Student.class;
		// 第二种方式:通过对象的getClass()方法获取<br>
		Student stu = new Student(1, "s");
		Class<? extends Student> class2 = stu.getClass();
		// 第三种方式:通过Class.forName("全名")方式获取
		Class<? extends Student> class3 = null;
		try {
			class3 = (Class<? extends Student>) class3.forName("com.usc.lilin.demo.Student");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		System.out.println("calss1:" + class1);
		System.out.println("calss2:" + class2);
		System.out.println("calss3:" + class3);
		System.out.println("calss1==class3?:" + (class1 == class3));
		System.out.println("calss2==class1?:" + (class1 == class2));
		System.out.println("calss2==class3?:" + (class3 == class2));

 

 为什么会发生这样子呢?

class1、class2、class3 都是Student的类类型。在Java中,一个类只可能是Class的一个实例对象,所以三者均相等

4.Java类的动态加载:
        通过.newInstance()方法创建对象

   

Student student = class1.newInstance();

 5.class的常用API

/**
	 * 获取对象的类的方法的信息
	 * 
	 * @param obij
	 */
	public static void getClassMethMSG(Object obj) {
		Class<? extends Object> class1 = obj.getClass();
		// 获取对象的全名
		String name = class1.getName();
		// 获取对象的简名、 不包含包名
		String simpleName = class1.getSimpleName();
		// 获取对象的父类
		Class<?> superclass = class1.getSuperclass();
		// 获取对象实现的接口
		Class<?>[] interfaces = class1.getInterfaces();
		// 获取对象的类型名称
		String typeName = class1.getTypeName();
		// 获取对象的方法 ,不管修饰符,不能获取父类的方法
		Method[] methods = class1.getDeclaredMethods();
		// 获取对象的public方法,包括父类的方法
		Method[] methods2 = class1.getMethods();
		for (Method method : methods) {
			getMethodMSG(method);
		}
		// 获取对象所在的包
		Package package1 = class1.getPackage();
		// 获取对象的成员变量
		Field[] fields = class1.getFields();
		for (Field field : fields) {
			getFieldMSG(field);
		}

		// 获取自己的构造函数
		Constructor<?>[] declaredConstructors = class1.getDeclaredConstructors();
		for (Constructor<?> constructor : declaredConstructors) {
			getConstructorMSG(constructor);
		}

	}

	/**
	 * 获取构造函数的信息
	 * 
	 * @param constructor
	 */
	private static void getConstructorMSG(Constructor<?> constructor) {
		// 获取参数信息
		Parameter[] parameters = constructor.getParameters();
		// 获取参数的类类型
		Class<?>[] parameterTypes = constructor.getParameterTypes();
	}

	/**
	 * 获取成员变量的信息
	 * 
	 * @param field
	 */
	private static void getFieldMSG(Field field) {
		// 获取成员变量的类型
		Class<?> type = field.getType();
		String name3 = type.getName();
		// 获取成员变量的名字
		String name2 = field.getName();
	}

	/**
	 * 获取方法的具体信息
	 * 
	 * @param method
	 */
	private static void getMethodMSG(Method method) {
		// 获取方法名
		String name2 = method.getName();
		// 获取方法的返回类型的类类型
		Class<?> returnType = method.getReturnType();

		Class<?> declaringClass = method.getDeclaringClass();
		// 获取方法参数的类类型
		Class<?>[] parameterTypes = method.getParameterTypes();
		// 获取方法参数
		Parameter[] parameters = method.getParameters();
		// 获取方法抛出的的异常类型
		Class<?>[] exceptionTypes = method.getExceptionTypes();
		// 获取方法的默认值
		Object defaultValue = method.getDefaultValue();
	}

 6.方法反射的应用

通过

method.invoke()方法实现方法的反射
/**
	 * Java反射机制中方法反射
	 */
	private static void methidInvoke() {
		Student stu = new Student();
		//获取class
		Class<? extends Student> class1 = stu.getClass();
		try {
			//获取方法Method
			//根据指定的方法名以及参数的类型与个数获取方法
			Method method = class1.getMethod("sayHello", String.class);
			method.invoke(stu, "gaosi");
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

 7.通过反射了解泛型的本质

泛型是在编译时候效,防止输入错误

ArrayList list = new ArrayList();
		
		ArrayList<String> list1 = new ArrayList<String>();
		list1.add("hello");
		//list1.add(20);错误的
		Class c1 = list.getClass();
		Class c2 = list1.getClass();
		System.out.println(c1 == c2);
		//反射的操作都是编译之后的操作
		
		/*
		 * c1==c2结果返回true说明编译之后集合的泛型是去泛型化的
		 * Java中集合的泛型,是防止错误输入的,只在编译阶段有效,
		 * 绕过编译就无效了
		 * 验证:我们可以通过方法的反射来操作,绕过编译
		 */
		try {
			Method m = c2.getMethod("add", Object.class);
			m.invoke(list1, 20);//绕过编译操作就绕过了泛型
			System.out.println(list1.size());
			System.out.println(list1);
			/*for (String string : list1) {
				System.out.println(string);
			}*///现在不能这样遍历
		} catch (Exception e) {
		  e.printStackTrace();
		}

猜你喜欢

转载自gaosililin.iteye.com/blog/2300839