JAVA的反射机制大总结

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制,本篇文章为大家详细讲解一下JAVA的反射机制。

一、Class类

在程序运行期间,Java运行时系统始终对所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。可以通过专门的Java类访问这些信息。保存这些信息的类被称为Class

创建Class类对象的三种方法:

1. 通过getClass方法

Object中的getClass方法将返回一个Class类型的实例。

class Person {
  //...
}

Person p = new Person();
Class c = p.getClass();

2. forName方法

可以通过静态方法forName获得类名对应的Class对象。

String className = "java.util.Date";
Class c = Class.forName(className);

如果需要在运行过程中需要改变类名,就可以使用这种方法。当然,字符串className必须是一种类名或接口(包括包名),否则会出现异常。

3. T.class

Class c1 = Date.class;
Class c2 = int.class;
Class c3 = Double[].class;

T表示任意的Java类型。通过T.class获取匹配的类对象。

注意:一个Class对象实际表示一种类型,而这种类型未必是一种类。

虚拟机为每个类型管理一个Class对象。因此可以用==运算符来实现两个类对象的比较

if (p.getClass() == Person.class) {...}

newInstance方法

通过newInstance方法可以创建一个类的实例。

Person person = p.getClass().newInstance();

创建了一个与p具有相同类类型的实例。newInstance调用默认的构造器初始化创建的对象。如果这个类没有默认的构造器,就会抛出异常。

二、利用反射解析类结构

获取包名+类名(包括父类名)

package com.xiaoxiaoyihan.reflection;

class Person {
   //...
}

class Student extends Person{

}

public class ReflectionDemo1 {
   public static void main(String[] args) {
       Student s = new Student();
       Class cl = s.getClass();
       Class superCl = cl.getSuperclass();
       System.out.println("获取类名:" + cl.getName());
       System.out.println("获取父类名:" + superCl.getName());
   }
}

【运行结果】: 获取类名:com.xiaoxiaoyihan.reflection.Student 获取父类名:com.xiaoxiaoyihan.reflection.Person

说明:如果类在一个包中,包的名字也作为类名的一部分。

一点扩展:

首先看一个例子:

class Person {
   private String name = "萧萧弈寒";
   // 省略setter和getter
}
class Animal {
   private String name = "paqi";
   // 省略setter和getter
}

Person p;
Animal a;
Class cPerson = p.getClass();
Class cAnimal = a.getClass();
// cPerson.getName()获取的是类名、p.getName()是Person实例的name属性值
System.out.println(cPerson.getName() + "" + p.getName());
System.out.println(cAnimal.getName() + "" + p.getName());

【运行结果】: com.xxyh.reflec.Person萧萧弈寒 com.xxyh.reflec.Animalpaqi

由此说明,一个Person对象p表示一个特定人的属性,一个Animal对象a表示一个特定动物的属性,一个Class对象表示一个特定类(Person或Animal)的属性。从这点看,Class的实例是一种对象

解析构造函数(Constructor)

Class类中的getConstructors方法将返回公共构造器数组。Class类中的getDeclaredConstructors将返回类中声明的构造器数组。

package com.xiaoxiaoyihan.reflection;

import java.lang.reflect.Constructor;
class Person {
   private String name;
   private int age;

   private Person() {}

   protected Person(String name) {
       this.name = name;
   }

   public Person(String name, int age) {
       this.name = name;
       this.age = age;
   }
}
public class ReflectionDemo1 {
   public static void main(String[] args) throws ClassNotFoundException {
       Class cl = Class.forName("com.xiaoxiaoyihan.reflection.Person");  // 直接抛出异常以简化代码

       Constructor[] constructors = cl.getDeclaredConstructors();
       //Constructor[] constructors = cl.getConstructors();
       for (Constructor c :constructors) {
           System.out.println(c);
       }
   }
}

【运行结果】:

private com.xiaoxiaoyihan.reflection.Person() protected com.xiaoxiaoyihan.reflection.Person(java.lang.String) public com.xiaoxiaoyihan.reflection.Person(java.lang.String,int)

// public com.xiaoxiaoyihan.reflection.Person(java.lang.String,int)// 本部分为运行getConstructors方法输出结果

对结果加以分析,会发现通过System.out.println(c);直接打印的构造函数是由几部分组成的,其中包括了修饰符(public/protected/private)、**类名*以及*构造函数的参数,那么,这些部分是如何获取的呢?

Modifier类中包含静态方法getModifiers方法,它返回一个整数i,用不同的数值表示public、static、final这样的修饰符。Modifier中的静态方法toString(i)返回对应的修饰符。Constructor类中包含由静态方法getParameterTypes,它返回一个描述参数类型的Class对象数组

package com.xiaoxiaoyihan.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

class Person {
   private String name;
   private int age;

   private Person() {}

   protected Person(String name) {
       this.name = name;
   }

   public Person(String name, int age) {
       this.name = name;
       this.age = age;
   }
}
public class ReflectionDemo1 {
   public static void main(String[] args) throws ClassNotFoundException {
       Class cl = Person.class;

       Constructor[] constructors = cl.getDeclaredConstructors();
       for (Constructor c :constructors) {
           // 获取包名和类名
           String name = c.getName();

           // 获取修饰符
           String modifiers = Modifier.toString(c.getModifiers());
           if (modifiers.length() > 0) {   //如果有修饰符
               System.out.print(modifiers + " ");
           }

           System.out.print(name + "(");

           // 获取构造函数的参数类型
           Class[] paramTypes = c.getParameterTypes();

           for (int i = 0; i if (i > 0) {    // 如果不止一个参数,使用","将参数类型分割
                   System.out.print(",");
               }
               System.out.print(paramTypes[i].getName());
           }
           System.out.println(");");
       }

   }
}

【运行结果】:

private com.xiaoxiaoyihan.reflection.Person(); protected com.xiaoxiaoyihan.reflection.Person(java.lang.String); public com.xiaoxiaoyihan.reflection.Person(java.lang.String,int);

解析方法(Method)

Class类中的getMethods将返回方法的数组,其中包括本类的所有方法、从接口实现的方法、父类的公共(public)方法、父类的父类的公共方法……一直延伸到Object的公共方法getDeclaredMethods方法将返回本类声明的方法、从接口实现的方法

package com.xiaoxiaoyihan.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;


class Person/* extends Object */ {
   private void privateMethodPerson() {
       //...
   }

   protected void protectedMethodPerson() {
       // ...
   }

   public void publicMethodPerson() {
       //...
   }
}

interface Smoke {
   void smoking();
}

class Student extends Person implements Smoke{
   @Override
   public void smoking() {
       // ...
   }

   private void privateMethodStudent() {
       //...
   }

   protected void protectedMethodStudent() {
       // ...
   }

   public void publicMethodStudent() {
       //...
   }
}


public class ReflectionDemo1 {
   public static void main(String[] args) {
       Student s = new Student();
       Class cl = s.getClass();
       Method[] methods = cl.getDeclaredMethods();
//        Method[] methods = cl.getMethods();

       for (Method m : methods) {
           System.out.println(m);
       }
   }
}

【运行结果】:

public void com.xiaoxiaoyihan.reflection.Student.smoking() protected void com.xiaoxiaoyihan.reflection.Student.protectedMethodStudent() private void com.xiaoxiaoyihan.reflection.Student.privateMethodStudent() public void com.xiaoxiaoyihan.reflection.Student.publicMethodStudent()

上面的例子故意给出一种继承结构,是为了查看getMethods的结果,在此就不给出结果了。注意Person默认继承了Object类。顺便说一句,笔者(非科班自学菜鸟)曾在面试的时候被问到Object中有哪些方法,估计他是想问有哪些常用方法吧,我没答全~2333,不知道读者您能一眼看出结果吗??。

类似地,我们看到上面的System.out.println(m);打印出方法由修饰符返回值**、*类名方法名以及参数*组成。那么这些部分是如果获取的呢? 与Construction类相似,Method类中也提供了静态方法getParamTypes,该方法返回描述参数类型的Class对象数组。此外,Method还提供了getReturnType方法,用于获取返回类型的Class对象。

 

复制代码

package com.xiaoxiaoyihan.reflection;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

class Person {

   private String name = "萧萧弈寒";

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public static void speak() {
       // ...
   }

   public final void eat() {
       // ...
   }
}


public class ReflectionDemo1 {
   public static void main(String[] args) {

       Class cl = Person.class;

       Method[] methods = cl.getDeclaredMethods();
       for (Method m : methods) {
           // 返回类型的Class对象
           Class retType = m.getReturnType();
           //
           String retTypeName = retType.getName();

           // 获取方法名
           String name = m.getName();

           String modifiers = Modifier.toString(m.getModifiers());
           if (modifiers.length() > 0) // 如果有修饰符
               System.out.print(modifiers + " ");

           // 返回值名
           System.out.print(retType.getName() + " ");

           System.out.print(name + "(");

           Class[] paramTypes = m.getParameterTypes();
           for (int i = 0; i if (i > 0) { // 如果不止一个参数,用","分割
                   System.out.print(paramTypes[i].getName());
               }
           }
           System.out.println(");");
       }

   }
}

【运行结果】: public java.lang.String getName(); public void setName(); public static void speak(); public final void eat();

解析域(Field)

Class类中的getDeclaredFields方法返回类中声明的域数组,getFields方法返回类中的公有域、接口中的域所组成的Field对象数组。

package com.xiaoxiaoyihan.reflection;

import java.lang.reflect.Field;
import java.util.Date;

class Person {
   private String name;
   protected int age;
   public Date birthday;
}

class Student extends Person implements Smoke{
   private float score;
}

interface Smoke {
   String brand = "大中华";
}

public class ReflectionDemo1 {
   public static void main(String[] args) {
       Class cl = Student.class;

       Field[] fields = cl.getFields();
       for (Field f : fields) {
           System.out.println(f);
       }
   }
}

【运行结果】: public static final java.lang.String com.xiaoxiaoyihan.reflection.Smoke.brand public java.util.Date com.xiaoxiaoyihan.reflection.Person.birthday

结果显示了字段由修饰符类型**、*类名字段名构成。这里需要引入Field类中的*getType*方法,它返回*字段声明类型的Class对象。下面同样作出解析:

package com.xiaoxiaoyihan.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Date;

class Person {
   private String name;
   protected int age;
   public Date birthday;
}

public class ReflectionDemo1 {
   public static void main(String[] args) {
       Class cl = Person.class;

       Field[] fields = cl.getDeclaredFields();
       for (Field f : fields) {
           // 属性类型的Class对象
           Class type = f.getType();

           // 属性类型名
           String name = type.getName();
           System.out.print(" ");

           // 修饰符
           String modifiers = Modifier.toString(f.getModifiers());

           if (modifiers.length() > 0) {   // 如果有修饰符
               System.out.print(modifiers + " ");
           }

           System.out.println(type.getName() + " " + name + ";");
       }
   }
}

【运行结果】:

private java.lang.String java.lang.String; protected int int; public java.util.Date java.util.Date;

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/221006.html<

(0)
运维的头像运维
上一篇2025-04-14 20:15
下一篇 2025-04-14 20:16

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注