java反射

avatar

个人理解

在运行状态中,对于任何一个类,都能获取到这个类的所有信息,例如该类中的方法,属性,及实现的接口等等;并且还能调用该类的任一方法或属性;这种在运行时动态的获取类信息或调用类中的属性或方法称之为反射

实战

所用到的实体类

这个类是我直接复制的,就没有去自己写了,自己在toString方法上添加了@Override注解,本来是准备写下注解的方法的,结果代码太多,就没写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

@Resource
public class Reflection implements Cloneable, Serializable {  
    private String     str;  
 private double d;  
 public boolean b;  
 public static short s;  
 public Reflection()  
    {  
    }  
    public Reflection(String str)  
    {  
        this.str = str;  
  }  
  
    public Reflection(String str, double d, boolean b)  
    {  
        this.str = str;  
		this.d = d;  
        this.b = b;  
   }  
   private void privateMethod()  
   {  
   }  
   public String publicMethod()  
   {  
        privateMethod();  
        return null;  
   }  
   public String publicMethod(int i)  
   {  
       return null;  
  }  
  public String publicMethod(int i, double d, List<String> l)  
  {  
      return "Reflection.publicMethod(int i, double d), i = " + i + ", d = " + d;  
 }  
 public static int returnOne()  
 {  
       return 1;  
 }  
 @Override  
 public String toString()  
 {  
    return "str = " + str + ", d = " + d + ", b = " + b;  
 }  
}

class

class的一些信息

  • 获取class的中方法
1
2
3
4
5
6
7
8

//1  
Class<?> aClass = Class.forName("com.example.demo.reflex.one.Reflection");  
//2  
Class<?> aClass1 = new Reflection().getClass();  
//3  
Class<Reflection> reflectionClass = Reflection.class;

  • 对类信息操作 代码
1
2
3
4
5
6
7
8
9
@Test  
public void classTest() throws ClassNotFoundException {  
   Class<?> aClass = Class.forName("com.example.demo.reflex.one.Reflection");  
  System.out.println("获取该类的父类: "+aClass.getSuperclass());  
  System.out.println("获取java.lang.Class的Class对象: "+aClass.getClass());  
  System.out.println("获取类的加载器: "+aClass.getClassLoader());  
  System.out.println("获取该类的注解: "+aClass.getAnnotations()[0]);  //注意返回的是数组;
}

运行结果:

1
2
3
4
5
获取该类的父类: class java.lang.Object
获取java.lang.ClassClass对象: class java.lang.Class
获取类的加载器: sun.misc.Launcher$AppClassLoader@18b4aac2
获取该类的注解: @javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)

Field

对属性操作

  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

@Test  
public void fieldTest() throws ClassNotFoundException, NoSuchFieldException {  
   Class<?> aClass = Class.forName("com.example.demo.reflex.one.Reflection");  
  Field f0 = aClass.getField("b");  
  System.out.println("aClass.getField(String name)通过名字获取该类中访问权限为public的字段"+f0);  
  System.out.println();  
  Field f1 =aClass.getDeclaredField("d");  
  System.out.println("aClass.getDeclaredField(String name)通过名字获取该类中任意访问权限的字段"+f1);  
  System.out.println();  
  Field[] fields = aClass.getFields();  
  System.out.println("aClass.getFields()是获取该类中所有public字段,包括继承而来的public字段");  
 for(Field field:fields){  
      System.out.println(field);  
  }  
   System.out.println();  
  Field[] declaredFields = aClass.getDeclaredFields();  
  System.out.println("aClass.getDeclaredFields()是获取该类中所有字段,不限制访问权限,不包括继承而来的");  
 for(Field field:declaredFields){  
      System.out.println(field);  
  }  
   System.out.println();  
  System.out.println("获取字段名字:Field.getName():" + f0.getName());  
  System.out.println("获取字段类型:Field.getType():" + f0.getType());  
  System.out.println("以整数形式返回此Field对象的Java语言修饰符:Field.getModifiers():" + f0.getModifiers());  
  System.out.println("使用Modifier解析后的修饰符:"+Modifier.toString(f0.getModifiers()));  
  ////返回Field的访问权限,对private的Field赋值,必须要将accessible设置为true
  System.out.println("Field.isAccessible():" + f0.isAccessible());  
  
}

  • 运行结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
aClass.getField(String name)通过名字获取该类中访问权限为public的字段public boolean com.example.demo.reflex.one.Reflection.b

aClass.getDeclaredField(String name)通过名字获取该类中任意访问权限的字段private double com.example.demo.reflex.one.Reflection.d

aClass.getFields()是获取该类中所有public字段,包括继承而来的public字段
public boolean com.example.demo.reflex.one.Reflection.b
public static short com.example.demo.reflex.one.Reflection.s

aClass.getDeclaredFields()是获取该类中所有字段,不限制访问权限,不包括继承而来的
private java.lang.String com.example.demo.reflex.one.Reflection.str
private double com.example.demo.reflex.one.Reflection.d
public boolean com.example.demo.reflex.one.Reflection.b
public static short com.example.demo.reflex.one.Reflection.s

获取字段名字:Field.getName()b
获取字段类型:Field.getType()boolean
以整数形式返回此Field对象的Java语言修饰符:Field.getModifiers()1
使用Modifier解析后的修饰符:public
Field.isAccessible()false

method

对方法进行操作

  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

@Test  
public void getMethod() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {  
   Class<?> aClass = Class.forName("com.example.demo.reflex.one.Reflection");  
  Method publicMethod = aClass.getMethod("publicMethod", int.class, double.class, List.class);  
  System.out.println("根据方法名字和参数获取方法,包括继承而来的public方法:Class.getMethod:"+publicMethod);  
  System.out.println();  
  Method toString = aClass.getDeclaredMethod("toString");  
  System.out.println("根据方法名获取本类方法,包括私有的:Class.getDeclaredMethod:"+toString);  
  System.out.println();  
  Method[] methods = aClass.getMethods();  
  System.out.println("该类的所有方法,包括继承父类而来的public方法");  
 for(Method m:methods){  
      System.out.println(m);  
  }  
   System.out.println();  
  Method[] declaredMethods = aClass.getDeclaredMethods();  
  System.out.println("本类声明的所有方法,不包括继承父类而来的方法");  
 for(Method m:declaredMethods){  
      System.out.println(m);  
  }  
   System.out.println();  
  Class<?>[] parameterTypes = publicMethod.getParameterTypes();  
  System.out.println("获取该方法的参数:Method.getParameterTypes");  
 for (Class c:parameterTypes){  
      System.out.println(c);  
  }  
   System.out.println();  
  System.out.println("获取方法的名字:Method.getName():"+publicMethod.getName());  
  System.out.println(" 获取方法的访问属性:Method.isAccessible():"+publicMethod.isAccessible());  
  System.out.println(" 获取方法的返回类型:Method.getReturnType():"+publicMethod.getReturnType());  
  System.out.println("反射调用方法"+publicMethod.invoke(aClass.newInstance(),1,2.3,new ArrayList<String>()));  
}

  • 运行结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
根据方法名字和参数获取方法,包括继承而来的public方法:Class.getMethod:public java.lang.String com.example.demo.reflex.one.Reflection.publicMethod(int,double,java.util.List)

根据方法名获取本类方法,包括私有的:Class.getDeclaredMethod:public java.lang.String com.example.demo.reflex.one.Reflection.toString()

该类的所有方法,包括继承父类而来的public方法
public java.lang.String com.example.demo.reflex.one.Reflection.toString()
public java.lang.String com.example.demo.reflex.one.Reflection.publicMethod()
public java.lang.String com.example.demo.reflex.one.Reflection.publicMethod(int)
public java.lang.String com.example.demo.reflex.one.Reflection.publicMethod(int,double,java.util.List)
public static int com.example.demo.reflex.one.Reflection.returnOne()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

本类声明的所有方法,不包括继承父类而来的方法
public java.lang.String com.example.demo.reflex.one.Reflection.toString()
public java.lang.String com.example.demo.reflex.one.Reflection.publicMethod()
public java.lang.String com.example.demo.reflex.one.Reflection.publicMethod(int)
public java.lang.String com.example.demo.reflex.one.Reflection.publicMethod(int,double,java.util.List)
private void com.example.demo.reflex.one.Reflection.privateMethod()
public static int com.example.demo.reflex.one.Reflection.returnOne()

获取该方法的参数:Method.getParameterTypes
int
double
interface java.util.List

获取方法的名字:Method.getName()publicMethod
 获取方法的访问属性:Method.isAccessible()false
 获取方法的返回类型:Method.getReturnType()class java.lang.String
反射调用方法Reflection.publicMethod(int i, double d), i = 1, d = 2.3

Constructor

  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

@Test
   public void constructorTest() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
      Class<?> aClass = Class.forName("com.example.demo.reflex.one.Reflection");

      Constructor<?>[] constructors = aClass.getConstructors();
      System.out.println("获取所有的构造方法:Class.getConstructors:");
      for(Constructor c:constructors){
         System.out.println(c);
      }
      System.out.println();
      Constructor<?> constructor = aClass.getConstructor(String.class);
      System.out.println("Class.getConstructor(T.class):指定参数顺序来获取构造函数:"+constructor);
      System.out.println();
      System.out.println("以整数形式返回方法对象的Java修饰符:constructor.getModifiers():"+constructor.getModifiers());
      System.out.println();
      System.out.println("Constructor.isAccessible():获取该Constructor的访问权限:"+constructor.isAccessible());
      System.out.println();
      Class<?>[] parameterTypes = constructors[0].getParameterTypes();
      System.out.println("Constructor.getParameterTypes():获取该方法的参数列表:");
      for(Class param:parameterTypes){
         System.out.println(param);
      }
      System.out.println();
      System.out.println("Constructor.isVarArgs():判断该方法是否带了可变数量的参数:" + constructor.isVarArgs());
      System.out.println();
      System.out.println("实例化");
      // 根据指定的构造方法实例化出一个类的实例来,重要
      Reflection reflection = (Reflection) constructor.newInstance("测试");
      System.out.println("Constructor.newInstance():" + reflection);
   }
   
  • 运行结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

获取所有的构造方法:Class.getConstructors:
public com.example.demo.reflex.one.Reflection(java.lang.String,double,boolean)
public com.example.demo.reflex.one.Reflection(java.lang.String)
public com.example.demo.reflex.one.Reflection()

Class.getConstructor(T.class):指定参数顺序来获取构造函数:public com.example.demo.reflex.one.Reflection(java.lang.String)

以整数形式返回方法对象的Java修饰符:constructor.getModifiers():1

Constructor.isAccessible():获取该Constructor的访问权限:false

Constructor.getParameterTypes():获取该方法的参数列表:
class java.lang.String
double
boolean

Constructor.isVarArgs():判断该方法是否带了可变数量的参数:false

实例化
Constructor.newInstance()str = 测试, d = 0.0, b = false

Modifier枚举值列表

Field、Constructor、Method中都有getModifiers()方法,返回的是表示此对象的Java语言修饰符,详细看下每个修饰符对应的枚举值:

修饰符 枚举值
public 1
private 2
protected 4
static 8
final 16
synchronized 32
volatile 64
transient 128
native 256
interface 512
abstract 1024
strict 2048

可以调用Modifier.toString()来解析这个值,直接输出修饰符;

总结

  • 自己对反射的理论知识还很差,需要多看书;
  • 我上边的代码其实只是反射中很少的一部分,写这么多代码知识想说明自己去学过,至少自己copy都代表动了手的,总比没动手好;
  • 反射这个东西是个好东西,我只是学到了皮毛,需要学的东西还有很多很多;
  • 其实平时接触的技术中很多都用到了反射,只是自己暂时还没有那个能力去看而已,总有一天会看到的;
  • 在这里十分感谢五月的仓颉,我是看了他写的文章才写出来的这篇文章;当然,你也可以认为我是复制的他的文章;

参考

参考1

坚持原创技术分享,您的支持将鼓励我继续创作!