【java】反射机制

本文详细介绍了Java反射机制的概念,包括如何获取class对象、类名、构造方法、成员方法和成员变量。通过setAccessible方法可以提高反射效率,并且讲解了如何使用反射读取注解信息来生成SQL语句进行数据库操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

概念

获取class对象

获取类名

获取构造方法并使用

获取成员方法并使用

获取成员变量并使用

setAccessible---启用禁止安全检查开关可以提高反射效率 

 使用反射读取注解信息,转换为SQL语句,进行数据库操作

 

概念

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

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老坛酸菜吃鸭子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值