代码即财富之我学Java反射(4)
2015-06-29 00:00
513 查看
摘要: Java反射知识是Java基础学习中非常重要的知识点之一,初期还体会不到反射机制的强大和神奇,到了后期Java Web和各种框架,包括Java对象反序列化等,这些都是以Java反射作为支撑,因此掌握Java反射是非常有必要的。
在学习Java反射知识之前,先看一个基本例子,这个例子展示了,Java对象最普通的构造和使用方式,也是Java基础学习最初期需要掌握的部分。
该程序成功打印出person的信息如下:
Per(name = zhangsan, age = 20)
这种方式相信任何一个学习过Java的都很容易看懂,也容易理解的正常方式,即先有类,然后实例化出对象;如果由一个对象得到关于该类的所有信息,这就是反射所在。修改main函数如下:
程序将打印出Person,说明成功地由对象信息反射得到类信息。实际上per.getClass()得到的是Class实例,可以这么说,Java中的所有对象都是Class类的实例,得到某个对象的Class类实例对象,便可以反射出该对象所属类的所有信息,例如所有的构造方法,方法,属性,修饰符,接口,异常等信息,这些都有反射专属类的支持,Constructor类,Method类,Field类,Modifer类,,Interface类,这些类都为与java.lang.reflect包里,因此使用的时候,别忘了导入包。而通常获取一个对象Class实例的方式有三种:per.getClass()是第一种,Person.class是第二种;Class.forName("Person")//实际中需要指定包名,这三种方式以第三种使用最多。重新修改main方法:
程序同样能打印出Person信息,现在尝试用c实例化Person对象:
程序成功输出:
Per(name = null, age = 0),
如果将Person类的无参构造函数去掉的话,这时就会出现异常:
Exception in thread "main" java.lang.InstantiationException: Person
at java.lang.Class.newInstance(Unknown Source)
at TestReflection.main(TestReflection.java:5)
显然程序是通过反射调用无参构造函数来实现Person类对象的实例化,所以一般我们都需要手动为一个类加上无参构造函数。现在利用Class实例对象输出Person类的所有构造函数:
输出如下:
public Person()
public Person(java.lang.String,int)
发现以上输出方法参数中没有修饰符,使用Modifier类调整输出如下:
经过调整之后,输出如下的合理信息:
public Person()
public Person(java.lang.String arg-0, int arg-1)
现在换一种实例化Person对象的方式,采用Class实例对象得到的构造函数来实例化Person对象,如下:
输出如下:
Per(name = null, age = 0)
Per(name = zhangsan, age = 20)
说明此种方式可以有效地针对构造函数的不同实例化对象,下面再介绍由Class实例对象反射得到Person类的其他方法以及调用的方式。获得Method实例,使用invoke方法实现调用。
成功输出如下:
Per(name = zhangsan, age = 20) say hello !!!
好了,其他的诸如接口,属性,这里就不再赘述了,总之,反射,就是利用Class类实例,获取其他类的结构信息。
在学习Java反射知识之前,先看一个基本例子,这个例子展示了,Java对象最普通的构造和使用方式,也是Java基础学习最初期需要掌握的部分。
public class TestReflection{ public static void main(String[] args) { Person per = new Person("zhangsan", 20); System.out.println(per); } } class Person{ private String name; private int age; public Person(){ } public Person(String name, int age){ this.name = name; this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String toString(){ return "Per(name = " + this.getName() + ", age = " + this.getAge() + ")"; } }
该程序成功打印出person的信息如下:
Per(name = zhangsan, age = 20)
这种方式相信任何一个学习过Java的都很容易看懂,也容易理解的正常方式,即先有类,然后实例化出对象;如果由一个对象得到关于该类的所有信息,这就是反射所在。修改main函数如下:
public class TestReflection{ public static void main(String[] args) { Person per = new Person(); System.out.println(per.getClass().getName()); } }
程序将打印出Person,说明成功地由对象信息反射得到类信息。实际上per.getClass()得到的是Class实例,可以这么说,Java中的所有对象都是Class类的实例,得到某个对象的Class类实例对象,便可以反射出该对象所属类的所有信息,例如所有的构造方法,方法,属性,修饰符,接口,异常等信息,这些都有反射专属类的支持,Constructor类,Method类,Field类,Modifer类,,Interface类,这些类都为与java.lang.reflect包里,因此使用的时候,别忘了导入包。而通常获取一个对象Class实例的方式有三种:per.getClass()是第一种,Person.class是第二种;Class.forName("Person")//实际中需要指定包名,这三种方式以第三种使用最多。重新修改main方法:
public class TestReflection{ public static void main(String[] args) throws Exception { Class c; c = Class.forName("Person"); System.out.println(c.getName()); } }
程序同样能打印出Person信息,现在尝试用c实例化Person对象:
public class TestReflection{ public static void main(String[] args) throws Exception { Class c = null; c = Class.forName("Person"); Person per = (Person)c.newInstance(); System.out.println(per); } }
程序成功输出:
Per(name = null, age = 0),
如果将Person类的无参构造函数去掉的话,这时就会出现异常:
Exception in thread "main" java.lang.InstantiationException: Person
at java.lang.Class.newInstance(Unknown Source)
at TestReflection.main(TestReflection.java:5)
显然程序是通过反射调用无参构造函数来实现Person类对象的实例化,所以一般我们都需要手动为一个类加上无参构造函数。现在利用Class实例对象输出Person类的所有构造函数:
import java.lang.reflect.*; public class TestReflection{ public static void main(String[] args) throws Exception { Class c = null; c = Class.forName("Person"); //Person per = (Person)c.newInstance(); Constructor cons[] = c.getConstructors(); for(int i=0;i<cons.length;i++){ System.out.println(cons[i]); } } }
输出如下:
public Person()
public Person(java.lang.String,int)
发现以上输出方法参数中没有修饰符,使用Modifier类调整输出如下:
public class TestReflection{ public static void main(String[] args) throws Exception { Class c = null; c = Class.forName("Person"); //Person per = (Person)c.newInstance(); Constructor cons[] = c.getConstructors(); for(int i=0;i<cons.length;i++){ Class params[] = cons[i].getParameterTypes(); int mod = cons[i].getModifiers(); System.out.print(Modifier.toString(mod) + " " + cons[i].getName() + "("); for(int j=0;j<params.length;j++){ System.out.print(params[j].getName() + " " + "arg-" + j); if(j < params.length-1){ System.out.print(", "); } } System.out.print(")"); System.out.println(); } } }
经过调整之后,输出如下的合理信息:
public Person()
public Person(java.lang.String arg-0, int arg-1)
现在换一种实例化Person对象的方式,采用Class实例对象得到的构造函数来实例化Person对象,如下:
Person per1 = (Person)cons[0].newInstance(); Person per2 = (Person)cons[1].newInstance("zhangsan", 20); System.out.println(per1); System.out.println(per2);
输出如下:
Per(name = null, age = 0)
Per(name = zhangsan, age = 20)
说明此种方式可以有效地针对构造函数的不同实例化对象,下面再介绍由Class实例对象反射得到Person类的其他方法以及调用的方式。获得Method实例,使用invoke方法实现调用。
Method m = c.getDeclaredMethod("say",String.class); m.invoke(per2,"hello !!!");
成功输出如下:
Per(name = zhangsan, age = 20) say hello !!!
好了,其他的诸如接口,属性,这里就不再赘述了,总之,反射,就是利用Class类实例,获取其他类的结构信息。
相关文章推荐
- Java总结篇系列:Java泛型
- [Java]学习笔记,随笔【五】
- Java基础实例
- javacore文件及heapdump文件分析
- java中的内部类总结
- 如何查看javacore和heapdump文件
- Spring AOP 之 HelloWorld(简单例子)
- .JavaCore/HeapDump文件及其分析方法
- 如何产生javacore和heapdump文件
- SpringMVC获取POST参数值时中文乱码
- java抓取糗事百科内容
- Android Eclipse开发环境配置
- 【Java.Core】Enum
- 18.Eclipse console 中文乱码解决 ?
- myeclipse 显示行数
- @suppressWarnings("unchecked") java 中是什么意思
- Eclipse Java注释模板设置详解
- spring装配集合
- java实现三种冒号算法的效率分析
- java中调整字体