目录
setAccessible---启用禁止安全检查开关可以提高反射效率
概念
java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用他的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
可以在运行时加载、探知、使用编译期间完全未知的类
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;
Class c = Class.forName(“com.g.reflection.Student”)
加载完类后,在堆内存中,产生了一个Class类型的对象(一个类只有一个Class对象,类似该类的设计图,一般只有一张,按设计图可生产多个对象),这个Class对象中包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为:反射
获取class对象
1.使用类的class属性来获取该类对应的class对象
Class<Student> c1=Student.class;
2.调用对象的getClass()方法,返回该对象所属类对应的Class对象
Student s=new Student();
Class<? extends Student> c2=s.getClass();
3.使用该Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径
Class<?> c4=class.forName("test.Student");
获取类名
Class.getName() 以String的形式,返回Class对象的“实体”名称;
Class.getSimpleName() 获取源代码中给出的“底层类”简称。
获取构造方法并使用
Constructor<?> [] getConstructors() 返回一个包含Constructor对象的数组,Constructor对象反映了由该对对象表示的类的所有公共构造函数
Constructor<?> [] getDeclaredConstructors() 返回反映由该class对象表示的类声明的所有构造函数的Constructor对象的数组
Constructor<T> [] getConstructor()(Class<?>...parameterTypes) 返回单个公共构造方法的对象
参数:对应的字节码对象
Constructor<T> [] getDeclaredConstructors()(Class<?>...parameterTypes) 返回单个构造方法对象
//获取构造器
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println("构造器:"+constructor);
}
Constructor c = clazz.getDeclaredConstructor(String.class,int.class);
System.out.println("获取带参构造器:"+c);
Constructor c2 = clazz.getDeclaredConstructor(null);
System.out.println("获取无参构造器:"+c2);
}
Constructor类中用于调用构造方法的方法
T newInstance(object...initargs) 根据指定的构造方法创建对象
//通过反射API动态调用无参构造方法,构造对象
Constructor<User> c1 = clazz.getDeclaredConstructor();
User u1 = c1.newInstance();
System.out.println(u1);
//通过反射API动态调用带参构造,构造对象
Constructor<User> c2 = clazz.getDeclaredConstructor(String.class,int.class);
User u2 = c2.newInstance("a",13);
System.out.println(u2.getName());
获取成员方法并使用
Method[] getMethods() 返回所有公共成员方法对象的数组,包括继承的
Method getDeclaredMethods() 返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name,Class<?>... parameterTypes) 返回单个公共成员方法对象
Method getDeclaredMethod(String name,Class<?>... parameterTypes) 返回单个成员方法对象
//获取方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("方法:"+method);}
Method m01 = clazz.getMethod("getAge", null);
//如果方法有参,则必须传递参数类型对应的class对象
Method m02 = clazz.getDeclaredMethod("setAge", int.class);
Method m03 = clazz.getDeclaredMethod("setAge", null);
System.out.println(m01);
System.out.println(m02);
System.out.println(m03);
Method类中用于调用成员方法的方法
Object invoke(Object obj,Object...args) 调用obj对象的成员方法,参数是args,返回值是Object类型
//通过反射API动态调用普通方法
User u3 = c1.newInstance();
Method m1 = clazz.getDeclaredMethod("setName", String.class);//u3.setName("张三"):
m1.invoke(u3, "张三");//需要调用的方法名和参数,变成了字符串,运行时改变方法名字符串可调用不同的方法
System.out.println(u3.getName());
获取成员变量并使用
Field[] getFields() 返回所有公共成员变量对象的数组
Field[] getDeclaredFields() 返回所有成员变量的数组
Field getField(String fieldName) 返回单个公共成员变量
Field getDeclaredField(String fieldName) 返回单个成员变量对象
Field类中用于给成员变量赋值的方法
void set(Object obj,Object value) 给obj对象的成员变量赋值为value
//使用反射API动态设置属性
User u4 = c1.newInstance();
Field f1 = clazz.getDeclaredField("name");
f1.setAccessible(true);//这个属性不需要做安全检查,可以直接访问
f1.set(u4, "李四");//通过反射直接写属性
System.out.println(u4.getName());
System.out.println(f1.get(u4));//通过反射直接读属性
setAccessible---启用禁止安全检查开关可以提高反射效率
public class EfficiencyDemo04 {
public static void main(String[] args) throws Exception, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
//普通方法调用
test01();
//反射机制方法调用
test02();
//禁用安全检查的反射机制方法调用
test03();
}
private static void test01() {
// TODO Auto-generated method stub
User u = new User("张三",18);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
u.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法调用一亿花费时间:"+(endTime-startTime)+"ms");
}
private static void test02() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class clazz = Class.forName("gdpu_getclass_bean.User");
Constructor<User> c = clazz.getDeclaredConstructor(String.class,int.class);
User u = c.newInstance("张三",18);
Method m = clazz.getDeclaredMethod("getName", null);
// TODO Auto-generated method stub
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
m.invoke(u, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射机制方法调用一亿次花费时间:"+(endTime-startTime)+"ms");
}
private static void test03() throws Exception {
Class clazz = Class.forName("gdpu_getclass_bean.User");
Constructor<User> c = clazz.getDeclaredConstructor(String.class,int.class);
User u = c.newInstance("张三",18);
Method m = clazz.getDeclaredMethod("getName", null);
m.setAccessible(true);//不执行安全检查
// TODO Auto-generated method stub
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
m.invoke(u, null);
}
long endTime = System.currentTimeMillis();
System.out.println("禁用安全检查的反射机制方法调用一亿次花费时间:"+(endTime-startTime)+"ms");
}
}
使用反射读取注解信息,转换为SQL语句,进行数据库操作
public class Demo {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
// TODO Auto-generated method stub
try {
Class clazz = Class.forName("gdpu_getclass_bean.Student");
//获得类的有效注解
Annotation[] annotations = clazz.getDeclaredAnnotations();
for (Annotation a : annotations) {
System.out.println(a);
}
//得到注解GdpuTable中属性value的参数值,从而获得表Student映射的数据库表的表名
GdpuTable gdpuTbAnno = (GdpuTable) clazz.getDeclaredAnnotation(GdpuTable.class);
String tbName = gdpuTbAnno.value();
System.out.println(tbName);
//获得属性id对应数据库表中字段
Field f1 = clazz.getDeclaredField("id");
GdpuField gdpuField1 = (GdpuField)f1.getDeclaredAnnotation(GdpuField.class);
String columnName = gdpuField1.columnName();
String type = gdpuField1.type();
int length = gdpuField1.length();
System.out.println(columnName+":"+type+"("+length+")");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获得属性name对应数据库表中字段
Field f2 = clazz.getDeclaredField("name");
GdpuField gdpuField2 = (GdpuField)f2.getDeclaredAnnotation(GdpuField.class);
String columnName2 = gdpuField2.columnName();
String type2 = gdpuField2.type();
int length2 = gdpuField2.length();
System.out.println(columnName2+":"+type2+"("+length2+")");
//获得属性age对应数据库表中的字段
Field f3 = clazz.getDeclaredField("age");
GdpuField gdpuField3 = (GdpuField)f3.getDeclaredAnnotation(GdpuField.class);
String columnName3 = gdpuField3.columnName();
String type3 = gdpuField3.type();
int length3 = gdpuField3.length();
System.out.println(columnName3+":"+type3+"("+length3+")");
//构造SQL语句,完成数据库插入操作
//insert into tb_student(id,sname,age) values(1003,"lisi",28)
String insertStudent = "insert into "+tbName+"("+columnName1+","+columnName2+","+columnName3+")"+" values(1003,"+"\"lisi\""+",28)";
System.out.println(insertStudent);
}
}