java反射的基本使用

淡淡的烟草味﹌ 2022-07-17 01:29 252阅读 0赞

java反射机制的使用是相当广泛,以前掌握的不是太好,趁最近有时间来复习一番。得意

百度百科中对于反射机制是这么介绍的:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;

一般我们都是通过new关键字来创建对象的,这个反射到底是何方婶婶?怎么那么牛?

不要急,我们先来看一下下面的示意图:

Center

每一个.class文件加载到内存的时候都是一个Class类的对象!把Demo.class加载到内存的时候,他就是一个Class的对象。与反射相关的类有一下的四种:

Class,Field,Method,Constructor,分别表示:类,成员变量,方法,和构造器。

获取Class通常有一下的3种方法:

1.通过类名称.class,对基本类型也支持;

Class c = int.class;

Class c = int[].class;

Class c = String.class

2.通过对象.getClass()方法

Class c = obj.getClass();

3.Class.forName()通过类名称加载类,这种方法只要有类名称就可以得到Class;

Class c = Class.forName(“类名”);(不要忘记包名)

********************************************************************************************

Class类的常用方法

String getName():获取类名称,包含包名;

String getSimpleName():获取类名称,不包含包名;

Class getSupperClass():获取父类的Class,

例如:new Integer(100).getClass().getSupperClass()返回的是Class

但new Object().getSupperClass()返回的是null,因为Object没有父类;

T newInstance():使用本类无参构造器来创建本类对象;

boolean isArray():是否为数组类型;

boolean isAnnotation():是否为注解类型;

boolean isAnnotationPresent(Class annotationClass):当前类是否被annotationClass注解了;

boolean isEnum():是否为枚举类型;

boolean isInterface():是否为接口类型;

boolean isPrimitive():是否为基本类型;

boolean isSynthetic():是否为引用类型;

下面举个例子来总结一下:

  1. package lsj.pc;
  2. public class Test {
  3. @org.junit.Test
  4. public void fun1() throws Exception {
  5. Class<?> clazz = Class.forName("lsj.pc.User");
  6. User user = (User)clazz.newInstance();
  7. user.setPassword("1234567");
  8. user.setUsername("TOM");
  9. System.out.println(user);
  10. }
  11. }
  12. class User {
  13. private String username;
  14. private String password;
  15. public User(String username, String password) {
  16. this.username = username;
  17. this.password = password;
  18. }
  19. public User() {
  20. }
  21. public String getUsername() {
  22. return username;
  23. }
  24. public void setUsername(String username) {
  25. this.username = username;
  26. }
  27. public String getPassword() {
  28. return password;
  29. }
  30. public void setPassword(String password) {
  31. this.password = password;
  32. }
  33. @Override
  34. public String toString() {
  35. return "用户名:"+ username + ", 密码:" + password ;
  36. }
  37. }

执行的结果如下:

User [username=TOM, password=1234567]

上面的例子中,通过反射获取了User类的Class对象,然后通过Class对象的newInstance()方法创建了一个user对象的实例。

2)获取玩Class对象,接下来获取构造器Constructor对象。

获取的方式有以下4种:

Constructor getConstructor(Class… parameterTypes):通过指定的参数类型获取公有构造器反射对象;

Constructor[] getConstructors():获取所有公有构造器对象;

Constructor getDeclaredConstructor(Class… parameterTypes):通过指定参数类型获取构造器反射对象。可以是私有构造器对象;

Constructor[] getDeclaredConstructors():获取所有构造器对象。包含私有构造器;

Construcator类常用方法

String getName():获取构造器名;

Class getDeclaringClass():获取构造器所属的类型;

Class[] getParameterTypes():获取构造器的所有参数的类型;

Class[] getExceptionTypes():获取构造器上声明的所有异常类型;

T newInstance(Object… initargs):通过构造器反射对象调用构造器。

下面举个例子:

  1. public class Test {
  2. @org.junit.Test
  3. public void fun1() throws Exception {
  4. Class<?> clazz = Class.forName("lsj.pc.User");
  5. Constructor<?> c=clazz.getConstructor(String.class,String.class);
  6. User user=(User) c.newInstance("TOM","1234567");
  7. /*User user = (User)clazz.newInstance();
  8. user.setPassword("1234567");
  9. user.setUsername("TOM");*/
  10. System.out.println(user);
  11. }

3)获取方法

Method getMethod(String name, Class… parameterTypes):

通过方法名和方法参数类型获取方法反射对象,包含父类中声明的公有方法,但不包含所有私有方法;

Method[] getMethods():

获取所有公有方法,包含父类中的公有方法,但不包含任何私有方法;

Method getDeclaredMethod(String name, Class… parameterTypes):

通过方法名和方法参数类型获取本类中声明的方法的反射对象,包含本类中的私有方法,但不包含父类中的任何方法;

Method[] getDeclaredMethods():

获取本类中所有方法,包含本类中的私有方法,但不包含父类中的任何方法。

下面是一些常用的方法:

String getName():获取方法名;

Class getDeclaringClass():获取方法所属的类型;

Class[] getParameterTypes():获取方法的所有参数的类型;

Class[] getExceptionTypes():获取方法上声明的所有异常类型;

Class getReturnType():获取方法的返回值类型;

Object invode(Object obj, Object… args):

通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,如果当前方法是static方法,那么可以给obj传递null。args表示是方法的参数;

现在我们试着获取User的toString方法。

  1. <span style="color:#000000;">public class Test {
  2. @org.junit.Test
  3. public void fun1() throws Exception {
  4. Class<?> clazz = Class.forName("lsj.pc.User");
  5. Constructor<?> c=clazz.getConstructor(String.class,String.class);
  6. User user=(User) c.newInstance("TOM","1234567");
  7. Method method=clazz.getMethod("toString");
  8. String result =(String) method.invoke(user);
  9. /*User user = (User)clazz.newInstance();
  10. user.setPassword("1234567");
  11. user.setUsername("TOM");*/
  12. System.out.println(result);
  13. }
  14. }</span>

结果 :用户名:TOM, 密码:1234567
4)获取类的成员变量

Field getField(String name):通过名字获取公有成员变量的反射对象,包含父类中声明的公有成员变量;

Field[] getFields():获取所有公有成员变量反射对象,包含父类中声明的公有成员变量;

Field getDeclaredField(String name):通过名字获取本类中某个成员变量,包含本类的private成员变量,但父类中声明的任何成员变量都不包含;

Field[] getDeclaredFields():获取本类中声明的所有成员变量,包含private成员变量,但不包含父类中声明的任何成员变量;

Fileld类有以下的一些常用的方法:

String getName():获取成员变量名;

Class getDeclaringClass():获取成员变量的类型;

Class getType():获取当前成员变量的类型;

Object get(Object obj):获取obj对象的成员变量的值;

void set(Object obj, Object value):设置obj对象的成员变量值为value;

下面举一个例子:

  1. import java.lang.reflect.Field;
  2. public class Test {
  3. @org.junit.Test
  4. public void fun1() throws Exception {
  5. Class<?> clazz = Class.forName("lsj.pc.User");
  6. User user=new User("老王","123");
  7. Field field1=clazz.getDeclaredField("username");
  8. Field field2=clazz.getDeclaredField("password");
  9. String username=(String) field1.get(user);
  10. String password=(String) field2.get(user);
  11. System.out.println(username+","+password);
  12. field1.set(user,"lisi");
  13. field2.set(user,"456");
  14. System.out.println(user);
  15. }
  16. }
  17. class User {
  18. public String username;
  19. public String password;
  20. public User(String username, String password) {
  21. this.username = username;
  22. this.password = password;
  23. }
  24. public User() {
  25. }
  26. public String getUsername() {
  27. return username;
  28. }
  29. public void setUsername(String username) {
  30. this.username = username;
  31. }
  32. public String getPassword() {
  33. return password;
  34. }
  35. public void setPassword(String password) {
  36. this.password = password;
  37. }
  38. @Override
  39. public String toString() {
  40. return "用户名:"+ username + ", 密码:" + password ;
  41. }
  42. }

输出结果:

老王,123
用户名:lisi, 密码:456

5)获取AccessibleObject

AccessibleObject类是Constructor、Method、Field三个类的父类。AccessibleObject最为重要的方法如下:

boolean isAccessible():判断当前成员是否可访问;

void setAccessible(boolean flag):设置当前成员是否可访问。

当Constructor、Method、Field为私有时,如果我们想反射操作,那么就必须先调用反射对象的setAccessible(true)方法,然后才能操作。

把刚才的User类中的两个属性改成private类型。

  1. public void fun1() throws Exception {
  2. Class<? > clazz = Class.forName("lsj.pc.User");
  3. User user=new User("老王","123");
  4. Field field1=clazz.getDeclaredField("username");
  5. Field field2=clazz.getDeclaredField("password");
  6. field1.setAccessible(true);
  7. field2.setAccessible(true);
  8. String username=(String) field1.get(user);
  9. String password=(String) field2.get(user);
  10. System.out.println(username+","+password);
  11. field1.set(user,"lisi");
  12. field2.set(user,"456");
  13. System.out.println(user);
  14. }

这样就可以访问私有的成员变量了。

发表评论

表情:
评论列表 (有 0 条评论,252人围观)

还没有评论,来说两句吧...

相关阅读

    相关 使用

    概述     JAVA反射机制是在运行中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态

    相关 Java深入浅出

    刚开始接触反射这个概念,感觉反射这个机制很复杂很难懂,所以在这篇文章中对java的反射机制以个人的理解总结归纳。 1. 什么是反射? 什么是反射?在官方文档中是这样说的