16.1 Class类与Java反射

1、概述
  a、通过Java反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述、实现访问、检测和修改描述Java对象本身信息的功能。Java反射机制的功能非常强大,在java.lang.reflect包中提供了对该功能的支持。
  b、注意:在通过getFields()和getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法;而通过方法getDeclaredFiedls()和getDeclareMethods()只是获得在本类中定义的所有成员变量和方法。
  c、通过反射可访问的主要描述信息:

组成部分访问方法返回值类型说明
包路径getPackage()Package对象获得该类的存放路径
类名称getName()String对象获得该类的名称
继承类getSuperclass()Class对象获得该类继承的类
实现接口getInterfaces()Class型数组获得该类实现的所有接口
构造方法getConstructor()Constructor型数组获得所有权限为public的构造方法
getConstructor(Class<?>...parameterTypes)Constructor对象获得权限为public的指定构造方法
getDeclaredConstructors()Constructor型数组获得所有构造方法,按声明顺序返回
getDeclaredConstructor(Class<?>...parameterTypes)Constructor对象获得指定构造方法
方法getMethods()Method型数组获得所有权限为public的方法
getMethod(String name, Class<?>...parameterTypes)Method对象获得权限为public的方法
getDeclaredMethods()Method型数组获得所有方法,按声明顺序返回
getDeclaredMethods(String name, Class<?>...parameterTypes)Method对象获得指定方法
成员变量getFields()Field型数组获得所有权限为public的成员变量
getField(String name)Field对象获得权限为public的指定成员变量
getDeclaredFields()Field型数组获得所有成员变量,按声明顺序返回
getDeclaredFields(String name)Field对象获得指定成员变量
内部类getClasses()Class型数组获得所有权限为public的内部类
getDeclaredClasses()Class型数组获得所有内部类
内部类的声明类getDeclaringClass()Class对象如果该类为内部类,则返回它的成员类,否则返回null

 

2、访问构造方法
  a、通过下列一组方法访问构造方法时,将返回Constructor类型的对象或数组。每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法。
    getConstructors()
    getConstructor(Class<?>...parameterTypes)
    getDeclaredConstructors()
    getDeclaredConstructor(Class<?>...parameterTypes)
  b、如果是访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。例如访问一个入口参数类型依次为String和int型的构造方法,通过下面两种方法均可实现。
    objectClass.getDeclaredConstructor(String.class, int.class);
    objectClass.getDeclaredConstructor(new Class[]{String.class, int.class});
  c、Constructor类中提供的常用方法如下:

方  法说  明
isVarArgs()查看该构造方法是否允许带有可变数量的参数如果允许则返回true,否则返回false
getParameterTypes()按照声明顺序以Class数组的形式获得该构造方法的各个参数的类型
getExceptionTypes()以Class数组的形式获得该构造方法可能抛出的异常类型
newInstance(Object...initargs)通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法
setAccessible(boolean flag)如果该构造方法的权限为private,默认为不允许通过反射利用newInstance(Object...initargs)方法创建对象。如果先执行该方法并将入口参数设置为true,则允许创建
getModifiers()获得可以解析出该构造方法所采用修饰符的整数

  d、通过java.lang.reflect.Modifier类可以解析出getModifiers()方法的返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,即可以查看是否被指定的修饰符修饰,还可以以字符创的形式获得所有修饰符。
  e、Modifer类中的常用解析方法如下:

静态方法说    明
isPublic(int mod)查看是否被public修饰符修饰,如果是则返回true,否则返回false
isProtected(int mod)查看是否被protected修饰符修饰,如果是则返回true,否则返回false
isPrivate(int mod)查看是否被private修饰符修饰,如果是则返回true,否则返回false
isStatic(int mod)查看是否被static修饰符修饰,如果是则返回true,否则返回false
isFinal(int mod)查看是否被final修饰符修饰,如果是则返回true,否则返回false
toString(int od)以字符创的形式返回所有修饰符


  f、例如:判断对象constructor所代表的构造方法是否被private修饰,以及以字符串形式获得该构造方法的所有修饰符的典型代码如下:
    int modifiers = constructor.getModifiers();
    boolean isEmbellishByPrivate = Modifier.isPrivate(modifiers);
    String embellishment = Modifier.toString(modifiers);

 1 package com.lzw;
 2 
 3 public class Example_01 {
 4     String s;
 5     int i, i2, i3;
 6     private Example_01() {
 7     }
 8     protected Example_01(String s, int i) {
 9         this.s = s;
10         this.i = i;
11     }
12     public Example_01(String... strings) throws NumberFormatException {
13         if (0 < strings.length)
14             i = Integer.valueOf(strings[0]);
15         if (1 < strings.length)
16             i2 = Integer.valueOf(strings[1]);
17         if (2 < strings.length)
18             i3 = Integer.valueOf(strings[2]);
19     }
20     public void print() {
21         System.out.println("s=" + s);
22         System.out.println("i=" + i);
23         System.out.println("i2=" + i2);
24         System.out.println("i3=" + i3);
25     }
26 }
View Code
 1 package com.lzw;
 2 
 3 import java.lang.reflect.*;
 4 
 5 public class Main_01 {
 6 
 7     public static void main(String[] args) {
 8 
 9         Example_01 example = new Example_01("10", "20", "30");
10         Class<? extends Example_01> exampleC = example.getClass();
11 
12         Constructor[] declaredConstructors = exampleC.getDeclaredConstructors();
13         for (int i = 0; i < declaredConstructors.length; i++) {
14             Constructor<?> constructor = declaredConstructors[i];
15             System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs());
16             System.out.println("该构造方法的入口参数类型依次为:");
17             Class[] parameterTypes = constructor.getParameterTypes();
18             for (int j = 0; j < parameterTypes.length; j++) {
19                 System.out.println(" " + parameterTypes[j]);
20             }
21             System.out.println("该构造方法可能抛出的异常类型为:");
22             Class[] exceptionTypes = constructor.getExceptionTypes();
23             for (int j = 0; j < exceptionTypes.length; j++) {
24                 System.out.println(" " + exceptionTypes[j]);
25             }
26             Example_01 example2 = null;
27             while (example2 == null) {
28                 try {
29                     if (i == 2)
30                         example2 = (Example_01) constructor.newInstance();
31                     else if (i == 1)
32                         example2 = (Example_01) constructor.newInstance("7", 5);
33                     else {
34                         Object[] parameters = new Object[] { new String[] {
35                                 "100", "200", "300" } };
36                         example2 = (Example_01) constructor
37                                 .newInstance(parameters);
38                     }
39                 } catch (Exception e) {
40                     System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
41                     constructor.setAccessible(true);
42                 }
43             }
44             if(example2!=null){
45             example2.print();
46             System.out.println();
47             }
48         }
49 
50     }
51 
52 }
View Code

 

3、访问成员变量
  a、在通过下列一组方法访问成员变量时,将返回Field类型的对象或数组。每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。
    getFields()
    getField(String name)
    getDeclaredFields()
    getDeclaredField(String name)
  b、如果是访问指定的成员变量,可以通过该成员变量的名称来访问。例如,访问一个名称为birthday的成员变量,访问方法如下:
    object.getDeclaredField("birthday");
  c、Field类的常用方法:

方法说  明
getName()获得该成员变量的名称
getType()获得表示该成员变量类型的Class对象
get(Object obj)获得指定对象obj中成员变量的值,返回值为Object型
set(Object obj, Object obj)将指定对象obj中成员变量的值设置为value
getInt(Object obj)获得指定对象obj中类型为int的成员变量的值
setInt(Object obj, int i)将指定对象obj中类型为int的成员变量的值设置为i
getFloat(Object obj)获得指定对象obj中类型为float的成员变量的值
setFloat(Object obj, float f)将指定对象obj中类型为float的成员变量的值设置为f
getBoolean(Object obj)获得指定对象obj中类型为boolean的成员变量的值
setBoolean(Object obj, boolean z)获得指定对象obj中类型为boolean的成员变量的值设置为z
setAccessible(boolean flag)此方法可以设置是否忽略权限限制直接访问private等私有权限的成员变量
getModifiers()获得可以解析出该成员变量所采用修饰符的整数
1 public class Example_02 {
2     int i;
3     public float f;
4     protected boolean b;
5     private String s;
6 }
View Code
 1 import java.lang.reflect.*;
 2 public class Main_02 {
 3     public static void main(String[] args) {
 4         Example_02 example = new Example_02();
 5         Class exampleC = example.getClass();
 6         // 获得所有成员变量
 7         Field[] declaredFields = exampleC.getDeclaredFields();
 8         for (int i = 0; i < declaredFields.length; i++) {
 9             Field field = declaredFields[i]; // 遍历成员变量
10             // 获得成员变量名称
11             System.out.println("名称为:" + field.getName());
12             Class fieldType = field.getType(); // 获得成员变量类型
13             System.out.println("类型为:" + fieldType);
14             boolean isTurn = true;
15             while (isTurn) {
16                 // 如果该成员变量的访问权限为private,则抛出异常,即不允许访问
17                 try {
18                     isTurn = false;
19                     // 获得成员变量值
20                     System.out.println("修改前的值为:" + field.get(example));
21                     // 判断成员变量的类型是否为int型
22                     if (fieldType.equals(int.class)) {
23                         System.out.println("利用方法setInt()修改成员变量的值");
24                         field.setInt(example, 168); // 为int型成员变量赋值
25                         // 判断成员变量的类型是否为float型
26                     } else if (fieldType.equals(float.class)) {
27                         System.out.println("利用方法setFloat()修改成员变量的值");
28                         // 为float型成员变量赋值
29                         field.setFloat(example, 99.9F);
30                         // 判断成员变量的类型是否为boolean型
31                     } else if (fieldType.equals(boolean.class)) {
32                         System.out.println("利用方法setBoolean()修改成员变量的值");
33                         // 为boolean型成员变量赋值
34                         field.setBoolean(example, true);
35                     } else {
36                         System.out.println("利用方法set()修改成员变量的值");
37                         // 可以为各种类型的成员变量赋值
38                         field.set(example, "MWQ");
39                     }
40                     // 获得成员变量值
41                     System.out.println("修改后的值为:" + field.get(example));
42                 } catch (Exception e) {
43                     System.out.println("在设置成员变量值时抛出异常,"
44                             + "下面执行setAccessible()方法!");
45                     field.setAccessible(true); // 设置为允许访问
46                     isTurn = true;
47                 }
48             }
49             System.out.println();
50         }
51     }
52 }
View Code

 

4、访问方法
  a、在通过下列一组方法访问方法时,将返回Method类型的对象或数组。每个Method对象代表一个方法,利用Method对象可以操纵相应的方法。
    getMethods()
    getMethod(String name, Class<?>...parameterTypes)
    getDeclaredMethods()
    getDeclaredMethod(String name, Class<?>...parameterTypes)
  b、如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。例如,访问一个名称为print、入口参数类型依次为String和int型的方法,通过下面两种方式均可实现:
    objectClass.getDeclaredMethod("print", String.class, int.class)
    objectClass.getDeclaredMethod("print", new Class[]{String.class, int.class})
  c、在反射中执行具有可变数量的参数的构造方法时,需要将入口参数定义成二维数组。
  d、Method类中提供的常用方法如下:

方法说  明
getName()获得该方法的名称
getParameterTypes()按照声明顺序以Class数组的形式获得该方法的各个参数的类型
getReturnType()以Class对象的形式获得该方法的返回值的类型
getExceptionTypes()以Class数组的形式获得该方法可能跑出的异常类型
invoke(Object obj, Object...args)利用指定参数args执行指定对象obj中的该方法,返回值为Object型
isVarArgs()查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false
getModifiers()获得可以解析出该方法所采用修饰符的整数
 1 package com.lzw;
 2 
 3 public class Example_03 {
 4     static void staticMethod() {
 5         System.out.println("执行staticMethod()方法");
 6     }
 7     
 8     public int publicMethod(int i) {
 9         System.out.println("执行publicMethod()方法");
10         return i * 100;
11     }
12     
13     protected int protectedMethod(String s, int i)
14             throws NumberFormatException {
15         System.out.println("执行protectedMethod()方法");
16         return Integer.valueOf(s) + i;
17     }
18     
19     private String privateMethod(String... strings) {
20         System.out.println("执行privateMethod()方法");
21         StringBuffer stringBuffer = new StringBuffer();
22         for (int i = 0; i < strings.length; i++) {
23             stringBuffer.append(strings[i]);
24         }
25         return stringBuffer.toString();
26     }
27 }
View Code
 1 package com.lzw;
 2 
 3 import java.lang.reflect.*;
 4 
 5 public class Main_03 {
 6     public static void main(String[] args) {
 7         Example_03 example = new Example_03();
 8         Class exampleC = example.getClass();
 9         
10         // 获得所有方法
11         Method[] declaredMethods = exampleC.getDeclaredMethods();
12         for (int i = 0; i < declaredMethods.length; i++) {
13             Method method = declaredMethods[i]; // 遍历方法
14             System.out.println("名称为:" + method.getName()); // 获得方法名称
15             System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs());
16             System.out.println("入口参数类型依次为:");
17             // 获得所有参数类型
18             Class[] parameterTypes = method.getParameterTypes();
19             for (int j = 0; j < parameterTypes.length; j++) {
20                 System.out.println(" " + parameterTypes[j]);
21             }
22             // 获得方法返回值类型
23             System.out.println("返回值类型为:" + method.getReturnType());
24             System.out.println("可能抛出的异常类型有:");
25             // 获得方法可能抛出的所有异常类型
26             Class[] exceptionTypes = method.getExceptionTypes();
27             for (int j = 0; j < exceptionTypes.length; j++) {
28                 System.out.println(" " + exceptionTypes[j]);
29             }
30             boolean isTurn = true;
31             while (isTurn) {
32                 // 如果该方法的访问权限为private,则抛出异常,即不允许访问
33                 try {
34                     isTurn = false;
35                     if("staticMethod".equals(method.getName()))
36                         method.invoke(example); // 执行没有入口参数的方法
37                     else if("publicMethod".equals(method.getName()))
38                         System.out.println("返回值为:"
39                                 + method.invoke(example, 168)); // 执行方法
40                     else if("protectedMethod".equals(method.getName()))
41                         System.out.println("返回值为:"
42                                 + method.invoke(example, "7", 5)); // 执行方法
43                     else if("privateMethod".equals(method.getName())) {
44                         Object[] parameters = new Object[] { new String[] {
45                                 "M", "W", "Q" } }; // 定义二维数组
46                         System.out.println("返回值为:"
47                                 + method.invoke(example, parameters));
48                     }
49                 } catch (Exception e) {
50                     System.out.println("在执行方法时抛出异常,"
51                             + "下面执行setAccessible()方法!");
52                     method.setAccessible(true); // 设置为允许访问
53                     isTurn = true;
54                 }
55             }
56             System.out.println();
57         }
58     }
59 }
View Code

 

转载于:https://www.cnblogs.com/studycode/p/9540076.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值