【Java】反射机制(应用)

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 【Java】反射机制(应用)

本文将通过学习反射工具的部分API并结合具体实例,实现对Java反射机制的初步了解

概述

Java反射机制是指在程序运行过程中,对于任意一个类,都能够获取到该类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

要实际应用Java反射,需要先了解下java.lang.Class类和Java提供反射功能的包java.lang.reflect。

在Java语言中,所有类的对象都是java.lang.Class类的实例,所有类都可以转变为java.lang.Class类型,我们可以通过Class得到一个类的相关信息,如属性和方法等;

java.lang.reflect包下的一些类可以对应接收Class拿到的类的相关信息,如java.lang.reflect.Method接收类中的非构造方法,java.lang.reflect.Field接收类的属性。

 

实例化Class类对象

想要通过Class类对象拿到类对象的相关信息,首先需要获得Class类对象,可以采用以下方法实现:

1、Class.forName()方法

1
Class? c1 = Class.forName("com.cha.Student");

Class? c1 = Class.forName(“com.cha.Student”);

2、类.class

1
Class? c2 = Student.class;

Class? c2 = Student.class;

3、类对象.getClass()方法

12
Student stu = new Student();Class? c3 = stu.getClass();

Student stu = new Student();
Class? c3 = stu.getClass();

注:Student为自定义的类

 

反射实际应用

反射实际应用需要java.lang.Class结合java.lang.reflect包下的一些类,下面将以实际代码演示如何通过反射操作类的属性和方法。

应用1:操作类的属性

通过反射取得类的属性,输出属性相关信息并设置属性值

通过Class的getDeclaredField(Stringname)方法和getDeclaredFields()方法可以拿到类属性成员,由java.lang.reflect.Field接收并操作具体属性字段。

API如下:

【Java】反射机制(应用)

java.lang.reflect.Field的一些方法可以拿到属性的相关信息,API如下:

【Java】反射机制(应用)

代码示例如下:

123456789101112131415161718192021222324252627
try {  Class? clazz = Student.class;  Field[] fields = clazz.getDeclaredFields();  Object obj = clazz.newInstance();  for(Field field : fields) {    System.out.println("属性名称:" + field.getName());    System.out.println("属性类型:" + field.getType().getSimpleName());    boolean flag = field.isAccessible();    System.out.println("属性是否可被外界访问:" + flag);    if (!flag) { // 如果不可被访问,则设置为可访问      field.setAccessible(true);    }    if (field.getType() == String.class) {      field.set(obj, "VALUE");    }    System.out.println("属性值:" + field.get(obj));    System.out.println("-----------------------------");  }} catch (SecurityException e) {  e.printStackTrace();} catch (InstantiationException e) {  e.printStackTrace();} catch (IllegalAccessException e) {  e.printStackTrace();} catch (IllegalArgumentException e) {  e.printStackTrace();}

try {
Class? clazz = Student.class;
Field[] fields = clazz.getDeclaredFields();
Object obj = clazz.newInstance();
for(Field field : fields) {
System.out.println(“属性名称:” + field.getName());
System.out.println(“属性类型:” + field.getType().getSimpleName());
boolean flag = field.isAccessible();
System.out.println(“属性是否可被外界访问:” + flag);
if (!flag) { // 如果不可被访问,则设置为可访问
field.setAccessible(true);
}
if (field.getType() == String.class) {
field.set(obj, “VALUE”);
}
System.out.println(“属性值:” + field.get(obj));
System.out.println(“—————————–”);
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}

运行结果:

【Java】反射机制(应用)

应用2:操作类的方法

 

通过反射取得类的方法,输出方法相关信息

通过Class的getDeclaredMethods()方法可以拿到类方法成员。getDeclaredMethods()可以拿到public、protected、default和private修饰的方法,但不包括继承自父类的方法和构造方法。由java.lang.reflect.Method接收并操作具体方法。

【Java】反射机制(应用)

java.lang.reflect.Method的一些方法可以拿到类方法的相关信息,API如下:

【Java】反射机制(应用)

代码实例如下:

新建Test.java文件,包含各种方法成员,代码如下:

12345678910111213141516171819202122232425262728
public class Test {   private String name;   public Test() {}  public Test(String name) {    this.name = name;  }   public double _public() {    // ...    return 0.23d;  }   protected int _protected() {    // ...    return 10;  }   private String _private() {    // ...    return "";  }   void _default() {    // ...  }}

public class Test {

private String name;

public Test() {}
public Test(String name) {
this.name = name;
}

public double _public() {
// …
return 0.23d;
}

protected int _protected() {
// …
return 10;
}

private String _private() {
// …
return “”;
}

void _default() {
// …
}
}

获取Test.java的方法成员:

123456789
Class? clazz = Test.class;Method[] methods = clazz.getDeclaredMethods();for(Method method : methods) {  System.out.println("方法名称:" + method.getName());  int modifier = method.getModifiers();  System.out.println("方法控制修饰符:" + Modifier.toString(modifier));  System.out.println("方法返回值类型:" + method.getReturnType());  System.out.println("-------------------------");}

Class? clazz = Test.class;
Method[] methods = clazz.getDeclaredMethods();
for(Method method : methods) {
System.out.println(“方法名称:” + method.getName());
int modifier = method.getModifiers();
System.out.println(“方法控制修饰符:” + Modifier.toString(modifier));
System.out.println(“方法返回值类型:” + method.getReturnType());
System.out.println(“————————-“);
}

getModifiers()获取到的修饰符为int类型,需要借助Modifier.toString()转换为字符串(代码见附2)

运行结果如下:

【Java】反射机制(应用)

可以看到运行结果中不包含Test类的构造方法

附1:(导包)

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

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

附2:Modifier.toString(int mod)实现代码(节选)

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
public static final int PUBLIC           = 0x00000001; public static final int PRIVATE          = 0x00000002; public static final int PROTECTED        = 0x00000004; public static final int STATIC           = 0x00000008; public static final int FINAL            = 0x00000010; public static final int SYNCHRONIZED     = 0x00000020; public static final int VOLATILE         = 0x00000040; public static final int TRANSIENT        = 0x00000080; public static final int NATIVE           = 0x00000100; public static final int INTERFACE        = 0x00000200; public static final int ABSTRACT         = 0x00000400; public static final int STRICT           = 0x00000800; public static String toString(int mod) {    StringBuilder sb = new StringBuilder();    int len;     if ((mod & PUBLIC) != 0)        sb.append("public ");    if ((mod & PROTECTED) != 0)     sb.append("protected ");    if ((mod & PRIVATE) != 0)       sb.append("private ");     /* Canonical order */    if ((mod & ABSTRACT) != 0)      sb.append("abstract ");    if ((mod & STATIC) != 0)        sb.append("static ");    if ((mod & FINAL) != 0)         sb.append("final ");    if ((mod & TRANSIENT) != 0)     sb.append("transient ");    if ((mod & VOLATILE) != 0)      sb.append("volatile ");    if ((mod & SYNCHRONIZED) != 0)  sb.append("synchronized ");    if ((mod & NATIVE) != 0)        sb.append("native ");    if ((mod & STRICT) != 0)        sb.append("strictfp ");    if ((mod & INTERFACE) != 0)     sb.append("interface ");     if ((len = sb.length())  0)    /* trim trailing space */        return sb.toString().substring(0, len-1);    return "";}

public static final int PUBLIC = 0x00000001;

public static final int PRIVATE = 0x00000002;

public static final int PROTECTED = 0x00000004;

public static final int STATIC = 0x00000008;

public static final int FINAL = 0x00000010;

public static final int SYNCHRONIZED = 0x00000020;

public static final int VOLATILE = 0x00000040;

public static final int TRANSIENT = 0x00000080;

public static final int NATIVE = 0x00000100;

public static final int INTERFACE = 0x00000200;

public static final int ABSTRACT = 0x00000400;

public static final int STRICT = 0x00000800;

public static String toString(int mod) {
StringBuilder sb = new StringBuilder();
int len;


if ((mod & PUBLIC) != 0)        sb.append("public ");
if ((mod & PROTECTED) != 0)     sb.append("protected ");
if ((mod & PRIVATE) != 0)       sb.append("private ");

/* Canonical order */
if ((mod & ABSTRACT) != 0)      sb.append("abstract ");
if ((mod & STATIC) != 0)        sb.append("static ");
if ((mod & FINAL) != 0)         sb.append("final ");
if ((mod & TRANSIENT) != 0)     sb.append("transient ");
if ((mod & VOLATILE) != 0)      sb.append("volatile ");
if ((mod & SYNCHRONIZED) != 0)  sb.append("synchronized ");
if ((mod & NATIVE) != 0)        sb.append("native ");
if ((mod & STRICT) != 0)        sb.append("strictfp ");
if ((mod & INTERFACE) != 0)     sb.append("interface ");

if ((len = sb.length())  0)    /* trim trailing space */
    return sb.toString().substring(0, len-1);
return "";

}

— END —

【Java】反射机制(应用)

原文始发于微信公众号(程序员阿木):【Java】反射机制(应用)

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 【Java】反射机制(应用)


 上一篇
JVM核心知识体系 JVM核心知识体系
1.问题 1、如何理解类文件结构布局? 2、如何应用类加载器的工作原理进行将应用辗转腾挪? 3、热部署与热替换有何区别,如何隔离类冲突? 4、JVM如何管理内存,有何内存淘汰机制? 5、JVM执行引擎的工作机制是什么?
下一篇 
【Java】注解开发 【Java】注解开发
本文将学习注解开发、在实际案例中讲解注解使用和注解信息获取、了解几个Java常用内置注解 概述Annotation(注解)是JDK1.5及以后版本引入的,以‘@注解名’在代码中存在。注解是一种独立于程序业务逻辑的标识,具有生成文档、跟踪代码