Java中的反射机制示例详解

网友投稿 308 2022-08-22


Java中的反射机制示例详解

目录反射什么是Class类获取Class实例的三种方式通过反射创建类对象通过反射获取类属性、方法、构造器更改访问权限和实例赋值运用场景

反射

反射就是把java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制

每一个Java程序执行必须通过编译、加载、链接和初始化四个阶段

1.编译:将.java.文件编译成字节码.class文件

2.加载:查找并加载类的二进制数据

3.链接:

验证:确保被加载类的正确性为类的静态变量分配内存,并将其初始化为默认值将类中的符号转换为直接引用

4.初始化:为类的静态变量赋予正确的初始值

什么是Class类

在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息

也就是说,无论你是什么对象,总会有有一个隐藏的Class对象与你相对应,而Class的实例表示正在运行的 Java 应用程序中的类和接口。借此,实现了我们Java的反射机制。

获取Class实例的三种方式

实例化对象调用getClass()方法

使用Class类的静态方法forName(),用类的名字获取一个Class实例

运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例

用代码来看一看:

public class reflect {

public static void main(String[] args) throws ClassNotFoundException {

Apple apple = new Apple();

// 使用对象的getClass()方法

Class a1 = apple.getClass();

// 使用Class类的静态方法forName()

Class a2 = Class.forName("p1.apple");

// 运用.class的方式来获取Class实例

Class a3 = Apple.class;

System.out.printf("a1: %s\na2: %s\na3: %s", a1, a2, a3);

}

}

class Apple {

private Integer weight;

private String color;

}

打印结果:

a1: class p1.applea2: class p1.applea3: class p1.apple进程已结束,退出代码0

通过反射创建类对象

通过反射创建类对象主要有两种方式:通过 Class 对象的 newInstance() 方法、通过 Constructor 对象的 newInstance() 方法。

public class reflect {

public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

// 通过 Class 对象的 newInstance() 方法

Class temp1 = Apple.class;

Apple apple1 = (Apple) temp1.newInstance();

// 通过 Constructor 对象的 newInstance() 方法

Class temp2 = Apple.class;

edPnFCNyrlConstructor constructor1 = temp2.getConstructor();

Apple apple2 = (Apple)constructor1.newInstance();

// 通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。

Class temp3 = Apple.class;

Constructor constructor2 = temp3.getConstructor(Integer.class,String.class);

Apple apple = (Apple)constructor2.newInstance(2, "Red");

System.out.println(apple);

}

}

class Apple {

private Integer weight;

private String color;

// 无参构造器

public Apple() {

System.out.println("我是无参构造!");

}

// 有参构造器

public Apple(Integer weight,String color) {

this.weight = weight;

this.color = color;

}

// 重写方法 方便打印显示对象内容

@Override

public String toString() {

return "Apple{" +

"weight=" + weight +

", color='" + color + '\'' +

'}';

}

}

打印结果:

我是无参构造!我是无参构造!Apple{weight=2, color='Red'}进程已结束,退出代码0

通过反射获取类属性、方法、构造器

public class reflect {

public static void main(String[] args) throws NoSuchFieldException {

// 返回一个类中所有可访问的公共字段,包括该类的公共字段和其继承的类的公共字段

Field[] fields1 = Apple.class.getFields();

System.out.println("getFields结果");

Arrays.stream(fields1).forEach(System.out::println);

// 返回一个类中全部字段,但只包括该类的字段

Field[] fields2 = Apple.class.getDeclaredFields();

System.out.println("getDeclaredFields结果");

Arrays.stream(fields2).forEach(System.out::println);

// 根据字段名返回一个公开字段

Field field1 = Apple.class.getField("noThing");

System.out.println("getField结果");

System.out.println(field1);

// 根据字段名返回一个字段

Field field2 = Apple.class.getDeclaredField("color");

System.out.println("getDeclaredField结果");

System.out.println(field2);

// 同Field Method也有四种获取方式

// 这里举其中一个例子

Method[] methods = Apple.class.getDeclaredMethods();

System.out.println("getDeclaredMethods结果");

Arrays.stream(methods).forEach(System.out::println);

// 同上 举一个获取构造器的例子

Constructor[] constructors = Apple.class.getDeclaredConstructors();

System.out.println("getDeclaredConstructors结果");

Arrays.stream(constructors).forEach(System.out::println);

}

}

class Apple {

private Integer weight;

private String color;

public String noThing;

public Apple() {

}

public Apple(Integer weight, String color) {

this.weight = weight;

this.color = color;

}

@Override

public String toString() {

return "Apple{" +

"weight=" + weight +

", color='" + color + '\'' +

'}';

}

}

打印结果:

getFields结果public java.lang.String p1.Apple.noThinggetDeclaredFields结果private java.lang.Integer p1.Apple.weightprivate java.lang.String p1.Apple.colorpublic java.lang.String p1.Apple.noThinggetField结果public java.lang.String p1.Apple.noThinggetDeclaredField结果private java.lang.String p1.Apple.colorgetDeclaredMethods结果public java.lang.String p1.Apple.toString()getDeclaredConstructors结果public p1.Apple()public p1.Apple(java.lang.Integer,java.lang.String)

更改访问权限和实例赋值

首先,通过field.setAccessible()可更改属性的访问权限

public class reflect {

public static void main(String[] args) throws NoSuchFieldException {

// 实例化一个Apple

Apple apple = new Apple();

// 获取所有字段 并统一设定为公有属性

Field[] fields = Apple.class.getDeclaredFields();

Arrays.stream(fields).forEach( field -> {

field.setAccessible(true);

// 打印结果

System.out.println(field);

try {

if (field.getType() == Integer.class) {

field.set(apple, 5);

} else if (field.getType() == String.class) {

field.set(apple, "Red");

}

} catch (IllegalAccessException e) {

e.printStackTrace();

}

});

// 查看apple结果

System.out.println(apple);

}

}

class Apple {

private Integer weight;

private String color;

@Override

public String toString() {

return "Apple{" +

edPnFCNyrl "weight=" + weight +

", color='" + color + '\'' +

'}';

}

}

打印结果:

private java.lang.Integer p1.Apple.weightprivate java.lang.String p1.Apple.colorApple{weight=5, color='Red'}进程已结束,退出代码0

通过源码文档和打印结果,可见setAccessable()方法并没有改变类字段的访问权限,而是作为一个标志,使得我们反射获取实例过程中可以对其进行操作

运用场景

在我看来,反射机制实际上就是上帝模式,如果说方法的调用是 Java 正确的打开方式,那反射机制就是上帝偷偷开的后门,只要存在对应的class,一切都能够被调用。

众所周知,语言有静态语言和动态语言两大分类,静态语言例如C/C++、Java、C#等,动态语言有python、php、javascript等。为了让Java语言也有动态语言的特性,有了反射机制,解耦以及提高代码的灵活性。

反射在开发过中或许并不常见,可我们使用的框架工具底层都有反射的存在。动态代理设计模式、JDBC 的数据库的连接、Spring 框架的使用等都应用到了反射机制。

以上就是Java中的反射机制示例详解的详细内容,更多关于Java反射机制的资料请关注我们其它相关文章!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springboot+jwt+微信小程序授权登录获取token的方法实例
下一篇:分布式面试分布式锁实现及应用场景
相关文章

 发表评论

暂时没有评论,来抢沙发吧~