0
点赞
收藏
分享

微信扫一扫

java之反射技术(一)


什么叫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

举报

相关推荐

0 条评论