网站首页 > 技术文章 正文
一 , 什么是java反射机制?
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
- JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods
- Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”
JAVA反射提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
Class类:代表一个类
Field 类:代表类的成员变量(成员变量也称为类的属性)
Method类:代表类的方法
Constructor 类:代表类的构造方法
Array类:提供了动态创建数组,以及访问数组的元素的静态方法
Reflection API的实际运用
在java.lang.Object 类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API 中的核心类,它有以下方法
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
利用反射机制运行时复制对象
public class User {
private Long id;
private String name;
private int age;
public User() {
}
public Customer(final String name, final int age) {
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName (final String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(final int age) {
this.age = age;
}
}
ublic class ReflectTest {
public Object copy(final Object object) throws Exception {
Class<?> classType = object.getClass(); // 获得对象的类型
System.out.println("Class:" + classType.getName());
// 通过默认构造方法创建一个新的对象
Object objectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
Field fields[] = classType.getDeclaredFields(); // 获得对象的所有属性
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
String fieldName = field.getName();
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getMethodName = "get" + firstLetter + fieldName.substring(1); // 获得和属性对应的getXXX()方法的名字
String setMethodName = "set" + firstLetter + fieldName.substring(1); // 获得和属性对应的setXXX()方法的名字
// 获得和属性对应的getXXX()方法
Method getMethod = classType.getMethod(getMethodName, new Class[]{});
// 获得和属性对应的setXXX()方法
Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()});
Object value = getMethod.invoke(object, new Object[]{}); // 调用原对象的getXXX()方法
System.out.println(fieldName + ":" + value);
setMethod.invoke(objectCopy, new Object[]{value}); // 调用拷贝对象的setXXX()方法
}
return objectCopy;
}
public static void main(final String[] args) throws Exception {
User user= new User("Tom", 21);
user.setId(new Long(1));
User userCopy = (User) new ReflectTest().copy(customer);
System.out.println("Copy information:" + userCopy.getId() + " " + userCopy.getName() + " "
+ userCopy.getAge());
}
}
动态创建和访问数组元素的各种静态方法。
例程ArrayTest 类的main()方法创建了一个长度为15 的字符串数组,接着把索引位置为11 的元素设为“hello word”,然后再读取索引位置为10 的元素的值
public class ArrayTester1 {
public static void main(String args[]) throws Exception {
Class<?> classType = Class.forName("java.lang.String");
Object myArray = Array.newInstance(classType, 15); // 创建一个长度为15的字符串数组
Array.set(myArray, 10, "hello word"); // 把索引位置为10的元素设为"hello"
String s = (String) Array.get(array, 10); // 获得索引位置为10的元素的值
System.out.println(s);
}
}
main()方法创建了一个 10 x 20 x 30 的整型数组,并把索引位置为[4][10][20] 的元素的值为设50。
public class ArrayTest {
public static void main(String args[]) {
int[] dimArray = new int[]{10, 20, 30};
Object array = Array.newInstance(Integer.TYPE, dimArray);//创建一个具有指定的数值类型和三个维度的新数组。
final Object arrayObjecy = Array.get(array, 4);
final Class<?> myClass = arrayObjecy.getClass().getComponentType();
System.out.println(myClass);
arrayObj = Array.get(arrayObj, 10);
Array.setInt(arrayObj, 20, 50);
int arrayCast[][][] = (int[][][]) array;
System.out.println(arrayCast[3][5][10]);
}
}
利用反射机制修改对象
运行时变更field内容
与先前两个动作相比,“变更field内容”轻松多了,因为它不需要参数和自变量。首先调用Class的getField()并指定field名称。获得特定的Field object之后便可直接调用Field的get()和set()。
public class RefFiled {
public double x;
public Double y;
public static void main(String args[]) throws NoSuchFieldException, IllegalAccessException {
Class c = RefFiled.class;
Field xf = c.getField("x");
Field yf = c.getField("y");
RefFiled obj = new RefFiled();
System.out.println("变更前x=" + xf.get(obj));
//变更成员x值
xf.set(obj, 1.1);
System.out.println("变更后x=" + xf.get(obj));
System.out.println("变更前y=" + yf.get(obj));
//变更成员y值
yf.set(obj, 2.1);
System.out.println("变更后y=" + yf.get(obj));
}
}
- 上一篇: Java 反射详解(java反射的用法)
- 下一篇: Java反射(java下一页)
猜你喜欢
- 2024-09-20 Tomcat源码篇-简单到超乎想象的启动流程
- 2024-09-20 Java创建对象的6种方式(java什么是面向对象)
- 2024-09-20 java与数据库结合学习(java如何与数据库建立连接)
- 2024-09-20 「java设计模式」——代理模式(案例解析)
- 2024-09-20 反射魔镜:Java编程中的神秘力量,你真的会用了吗?
- 2024-09-20 Java反射详解(java反射的用法)
- 2024-09-20 JAVA基础(java基础题库及答案)
- 2024-09-20 java反射机制(Java反射机制主要提供了以下哪些功能)
- 2024-09-20 Java面试基础(java面试基础题及答案整理)
- 2024-09-20 同事跳槽到百度,总结的30道Java面试必问题目,限时领取
- 1514℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 562℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 507℃MySQL service启动脚本浅析(r12笔记第59天)
- 486℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 484℃启用MySQL查询缓存(mysql8.0查询缓存)
- 464℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 444℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 441℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)