反射

  • 反射是什么?
  • Class类
  • 利用反射还原类
  • 通用toString()
  • 通用数组拷贝

反射是什么?

能够分析类能力的程序称为反射,利用反射能够编写动态操作Java代码的程序

Class类

每个对象都有一个运行时的类型标识,称为Class,用于跟踪对象所属的类

class Person {}

可通过Object中getClass方法、Class.forName()或T.class获取一个类对应的Class对象,每个java类型都有匹配的类对象

Person person = new Person();
Class personClass = person.getClass();try {Class StringClass = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {e.printStackTrace();
}Class voidClass = Void.class;

其保存了描述类的各种属性,如类名(会附带包名)

String className = personClass.getName()

可通过类对象创建新的实例,newInstance()会调用默认无参的构造方法,无则报错

try {Person person2 = (Person) personClass.newInstance();
} catch (IllegalAccessException | InstantiationException e) {e.printStackTrace();
}

可通过==运算符判断两个类对象是否相等,多用于equals中

if (person.getClass() == person.getClass()) {}

利用反射还原类

反射中有Field、Constructor和Method描述类的域、方法和构造方法

  • 都有getName返回名称,Modifier.toString(getMidifiers())获取修饰符
  • Field的getType()获取域的数据类型
  • Constructor和Method的getParameterTypes()获取参数类型
  • getDeclaredFields()、getDeclaredConstructors()、getDeclaredMethods()返回全部域、方法和构造方法(包括private)
  • Method的getReturnType()获取返回值类型
class Reflection {public static void reflect(String name) {try {Class thisClass = Class.forName(name);Class supClass = thisClass.getSuperclass();String modifies = Modifier.toString(thisClass.getModifiers());if (modifies.length() > 0) {System.out.print(modifies + " ");}System.out.print("class " + name);if (supClass != null && supClass != Object.class) {System.out.print(" extend " + supClass.getName());}System.out.print(" {\n");printField(thisClass);System.out.println();printConstructors(thisClass);System.out.println();printMethods(thisClass);System.out.println("}");} catch (ClassNotFoundException e) {e.printStackTrace();}System.exit(0);}public static void printField(Class thisClass) {Field[] fields = thisClass.getDeclaredFields();for (Field f : fields) {Class type = f.getType();String name = f.getName();System.out.print("  ");String modifiers = Modifier.toString(f.getModifiers());if (modifiers.length() > 0) {System.out.print(modifiers + " ");}System.out.println(type.getName() + " " + name + ";");}}public static void printConstructors(Class thisClass) {Constructor[] constructors = thisClass.getDeclaredConstructors();for (Constructor c : constructors) {String name = c.getName();System.out.print("  ");String modifiers = Modifier.toString(c.getModifiers());if (modifiers.length() > 0) {System.out.print(modifiers + " ");}System.out.print(name + "(");Class[] paraTypes = c.getParameterTypes();for (int i = 0; i < paraTypes.length; i++) {if (i > 0) {System.out.println(", ");}System.out.print(paraTypes[i].getName());}System.out.println(");");}}public static void printMethods(Class thisClass) {Method[] methods = thisClass.getDeclaredMethods();for (Method m : methods) {Class returnType = m.getReturnType();String name = m.getName();System.out.print("  ");String modifiers = Modifier.toString(m.getModifiers());if (modifiers.length() > 0) {System.out.print(modifiers + " ");}System.out.print(returnType.getName() + " " + name + "(");Class[] paraTypes = m.getParameterTypes();for (int i = 0; i < paraTypes.length; i++) {if (i > 0) {System.out.print(", ");}System.out.print(paraTypes[i].getName());}System.out.println(");");}}
}

调用时输入类名

Reflection.reflect(Double.class.getName());

通用toString()

  • getComponentType()获取数组类型
  • setAccessible(AccessibleObject[] array,boolean flag)设置对象数组的可访问标志,true为可访问私有部分
  • Filed的get(Object obj)返回对应域在obj中的值
  • Array的get(obj, i)获取obj数组在i中对象
class ObjectAnalyzer {private ArrayList<Object> visited = new ArrayList<>();public String toString(Object obj) {if (obj == null) {return "null";}if (visited.contains(obj)) {return "...";}visited.add(obj);Class thisClass = obj.getClass();if (thisClass == String.class) {return (String) obj;}if (thisClass.isArray()) {String r = thisClass.getComponentType() + "[]{";for (int i = 0; i < Array.getLength(obj); i++) {if (i > 0) {r += ",";}Object val = Array.get(obj, i);if (thisClass.getComponentType().isPrimitive()) {r += val;} else {r += toString(val);}return r + "}";}}String r = thisClass.getName();do {r += "[";Field[] fields = thisClass.getDeclaredFields();AccessibleObject.setAccessible(fields, true);for (Field f : fields) {if (!Modifier.isStatic(f.getModifiers())) {if (r.endsWith("[")) {r += ",";}r += f.getName() + "=";try {Class t = f.getType();Object val = f.get(obj);if (t.isPrimitive()){r+=val;}else {r+=toString(val);}} catch (Exception e) {e.printStackTrace();}}}r += "]";thisClass = thisClass.getSuperclass();}while (thisClass != null);return r;}
}

调用

ArrayList<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < 5; i++) {arrayList.add(i * i);
}
System.out.println(new ObjectAnalyzer().toString(arrayList));

通用数组拷贝

现有badCopy利用Object[]进行拷贝

class CopyUtil {public static Object[] badCopy(Object[] a, int newLength) {Object[] newArray = new Object[newLength];System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));return newArray;}
}

以下代码无法执行,在返回时一个Object[]无法转换成Person[],且无法针对基本数据类型转换,因为int[] 无法转换成Object[]

Person[] people = new Person[10];
people = (Person[]) CopyUtil.badCopy(people, 2 % people.length);
//int[] a = new int[10];
//a = CopyUtil.badCopy(a, 2 % a.length);

修改为goodCopy,内部使用反射Array.newInstance创建Object实例,所有对象都可通过Object进行转换

public static Object goodCopy(Object a, int newLength) {Class thisClass = a.getClass();if (!thisClass.isArray()) {return null;}Class componentType = thisClass.getComponentType();int length = Array.getLength(a);Object newArray = Array.newInstance(componentType, newLength);System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));return newArray;
}

Java基础——反射.相关推荐

  1. [Java基础] 反射机制汇总

    引言 初学Java反射机制的时候,只是感觉很神奇,但是不知道学了该怎么用,所以过了一段时间就忘得差不多了:最近接触到了框架,在学习中遇到了反射,深深体会到了反射机制的神奇,回来复习了一下反射机制,写一 ...

  2. 16、Java 基础-反射

    Java 反射 1.反射 反射是指程序可以访问.检测.修改它本身的状态或行为的一种能力. 2.Java的反射机制 java的反射机制是指在程序的运行状态中,给定任意一个类,都可以获取到这个累的属性和方 ...

  3. java基础反射知识总结_非常好的Java基础反射总结

    前言疯狂复习基础ing- 最近复习的Jv基础反射做了应该总结,果然反射不只有那么一点点东西,多的是精髓! 最重要的是最后推荐的那两篇文章,写的非常非常好!!反射 1.反射的原理Jv反射机制就是在运行状 ...

  4. Java基础-反射机制

    目录 1.反射机制概述 2.获取class的三种方式 2.1.Class.forName()方式 2.2.obj.getClass()方式 2.3..class方式 3.通过反射实例化对象 4.通过读 ...

  5. Java基础—反射—简单介绍

    一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见的 JavaScript 就是动态语言,除此之外 Ruby,Python 等也属于 ...

  6. [Java基础]反射获取成员方法并使用

    代码如下: package ClassObjectPack01;import ClassObjectPack.Student;import java.lang.reflect.Constructor; ...

  7. [Java基础]反射获取成员变量并使用

    代码如下: package ClassObjectPack;public class Student {private String name;int age;public String addres ...

  8. [Java基础]反射获取构造方法并使用练习

    Student类代码如下: package ClassObjectPack;public class Student {private String name;int age;public Strin ...

  9. Java基础--反射

    1.概念 什么是反射? (1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法. 本质是JVM得到class对象之后,再通过class对象进行反编译,从而 ...

最新文章

  1. 关于“ModuleNotFoundError: No module named ‘flask._compat‘”的解决
  2. linux下添加用户并赋予root权限
  3. docker容器间数据共享
  4. 我的Linux系统入坑之路!!!!
  5. vs2003打开项目错误
  6. sleuth微服务整合Zipkin
  7. 理解DDoS防护本质:基于资源较量和规则过滤的智能化系统
  8. 持续集成与自动化部署 - jenkins sonar代码质量管理平台 部署和基础使用(五)...
  9. HTML 基础语言
  10. roboware使用过程中出出现找不到功能包的解决办法
  11. 润乾集算报表实现多数据集关联的示例
  12. 【Oracle】搭建DataGuard
  13. jquery validate表单校验
  14. QQ安装目录下各文件用途不完全揭密(转)
  15. WebCralwer_java
  16. 产品心理学:福格行为模型详解与应用
  17. c#绝对值函数图像_C# 中如何取绝对值函数
  18. 10个免费的在线Markdown编辑器
  19. 统计学习方法总结、应用对比
  20. 外贸公司邮箱大全,选择哪个企业邮箱最好用?

热门文章

  1. GTJ2018如何导出全部工程量_分享2个GTJ2018最新版小技巧,你get了吗?
  2. python实现屏幕截图_电脑截屏操作有哪些,用Python进行屏幕截图,只用两行代码搞定...
  3. 指南:在 linux 下的 Oracle Database 11g 中安装 Oracle Enterprise Manager 10g Grid Control 第 5 版
  4. 上海东锦江希尔顿逸林酒店圆满落幕
  5. 【论文笔记】Towards Making Systems Forget with Machine Unlearning
  6. 电脑显示服务器不稳定怎么办,网速不稳定怎么办? 网速不稳定的原因与解决办法-电脑教程...
  7. 栅格影像WGS84转CGCS2000坐标系
  8. 几款好用的鼠标手势工具录屏
  9. Pr软件怎么导入预设?premiere无法导入预设?pr转场预设如何导入
  10. 如何评估无监督学习算法