java反射简单讲解
来源:互联网 发布:游戏编程图书 编辑:程序博客网 时间:2024/05/18 03:11
java反射讲解
1 Class类的概念介绍
1.1 概念
先看一个类:Person
public class Person{}Person p1 = new Person();
众所周知,p1是Person的实例对象,那么请大家想一个问题:
Person这个类是不是一个实例对象呢?答案:是!Person类是java.lang.Class类的实例对象。
注意: 我们写的任何一个类都是Class类的实例对象。
1.2 类的实例对象表示
Person的实例对象这样表示:
Person p1 = new Person();
Person这个类也是一个实例对象(Class类的实例对象),表示方法有3种如下:
1.Class c1 = Person.class;//这句话其实也在告诉我们,任何类都有一个隐含的静态成员变量class//第二种表达方式:已知Person的对象,可以通过该类的对象获取2.Person p1 = new Person(); Class c2 = p1.getClass();//第三种表达方式3. Class c3 = Class.forName("com.czh.study.Person");
总结:
1.在官网上说c1,c2,c3都是Person类的类类型(class type)2.万事万物皆对象3.类也是对象,类是Class类的实例对象,这个对象我们称为该类的类类型。
看到上面的3种方式大家可能会问:
既然任何一个类都是Class类的实例对象,那么为什么不用Class c4 = new Class();来表示呢?
我们来看看Class类的源码:
private Class() { // Prevent this class to be instantiated, instance should be created by JVM only}这是Class源码中的一段,看到没Class的构造函数是私有的。这个Class的实例只能被虚拟机创建。
接下来我们来看一下上面的这3种表示方式c1,c2,c3是否相等。代码如下:
public static void main(String[] args) { Class c1 = Person.class; Person p1 = new Person(); Class c2 = p1.getClass(); try { Class c3 = Class.forName("com.czh.study.Person"); System.out.println(c3 == c2); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(c1 == c2); //我们完全可以通过类的类类型来创建该类的对象,也就是说,我们可以通过c1,c2,c3来创建Person的实例对象。 try { Person p2 = (Person) c1.newInstance();//切记Person必须要有无参的构造方法。 p2.toString(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }}输出结果:truetrue
通过上面的代码,我们可能看出:
1.三种方式创建出来的c1,c2,c3完全是相等的。2.Person p2 = (Person) c1.newInstance();中newInstance()方法的使用必须要求Person类中有无参的构造函数。
2 了解静态加载类和动态加载类的区别
Class c3 = Class.forName("类的全称");不仅表示了类的类类型,还代表了动态加载类。
举个例子:
静态加载类:
Person p1 = new Person();这句话在编译的过程中,虚拟机会加载Person类,如果Person类不存在就直接报错,编译都不会通过。这种编译时刻加载类叫静态加载类
动态加载类:
public void loadClass(String className){ Class c = Class.forName(className); Person p = (Person)c.newInstance();}这种方式写,编译的时候不会出现任何错误。
不知道,这么写大家是否能明白。
3 通过反射获取方法信息
3.1 基本数据类型的类类型
Class c1 = int.class;//int 的类类型 Class c2 = String.class;//String类的类类型Class c3 = double.class;Class c4 = Double.class;// 注意和double.class不一样Class c5 = void.class;System.out.println(c2.getName());//包含包名的类名称System.out.println(c2.getSimpleName());//不包含包名的类名称结果:java.lang.StringString
3.2 我们来看一下Class类的基本API操作
我们来写一下打印类的信息,包括类的成员函数和变量,代码如下:
/** * @author 作者 YYD * @version 创建时间:2016年10月7日 上午6:37:23 * @function 未添加 */public class ClassUtil { public static void printClassMessage(Object obj){ Class c = obj.getClass();//这里传递的是哪个子类的对象,c就是该子类的类类型 System.out.println("类的名称是:"+c.getName()); /** * Method类,方法对象 * 一个成员方法,就是一个Method对象 * getMethods()方法获取是是所有的public的函数,包括父类继承的 * getDeclaredMethods()获取所有该类自己声明的方法,不问访问权限 */ Method[] methods = c.getMethods(); for (Method method : methods) { //得到返回值类型的类类型,如果返回值是int型,那么returnType为int.class Class returnType = method.getReturnType(); System.out.print(returnType.getName()+" "); System.out.print(method.getName()+"(");//获取方法的名称 /** * 获取参数类型 -->得到的是参数列表的类型的类类型。 * 如果参数是int类型,那么得到的是int.class,因为一个方法的参数可以是多个,所以得到的是一个数组 */ Class[]paramsTypes = method.getParameterTypes(); for (Class class1 : paramsTypes) { System.out.print(class1.getName()+","); } System.out.println(")"); }// Field[] fields = c.getFields(); }}//调用使用printClassMessage方法public static void main(String[] args) { String str = "hello world"; ClassUtil.printClassMessage(str);}
结果如下:
int numberOfLeadingZeros(int,)int numberOfTrailingZeros(int,)int bitCount(int,)boolean equals(java.lang.Object,)java.lang.String toString(int,int,)java.lang.String toString()java.lang.String toString(int,)int hashCode(int,)int hashCode()int min(int,int,)int max(int,int,)int reverseBytes(int,)int compareTo(java.lang.Integer,)...太多就不一一显示了,大家可以试一下
4 通过反射获取成员变量和构造函数信息
注意:成员变量也是对象,在java.lang.reflect.Field中Field类封装了关于成员变量的操作
4.1 获取成员变量的信息
代码如下:
/** * getFields() 获取所有public的成员变量的信息 * getDeclaredFields()获取自己声明的成员变量信息,无论访问权限 * @param obj */public static void printClassFieldMsg(Object obj){ Class c = obj.getClass(); Field[] fields = c.getDeclaredFields(); for (Field field : fields) { //field.getType()获取成员变量类型的类类型,如果类型是int型,那么得到的是int.class System.out.println(field.getType().getName()+" "+field.getName()); }}Integer inte = new Integer(1);ClassUtil.printClassFieldMsg(inte);结果如下: int MIN_VALUE int MAX_VALUE java.lang.Class TYPE [C digits [C DigitTens [C DigitOnes [I sizeTable int value int SIZE int BYTES long serialVersionUID
4.2 获取构造方法的信息
代码如下:
/** * 打印构造函数的信息 * @param obj */public static void printConstructmsg(Object obj){ Class c = obj.getClass(); /** * 构造函数也是对象,java.long.Constructor封装了构造函数的信息 */ Constructor[] cons = c.getDeclaredConstructors(); for (Constructor constructor : cons) { System.out.print(constructor.getName()+"("); Parameter[] p = constructor.getParameters(); for (Parameter parameter : p) { System.out.print(parameter.getType().getSimpleName()+" "+parameter.getName()+","); } System.out.println(")"); }}//调用方法ClassUtil.printConstructmsg("hello");结果如下: java.lang.String(byte[] arg0,int arg1,int arg2,) java.lang.String(byte[] arg0,Charset arg1,) java.lang.String(byte[] arg0,String arg1,) java.lang.String(byte[] arg0,int arg1,int arg2,Charset arg3,) java.lang.String(byte[] arg0,int arg1,int arg2,String arg3,) java.lang.String(char[] arg0,boolean arg1,) java.lang.String(StringBuilder arg0,) java.lang.String(StringBuffer arg0,) java.lang.String(byte[] arg0,) java.lang.String(int[] arg0,int arg1,int arg2,) java.lang.String() java.lang.String(char[] arg0,) java.lang.String(String arg0,) java.lang.String(char[] arg0,int arg1,int arg2,) java.lang.String(byte[] arg0,int arg1,) java.lang.String(byte[] arg0,int arg1,int arg2,int arg3,)
5 方法反射的基本操作
方法反射的操作如下:
method.invoke(对象,参数列表)
举例代码如下:
/** * @author 作者 YYD * @version 创建时间:2016年10月7日 上午6:38:08 * @function 未添加 */public class Client { public static void main(String[] args) { /** *首先获取类的类类型 *第二获取方法getMethod()和*getDelcaredMethod() */ try { Person person = new Person(); Class p = person.getClass(); Method m = p.getMethod("add",int.class,int.class); //m.setAccessible(true);//注意,如果add方法是private的,如果要调用,就需要加上这样一句话 //方法的反射操作是用m对象来进行方法调用 m.invoke(person, 1,1); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }} class Person { public void add(int a,int b){ System.out.println(a + b); }}
6 属性反射的基本操作
现在我们来讲一下,如何通过反射访问私有变量,并且赋值。代码如下:
//访问私有变量 public static void main(String[] args) { try { Class c = Class.forName("com.czh.study.Person"); Field f = c.getDeclaredField("age"); f.setAccessible(true);// 调用private属性的关键一句话 Person person = (Person) c.newInstance(); f.set(person, 10);//给属性赋值和获取属性的值必须是相同的对象 System.out.println(f.get(person));//给属性赋值和获取属性的值必须是相同的对象 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }}
7 总结
好了,就讲到这里吧,希望对大家有所帮助。
0 0
- java反射简单讲解
- 反射简单讲解实例
- java反射机制讲解
- java 反射详细讲解
- Java反射讲解
- java反射讲解实例
- java反射讲解
- java中反射讲解
- 实例讲解java的反射
- JAVA 反射详细讲解 实例
- JAVA反射机制知识讲解
- java的反射类讲解
- 详细讲解Java反射机制
- Java反射机制基础讲解
- Java反射讲解(一)
- 网络编程和反射--简单讲解
- Java简单注释讲解
- Java集合--简单讲解
- 洛谷 P1328 生活大爆炸版石头剪刀布
- Linux学习笔记7 cut,sort,uniq,wc,tr
- 二进制平行算法
- 三道java高级工程师面试题
- Vue 爬坑之路(一)—— 使用 vue-cli 搭建项目
- java反射简单讲解
- 自定义Behavior之ToolBar上滑TabLayout颜色渐变
- 最长上升连续子序列
- 时间序列分析笔记(待整理)
- js向div中追加html代码
- 数据结构与算法分析笔记与总结(java实现)--二叉树4:二叉树的序列化和反序列化练习题
- MongoDB笔记
- ContentProvider(内容提供者)和ContentResolve(内容访问者)
- nginx 参数优化