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();
}