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

简介: 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类常用方法


2.png

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

ethod测试结果如下:

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】类的加载过程

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



20180822140138679.jpg


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


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

目录
相关文章
|
1月前
|
Java 开发工具
【GDAL-java的四个常用代码示例】
【GDAL-java的四个常用代码示例】
35 0
|
1月前
|
Java
Java并发编程中的锁机制
【2月更文挑战第22天】 在Java并发编程中,锁机制是一种重要的同步手段,用于保证多个线程在访问共享资源时的安全性。本文将介绍Java锁机制的基本概念、种类以及使用方法,帮助读者深入理解并发编程中的锁机制。
|
1月前
|
Java 程序员
Java中的异常处理机制
【2月更文挑战第22天】在Java编程中,异常处理是一个重要的概念。它允许程序员在程序执行过程中遇到错误时,对错误进行处理,而不是让程序崩溃。本文将介绍Java中的异常处理机制,包括异常的分类、如何捕获和处理异常以及自定义异常等内容。
18 1
|
1月前
|
开发框架 Java API
java反射机制的原理与简单使用
java反射机制的原理与简单使用
17 1
|
1月前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
23 2
|
1天前
|
设计模式 Java Spring
来聊聊Java的反射机制(下)
来聊聊Java的反射机制(下)
5 0
|
3天前
|
Java 数据库连接
深入理解Java异常处理机制
【4月更文挑战第24天】本文将探讨Java中的异常处理机制,包括异常的概念、分类、捕获和抛出等方面。通过深入了解异常处理机制,可以帮助我们编写更加健壮的程序,提高代码的可读性和可维护性。
|
21天前
|
安全 Java 调度
深入理解Java中的线程安全与锁机制
【4月更文挑战第6天】 在并发编程领域,Java语言提供了强大的线程支持和同步机制来确保多线程环境下的数据一致性和线程安全性。本文将深入探讨Java中线程安全的概念、常见的线程安全问题以及如何使用不同的锁机制来解决这些问题。我们将从基本的synchronized关键字开始,到显式锁(如ReentrantLock),再到读写锁(ReadWriteLock)的讨论,并结合实例代码来展示它们在实际开发中的应用。通过本文,读者不仅能够理解线程安全的重要性,还能掌握如何有效地在Java中应用各种锁机制以保障程序的稳定运行。
|
27天前
|
Java 程序员 开发者
深入理解Java异常处理机制
在Java编程中,异常处理是确保程序健壮性与稳定性的重要组成部分。本文旨在深度剖析Java异常处理机制的核心概念、结构及其实际应用策略,帮助开发者更好地理解并运用异常处理来优化程序设计。我们将从Java异常体系结构入手,探讨try-catch-finally语句块的执行流程,分析自定义异常的必要性与实现方式,并通过实例演示如何有效地管理和处理异常情况。
23 3
|
1月前
|
设计模式 XML 存储
java中的反射机制
java中的反射机制
12 1