linux cpu占用率如何看
270
2022-10-23
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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~