JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
在面向对象的世界里,万事万物皆对象。那么java语言中,静态成员、类是谁的对象呢?
类是对象,类是java.lang.Class类的实例对象。那么Class类的实例对象如何表示呢?我们来看一下源码:
/*
* Constructor. Only the Java Virtual Machine creates Class
* objects.
*/
private Class() {}
构造器被私有,只有java虚拟机能创建Class的实例对象。
任何一个类都是Class的实例对象,这个实例对象(类)有三种表示方式:
Class c1 = A.class;//第一种,实际告诉我们,任何一个类都有一个隐含的静态成员变量class
A a = new A();
Class c2 = a.getClass();//第二种,已知该类的对象,调用getClass方法
Class c3 = null;//第三种,通过Class.forName
try {
c3 = Class.forName("com.honor.A");//作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
我们可以通过类的类类型创建该类的实例对象,即通过c1、c2、c3创建A的实例对象:
try {
A a = c3.newInstance();//A必需要有无参数的构造方法
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Class.forName("类的全称")不仅表示了类的类型,还代表了动态加载类,编译时刻加载类是静态加载类,运行时刻加载类是动态加载类。new创建对象是静态加载类,在编译时刻就需要加载所有的可能使用到的类。反射是动态加载类,反射的操作都是编译之后的操作。
反射常用的一些方法:
c.getName();//获取类的名称
/*
* Method类,方法对象
* 一个成员方法就是一个Method对象
* getMethods方法获取所有的public修饰的函数,包括父类继承来的方法
* getDeclaredMethods()获取的是所有该类自己声明的方法,忽略访问权限
*/
c.getDeclaredMethods();
Method [] methods = c.getMethods();
for(int i = 0;i<methods.length;i++){
Class returnType = methods[i].getReturnType();//得到方法返回值类型的类类型(int.class,String.class...)
methods[i].getName();//得到方法的名称
}
/*
* 成员变量也是对象
* java.lang.refect.Field
* Field类封装了关于成员变量的操作
* getFields()方法获取的是所有的public的成员变量的信息
* getDeclaredFields()方法获取的是该类自己声明的成员变量的信息
*
*/
c.getFields();
Field [] fields = c.getDeclaredFields();
for(Field field:fields){
Class fieldType = field.getType();//得到成员变量的类型的类类型
fieldType.getName();//得到成员变量类型的名字
field.getName();//得到成员变量的名称
}
通过反射了解集合泛型的本质:
java中集合的泛型是防止错误输入的,只在编译阶段有效,绕过编译就无效了,可以通过方法的反射来操作,绕过编译。
List<String> list = new ArrayList<String>();
list.add("hi");
Class c = list.getClass();
try {
Method m = c.getMethod("add", Object.class);
m.invoke(list, 10);//绕过泛型(编译)
System.out.println(list.size());//通过list长度可以判断是否通过反射加到了list中
} catch (Exception e) {
e.printStackTrace();
}
在面向对象的世界里,万事万物皆对象。那么java语言中,静态成员、类是谁的对象呢?
类是对象,类是java.lang.Class类的实例对象。那么Class类的实例对象如何表示呢?我们来看一下源码:
/*
* Constructor. Only the Java Virtual Machine creates Class
* objects.
*/
private Class() {}
构造器被私有,只有java虚拟机能创建Class的实例对象。
任何一个类都是Class的实例对象,这个实例对象(类)有三种表示方式:
Class c1 = A.class;//第一种,实际告诉我们,任何一个类都有一个隐含的静态成员变量class
A a = new A();
Class c2 = a.getClass();//第二种,已知该类的对象,调用getClass方法
Class c3 = null;//第三种,通过Class.forName
try {
c3 = Class.forName("com.honor.A");//作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
我们可以通过类的类类型创建该类的实例对象,即通过c1、c2、c3创建A的实例对象:
try {
A a = c3.newInstance();//A必需要有无参数的构造方法
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Class.forName("类的全称")不仅表示了类的类型,还代表了动态加载类,编译时刻加载类是静态加载类,运行时刻加载类是动态加载类。new创建对象是静态加载类,在编译时刻就需要加载所有的可能使用到的类。反射是动态加载类,反射的操作都是编译之后的操作。
反射常用的一些方法:
c.getName();//获取类的名称
/*
* Method类,方法对象
* 一个成员方法就是一个Method对象
* getMethods方法获取所有的public修饰的函数,包括父类继承来的方法
* getDeclaredMethods()获取的是所有该类自己声明的方法,忽略访问权限
*/
c.getDeclaredMethods();
Method [] methods = c.getMethods();
for(int i = 0;i<methods.length;i++){
Class returnType = methods[i].getReturnType();//得到方法返回值类型的类类型(int.class,String.class...)
methods[i].getName();//得到方法的名称
}
/*
* 成员变量也是对象
* java.lang.refect.Field
* Field类封装了关于成员变量的操作
* getFields()方法获取的是所有的public的成员变量的信息
* getDeclaredFields()方法获取的是该类自己声明的成员变量的信息
*
*/
c.getFields();
Field [] fields = c.getDeclaredFields();
for(Field field:fields){
Class fieldType = field.getType();//得到成员变量的类型的类类型
fieldType.getName();//得到成员变量类型的名字
field.getName();//得到成员变量的名称
}
通过反射了解集合泛型的本质:
java中集合的泛型是防止错误输入的,只在编译阶段有效,绕过编译就无效了,可以通过方法的反射来操作,绕过编译。
List<String> list = new ArrayList<String>();
list.add("hi");
Class c = list.getClass();
try {
Method m = c.getMethod("add", Object.class);
m.invoke(list, 10);//绕过泛型(编译)
System.out.println(list.size());//通过list长度可以判断是否通过反射加到了list中
} catch (Exception e) {
e.printStackTrace();
}