Java反射机制(Reflection)简解与示例

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

在java环境中,反射机制允许程序在执行时获取某各类自身的定义信息,例如属性和方法等也可以实现动态创建类的对象、变更属性的内容或执行特定的方法的功能。从而使java具有动态语言的特性,增强了程序的灵活性和可移植性。

通过反射你可以获取类的Field、Method、Constructor、Superclass、Interface、Annotation以及泛型和类所在的包等信息。


【1】Reflection功能与API

Java反射机制提供的功能:

1.在运行时判断任意一个对象所属的类型;
2.在运行时构造任意一个类的对象;
3.在运行时判断任意一个类所具有的成员变量和方法;
4.在运行时调用任意一个对象的方法,甚至可以调用private方法。
5.生成动态代理。


Java反射机制API:

实现java反射机制的API在java.lang.reflect包下,如下所示:

1.java.lang.Class类:代表一个类;

2.java.lang.reflect.Field类:代表类的成员变量;

3.java.lang.reflect.Method类:代表类的方法;

4.java.lang.reflect.Constructor类:代表类的构造方法;

5.java.lang.reflectArray类:提供了动态创建数组以及访问数组的元素的静态方法。该类中所有方法都是静态的。


【2】Class类与加载机制

① class类定义

在Object类中定义了以下的方法,此方法将被所有子类继承:

public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

这里写图片描述

可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。

Class本身也是一个类;
Class 对象只能由系统建立对象;
一个类在 JVM 中只会有一个Class实例 ;
一个Class对象对应的是一个加载到JVM中的一个.class文件;
每个类的实例都会记得自己是由哪个 Class 实例所生成;
通过Class可以完整地得到一个类中的完整结构 。


② class类常用方法

方法名功能说明
static Class<?> forName(String className)返回指定类名 name 的 Class 对象
T newInstance调用缺省构造函数,返回该Class对象的一个实例
String getName()返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称
native Class<? super T> getSuperclass()返回当前Class对象的父类的Class对象
Class<?>[] getInterfaces()获取当前Class对象的接口
ClassLoader getClassLoader()返回该类的类加载器
Constructor<?>[] getConstructors()获取自身的所有的 public Constructor
Field[] getFields()获取自身和父类的所有的 public Field
Method[] getMethods()获取自身和父类所有的 public Method
Field[] getDeclaredFields()获取自身所有的Field,但不包括从父类继承下来的属性
Method[] getDeclaredMethods()获取自身所有的Method,但不包括从父类继承下来的方法
Constructor<?>[] getDeclaredConstructors()获取自身所有的Constructor
Field getField(String name)根据名字获取自身和父类的的 public Field
Field getDeclaredField(String name)根据名字获取自身的属性
Method getMethod(String name)根据名字获取自身和父类的的 public Method
Method getDeclaredMethod(String name)根据名字获取自身的Method
public Constructor<T> getConstructor(Class<?>... parameterTypes)获取自身的 public Constructor
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)根据名字获取自身的Constructor

这里Field示例总结如下:

# 获取自身和父类的所有的 public Field
 public Field[] getFields() throws SecurityException {}

# 获取自身所有的Field,但不包括从父类继承下来的属性
public Field[] getDeclaredFields() throws SecurityException {}

# 根据名字获取自身和父类的 public Field
public Field getField(String name)

#  根据名字获取自身的 Field
public Field getDeclaredField(String name)

Field代码测试如下:

public class Father {
	
	 public int a;
	 
     private int b;	
     
     protected int f;
     
     int g;

}
public class Son extends Father {
	
	int c;
	 
    private String d;
 
    protected float e;
    
    public int h;

}
public class FieldTest {
	
	public static void main(String[] args) {
		Class cls = Son.class;
		 
        try {
          Field c = cls.getDeclaredField("c");
          System.out.println("getDeclaredField获取自身default :"+c);
          Field d = cls.getDeclaredField("d");
          System.out.println("getDeclaredField获取自身private :"+d);
          Field e = cls.getDeclaredField("e");
          System.out.println("getDeclaredField获取自身protected :"+e);
          Field h = cls.getDeclaredField("h");
          System.out.println("getDeclaredField获取自身public :"+h);
          
          // 父类public获取不到
//          Field a = cls.getDeclaredField("a");
//          System.out.println("getDeclaredField获取父类public :"+a);
          // 父类private获取不到
//          Field b = cls.getDeclaredField("b");
//          System.out.println("getDeclaredField获取父类private :"+b);
//          父类protected获取不到
//          Field f = cls.getDeclaredField("f");
//          System.out.println("getDeclaredField获取父类protected :"+f);
//          父类default获取不到
//          Field g = cls.getDeclaredField("g");
//          System.out.println("getDeclaredField获取父类default :"+g);
 
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("getDeclaredField "+e.getMessage());
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("getDeclaredField "+e.getMessage());
        }
 
        try {
        	// 自身default获取不到
//            Field c = cls.getField("c");
//            System.out.println("getField获取自身default :"+c);
        	// 自身private获取不到
//            Field d = cls.getField("d");
//            System.out.println("getField获取自身private :"+d);
        	// 自身protected获取不到
//            Field e = cls.getField("e");
//            System.out.println("getField获取自身protected :"+e);
            Field h = cls.getField("h");
            System.out.println("getField获取自身public :"+h);
            
            Field a = cls.getField("a");
            System.out.println("getField获取父类public :"+a);
            // 父类private获取不到
//            Field b = cls.getField("b");
//            System.out.println("getField获取父类private :"+b);
//            父类protected获取不到
//            Field f = cls.getField("f");
//            System.out.println("getField获取父类protected :"+f);
            //父类default获取不到
//            Field g = cls.getField("g");
//            System.out.println("getField获取父类default :"+g);
 
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("getField "+e.getMessage());
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("getField "+e.getMessage());
        }
 
        // 获取自身所有,不包括父类属性
        Field[] filed1 = cls.getDeclaredFields();
 
        for ( Field f : filed1 ) {
            System.out.println("Declared Field :"+f.getName());
        }
        // 获取所有public属性,包括父类的
        Field[] filed2 = cls.getFields();
 
        for ( Field f : filed2 ) {
            System.out.println("Field :"+f.getName());
        }

	}

}

Field测试结果如下:

getDeclaredField获取自身default :int com.web.test.Son.c
getDeclaredField获取自身private :private java.lang.String com.web.test.Son.d
getDeclaredField获取自身protected :protected float com.web.test.Son.e
getDeclaredField获取自身public :public int com.web.test.Son.h
getField获取自身public :public int com.web.test.Son.h
getField获取父类public :public int com.web.test.Father.a
Declared Field :c
Declared Field :d
Declared Field :e
Declared Field :h
Field :h
Field :a

Method示例总结如下:

# 获取自身和父类的所有的 public Method
 public Method[] getMethods() throws SecurityException {

# 获取自身所有的Method,但不包括从父类继承下来的方法
 public Method[] getDeclaredMethods() throws SecurityException {}

# 根据名字获取自身和父类的 public Method
public Method getMethod(String name, Class<?>... parameterTypes)

#  根据名字获取自身的 Method
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

Method代码测试如下:


public class Father {
	
	 public int a;
	 
     private int b;	
     
     protected int f;
     
     int g;
     
     public  void methodA(){
    	 System.out.println("父类public  methodA");
     }
     private void methodB(){
    	 System.out.println("父类private methodB");
     }
     protected void methodF(){
    	 System.out.println("父类protected methodF");
     }
     void methodG(){
    	 System.out.println("父类default methodG");
     }

}

public class Son extends Father {
	
	int c;
	 
    private int d;
 
    protected float e;
    
    public int h;
    
    void methodC(){
   	 System.out.println("自身default   methodC");
    }
    private void methodD(){
   	 System.out.println("自身private methodD");
    }
    protected void methodE(){
   	 System.out.println("自身protected methodE");
    }
    public void methodH(){
   	 System.out.println("自身public methodH");
    }
}

public class MethodTest {
	
	public static void main(String[] args) {
		Class cls = Son.class;
		 
        try {
          Method c = cls.getDeclaredMethod("methodC");
          System.out.println("getDeclaredMethod获取自身default :"+c);
          Method d = cls.getDeclaredMethod("methodD");
          System.out.println("getDeclaredMethod获取自身private :"+d);
          Method e = cls.getDeclaredMethod("methodE");
          System.out.println("getDeclaredMethod获取自身protected :"+e);
          Method h = cls.getDeclaredMethod("methodH");
          System.out.println("getDeclaredMethod获取自身public :"+h);
          
          // 父类public获取不到
//          Method a = cls.getDeclaredMethod("methodA");
//          System.out.println("getDeclaredMethod获取父类public :"+a);
          // 父类private获取不到
//          Method b = cls.getDeclaredMethod("methodB");
//          System.out.println("getDeclaredMethod获取父类private :"+b);
//          父类protected获取不到
//          Method f = cls.getDeclaredMethod("methodF");
//          System.out.println("getDeclaredMethod获取父类protected :"+f);
//          父类default获取不到
//          Method g = cls.getDeclaredMethod("methodG");
//          System.out.println("getDeclaredMethod获取父类default :"+g);
 
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("getDeclaredMethod "+e.getMessage());
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("getDeclaredMethod "+e.getMessage());
        }
 
        try {
        	// 自身default获取不到
//            Method c = cls.getMethod("methodC");
//            System.out.println("getMethod获取自身default :"+c);
        	// 自身private获取不到
//            Method d = cls.getMethod("methodD");
//            System.out.println("getMethod获取自身private :"+d);
        	// 自身protected获取不到
//            Method e = cls.getMethod("methodE");
//            System.out.println("getMethod获取自身protected :"+e);
        	Method h = cls.getMethod("methodH",null);
            System.out.println("getMethod获取自身public :"+h);
            
            Method a = cls.getMethod("methodA",null);
            System.out.println("getMethod获取父类public :"+a);
            // 父类private获取不到
//            Method b = cls.getMethod("methodB");
//            System.out.println("getMethod获取父类private :"+b);
//            父类protected获取不到
//            Method f = cls.getMethod("methodF");
//            System.out.println("getMethod获取父类protected :"+f);
            //父类default获取不到
//            Method g = cls.getMethod("methodG");
//            System.out.println("getMethod获取父类default :"+g);
 
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("getMethod "+e.getMessage());
        }catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("getMethod "+e.getMessage());
		}
 
        // 获取自身所有,不包括父类方法
        Method[] method1 = cls.getDeclaredMethods();
 
        for ( Method m : method1 ) {
            System.out.println("Declared Method :"+m.getName());
        }
        // 获取所有public方法,包括父类的
        Method[] method2 = cls.getMethods();
 
        for ( Method m : method2 ) {
            System.out.println("Method :"+m.getName());
        }

	}

}

Method测试结果如下:

getDeclaredMethod获取自身default :void com.web.test.Son.methodC()
getDeclaredMethod获取自身private :private void com.web.test.Son.methodD()
getDeclaredMethod获取自身protected :protected void com.web.test.Son.methodE()
getDeclaredMethod获取自身public :public void com.web.test.Son.methodH()
getMethod获取自身public :public void com.web.test.Son.methodH()
getMethod获取父类public :public void com.web.test.Father.methodA()
Declared Method :methodC
Declared Method :methodD
Declared Method :methodH
Declared Method :methodE
Method :methodH
Method :methodA
Method :wait
Method :wait
Method :wait
Method :equals
Method :toString
Method :hashCode
Method :getClass
Method :notify
Method :notifyAll

Constructor总结如下:

# 获取自身所有的 public Constructor
public Constructor<?>[] getConstructors() throws SecurityException {}

# 获取自身所有的Constructor--构造器不能继承
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {}

# 获取自身 public Constructor
public Constructor<T> getConstructor(Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {}

# 获取自身的 Constructor
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
throws NoSuchMethodException, SecurityException {

Constructor测试代码如下:

public class Father {
	
	 public int a;
	 
     private int b;	
     
     protected int f;
     
     int g;
     
     public  void methodA(){
    	 System.out.println("父类public  methodA");
     }
     private void methodB(){
    	 System.out.println("父类private methodB");
     }
     protected void methodF(){
    	 System.out.println("父类protected methodF");
     }
     void methodG(){
    	 System.out.println("父类default methodG");
     }
     
     public Father(){
    	 super();
     }
     private Father(int b){
    	 super();
    	 this.b = b;
     }
     protected Father(int f,int b ){
    	 super();
    	 this.f = f;
    	 this.b = b;
     }
     Father(int f,int b,int g ){
    	 super();
    	 this.f = f;
    	 this.b = b;
    	 this.g = g;
     }
     public Father(int a,int f,int b,int g ){
    	 super();
    	 this.a = a;
    	 this.f = f;
    	 this.b = b;
    	 this.g = g;
     }
}

public class Son extends Father {
	
	int c;
	 
    private int d;
 
    protected float e;
    
    public int h;
    
    void methodC(){
   	 System.out.println("自身default   methodC");
    }
    private void methodD(){
   	 System.out.println("自身private methodD");
    }
    protected void methodE(){
   	 System.out.println("自身protected methodE");
    }
    public void methodH(){
   	 System.out.println("自身public methodH");
    }
    
    public Son(){
   	 super();
    }
    private Son(int d){
   	 super();
   	 this.d = d;
    }
    protected Son(int d,int e ){
   	 super();
   	 this.e = e;
   	 this.d = d;
    }
    Son(int c,int d,int e ){
   	 super();
   	 this.c = c;
   	 this.d = d;
   	 this.e = e;
    }
}

public class ConstructorTest {
	
	public static void main(String[] args) {
		Class cls = Son.class;
		 
        try {
          Constructor<Son> c = cls.getDeclaredConstructor(int.class,int.class,int.class);
          System.out.println("getDeclaredConstructor获取自身default :"+c);
          Constructor<Son> d = cls.getDeclaredConstructor(int.class);
          System.out.println("getDeclaredConstructor获取自身private :"+d);
          Constructor<Son> e = cls.getDeclaredConstructor(int.class,int.class);
          System.out.println("getDeclaredConstructor获取自身protected :"+e);
          Constructor<Son> h = cls.getDeclaredConstructor();
          System.out.println("getDeclaredConstructor获取自身public :"+h);
          
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            System.out.println("getDeclaredConstructor "+e.getMessage());
        } catch (SecurityException e) {
            e.printStackTrace();
            System.out.println("getDeclaredConstructor "+e.getMessage());
        }
 
        try {
        	
             // 自身default获取不到
//        	 Constructor<Son> c = cls.getConstructor(int.class,int.class,int.class);
//             System.out.println("getConstructor获取自身default :"+c);
             // 自身private获取不到
//             Constructor<Son> d = cls.getConstructor(int.class);
//             System.out.println("getConstructor获取自身private :"+d);
             // 自身protected获取不到
//             Constructor<Son> e = cls.getConstructor(int.class,int.class);
//             System.out.println("getConstructor获取自身protected :"+e);
             Constructor<Son> h = cls.getConstructor();
             System.out.println("getConstructor获取自身public :"+h);
             
             // 父public can't get
//             Constructor constructor = cls.getConstructor(int.class,int.class,int.class,int.class);
//             System.out.println("getConstructor获取父public :"+constructor);
 
        } catch (SecurityException | NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("getConstructor "+e.getMessage());
        }
 
        // 获取自身所有 Constructor
        Constructor[] constructors1 = cls.getDeclaredConstructors();
 
        for ( Constructor c : constructors1 ) {
            System.out.println("Declared Constructor :"+c.getName());
        }
        // 获取自身所有public Constructor
        Constructor[] constructors2 = cls.getConstructors();
 
        for ( Constructor c : constructors2 ) {
            System.out.println("Constructor :"+c.getName());
        }
	}
}

Constructor测试结果如下:

getDeclaredConstructor获取自身default :com.web.test.Son(int,int,int)
getDeclaredConstructor获取自身private :private com.web.test.Son(int)
getDeclaredConstructor获取自身protected :protected com.web.test.Son(int,int)
getDeclaredConstructor获取自身public :public com.web.test.Son()
getConstructor获取自身public :public com.web.test.Son()
Declared Constructor :com.web.test.Son
Declared Constructor :com.web.test.Son
Declared Constructor :com.web.test.Son
Declared Constructor :com.web.test.Son
Constructor :com.web.test.Son


③ 实例化类的四种方法

  • 已知具体的类,通过类的class属性获取
Class clazz = String.class
# 该方法最为安全可靠,程序性能最高
  • 已知某个类的实例,调用该实例的getClass()方法获 取Class对象
Class clazz = person.getClass();
  • 已知一个类的全类名,且该类在类路径下,可通过 Class类的静态方法forName()获取
Class clazz = Class.forName(“java.lang.String”);
# 可能抛出ClassNotFoundException
  • ClassLoader
ClassLoader cl = this.getClass().getClassLoader();
Class clazz = cl.loadClass(“类的全类名”);


【3】类的加载过程

当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。

这里写图片描述
这里写图片描述


【4】ClassLoader

类加载器是用来把类(class)装载进内存的。

JVM 规范定义了两种类型的类加载器:启动类加载器(bootstrap)和用户自定义加载器(user-defined class loader)。

JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示:

这里写图片描述

实例代码如下:

//1.获取一个系统类加载器
ClassLoader classloader = ClassLoader.getSystemClassLoader();
System.out.println(classloader);

//2.获取系统类加载器的父类加载器,即扩展类加载器
classloader = classloader.getParent();
System.out.println(classloader);

//3.获取扩展类加载器的父类加载器,即引导类加载器
classloader = classloader.getParent();
System.out.println(classloader);

//4.测试当前类由哪个类加载器进行加载
classloader = Class.forName("exer2.ClassloaderDemo").getClassLoader();
System.out.println(classloader);


实例demo–动态创建数组对象:

/*,对数组元素赋值和取值*/
public void test(){
	Class c = Class.forName("java.lang.String");
	//create a String type Array,the length is 10
	Object arr = Array.newInstance(c,10);
	//at the index =5 ,assignment the parameter value
	Array.set(arr,5,"this is a test");
	//get the index=5 value
	String s = (String)Array.get(arr,5);
	System.out.println(s);
}

【5】使用反射获取私有属性/方法

使用Class类中的方法可以获得该类中的所有Constructor对象,Method对象,和Field对象。

但是无法访问私有化的构造方法,普通方法,和私有属性,此时我们可以使用他们继承父类(AccessibleObject)中的setAccessible()方法,来设置或取消访问检查,以达到访问私有对象的目的。

如下示例,获取私有属性(方法类同):

 	 Field[] fields = Test.class.getDeclaredFields();
      for (int i = 0; i < fields.length; i++) {
          fields[i].setAccessible(true);
          try {
              System.out.println(fields[i].get(test));
          } catch (IllegalArgumentException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }

其他点击查看反射详解参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

流烟默

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

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

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

打赏作者

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

抵扣说明:

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

余额充值