什么叫JAVA反射技术(Reflection)?
谈到反射,我们首先了解下动态语言。
“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。
从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。
这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。
Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),
并生成其对象实体、或对其fields设值、或唤起其methods。
这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。
Reflection和introspection是常被并提的两个术语。
那在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?
答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。
JAVA反射提供了那些功能
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
modifiers(诸如public, static 等等)、 superclass(例如Object)、实现之 interfaces(例如Serializable),也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methods。
JAVA反射会用到哪些类
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
Class类:代表一个类。
Field 类:代表类的成员变量(成员变量也称为类的属性)。
Method类:代表类的方法。
Constructor 类:代表类的构造方法。
Array类:提供了动态创建数组,以及访问数组的元素的静态方法
JAVA反射我们怎么用
Class是Reflection起源,针对任何你想探勘的class,唯有先为它产生一个Class Object,接下来才能经由后者唤醒
为数十多个的Reflection APIs
1、如何获得获得一个类以及类的相关信息
/**
* 通过一个对象获得完整的包名和类名
* @param args
*/
public static void main(String[] args) {
new Demo();
System.out.println(demo.getClass().getName());
class.getName());
class.getSimpleName());
}
com.reflect.Demo
com.reflect.Demo
Demo
这个例子告诉我们既可以通过对象调用getClass方法获取类的信息,也可以直接类.class的形式。
2、我们所常见的Class.forName(" ");
public static void main(String[] args) {
null;
null;
null;
try
{
"com.reflect.Demo");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
new Demo().getClass();
class;
"类名称"+demo1.getName());
"类名称"+demo2.getName());
"类名称"+demo3.getName());
}
类名称com.reflect.Demo
类名称com.reflect.Demo
类名称com.reflect.Demo
记住这是第三种获得类的方式,给定完整的字符串名的类或接口,返回一个类对象。
3、通过一个类去实例化它的对象,不采取new的方式
public static void main(String[] args) {
null;
try
{
"com.reflect.Person");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
null;
try
{
person = (Person)demo.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
"jay");
11);
System.out.println(person);
}
[jay||11]
这里我们应该看到了newInstance方法,调用它就能返回一个类的实例对象,注意的是,定义的类必须提供一个无参的构造方法才能通过此方法去实例化。
如果没有提供呢,我们是不是就没法通过反射的方式实例化了呢,当然不会,请看下一个示例。
4、实例化一个无参构造方法的类
public static void main(String[] args) {
null;
try
{
"com.reflect.Person");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
try
{
new Class[]{String.class}).newInstance(new Object[]{"Rollen"});
System.out.println(person);
}
catch(Exception e)
{
e.printStackTrace();
}
}
打印结果:
[Rollen||0]
因为构造方法的参数个数及类型都是未知的,所以这里用到的是传数组的方式。
5、得到一个类的所有接口
public static void main(String[] args) {
null;
try
{
"com.reflect.People");
}
catch (Exception e)
{
e.printStackTrace();
}
//保存所有的接口
Class<?> intes[]=demo.getInterfaces();
for (int i = 0; i < intes.length; i++)
{
"实现的接口 "+intes[i].getName());
}
}
实现的接口 com.reflect.China
6、得到一个类的父类
public static void main(String[] args) {
null;
try
{
"com.reflect.People");
}
catch (Exception e)
{
e.printStackTrace();
}
//取得父类
Class<?> temp=demo.getSuperclass();
"继承的父类为: "+temp.getName());
}
打印结果:
继承的父类为: java.lang.Object
7、得到一个类的所有构造方法
public static void main(String[] args) {
null;
try
{
"com.reflect.People");
}
catch (Exception e)
{
e.printStackTrace();
}
Constructor<?>cons[]=demo.getConstructors();
for (int i = 0; i < cons.length; i++)
{
"构造方法: "+cons[i]);
}
}
构造方法: public com.reflect.People(java.lang.String)
构造方法: public com.reflect.People()
8、得到所有构造方法的修饰类型及参数类型
public static void main(String[] args){
null;
try
{
"com.reflect.People");
}
catch (Exception e)
{
e.printStackTrace();
}
Constructor<?> cons[] = demo.getConstructors();
for (int i = 0; i < cons.length; i++)
{
Class<?> p[] = cons[i].getParameterTypes();
"构造方法: ");
// 权限修饰符
int mo = cons[i].getModifiers();
" ");
//构造方法名字
String consName=cons[i].getName();
"(");
for (int j = 0; j < p.length; ++j)
{
//参数类型名字
String typeName=p[j].getName();
" arg" + i);
if (j < p.length - 1)
{
",");
}
}
"){}");
}
}
构造方法: public com.reflect.People(java.lang.String arg0){}
构造方法: public com.reflect.People(){}
9、得到属性的修饰符,及类型和名字
public static void main(String[] args) {
null;
try
{
"com.reflect.People");
}
catch (Exception e)
{
e.printStackTrace();
}
"===============本类属性========================");
// 取得本类的全部属性
Field[] field = demo.getDeclaredFields();
for (int i = 0; i < field.length; i++)
{
// 权限修饰符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = field[i].getType();
//属性字段名字
String name=field[i].getName();
" " + type.getName() + " "+ name + ";");
}
"===============实现的接口或者父类的属性========================");
// 取得实现的接口或者父类的属性
Field[] filed1 = demo.getFields();
for (int j = 0; j < filed1.length; j++)
{
// 权限修饰符
int mo = filed1[j].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = filed1[j].getType();
//属性字段名字
String name=filed1[j].getName();
" " + type.getName() + " "+ name + ";");
}
}
===============本类属性========================
private java.lang.String sex;
===============实现的接口或者父类的属性========================
public static final java.lang.String name;
public static final int age;
10、通过反射的方式调用某个对象的方法
public static void main(String[] args) {
null;
try
{
"com.reflect.People");
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
// 调用Person类中的sayChina方法
"sayChina");
method.invoke(demo.newInstance());
// 调用Person的sayHello方法
"sayHello", new Class[]{String.class, int.class});
new Object[]{"Rollen", 20} );
}
catch (Exception e)
{
e.printStackTrace();
}
}
hello ,china
Rollen 20
11、通过反射操作属性
正常情况下,我们是不可以直接操作其它某个对象的私有属性,但是反射可以做到
public static void main(String[] args) throws Exception {
null;
null;
"com.reflect.People");
obj = demo.newInstance();
"sex");
true);
"男");
System.out.println(field.get(obj));
}
男
12、通过反射取得并修改数组的信息
public static void main(String[] args) {
int[] temp={1,2,3,4,5};
Class<?>demo=temp.getClass().getComponentType();
"数组类型: "+demo.getName());
"数组长度 "+Array.getLength(temp));
"数组的第一个元素: "+Array.get(temp, 0));
0, 100);
"修改之后数组第一个元素为: "+Array.get(temp, 0));
}
数组类型: int
数组长度 5
数组的第一个元素: 1
修改之后数组第一个元素为: 100