-------------------android培训、 java培训、期待与您交流!-------------------
反射就是把Java类中各种成分如(成员变量,构造方法,方法等)
映射成相应的Java类。这样就可以通过成员变量、方法、构造方法
等来调用对象。那具体是怎样操作的呢?
Class对象
Java程序中许多对象在运行时都会有两种类型:编译时类型和运行时类型。
每个类被加载之后,系统就会为该类生成一个对应的Class对象,通过Class对象可以访问到Java虚拟机中的这个类。
Java程序中获得Class对象有如下三种方式:
(1)使用Class类的forName()静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名(必须添加完整的包名)。
(2)调用某个类的Class属性来获取该类对应的Class对象。比如:Person.class将返回Person类对应的Class对象。
(3)调用某个对象的getClass()方法,该方法是java.lang.Object类中的一个方法,所以所有Java对象都可以调用该方法,该方法返回该对象所属类对应的Class对象。
第一种和第二种方式都是直接根据类来获取该类的Class对象,但相比之下,第二种方式有如下两种优势:
(1)代码更安全,程序在编译阶段就可以知道需要访问的Class对象是否存在。
(2)程序性能更高,因为这种方式无须调用方法,所以性能更好。
所以大部分时候建议使用第二种来获取Class对象。当我们获取到Class对象后,程序就可以调用Class对象的方法来获取该类的真实信息。
从Class对象中获取信息
Class对应的类包含四个构造函数:
(1)Connstructor<T> getConstructor(Class<?>... parameter types):返回此Class对象所表示的类的指定的public构造函数。
(2)Connstructor<T>[] getConstructors():返回此Class对象所表示的类的所有public构造函数。
(3)Connstructor<T> getDeclaredConstructor(Class<?>... parameter types):返回此Class对象所表示的类的指定构造函数,与构造的访问级别无关。
(4)Connstructor<T>[] getDeclaredConstructosr():返回此Class对象所表示的类所有构造函数,与构造的访问级别无关。
访问Class对应的类所包含的方法:
(1)Metnod getMethod(String name,Class<?>... parameter types):返回此Class对象所表示的类的指定public方法。
(2)Method[] getMethods():返回此Class对象所表示的类的所有public方法。
(3)Method getDeclaredMethod(String name,Class<?>... parameter types):返回此Class对象所表示的类的指定方法,与方法的访问级别无关。
(4)Method[] getDeclaredMethods():返回此Class对象所表示的类的全部方法,与方法的访问级别无关。
访问Class对应的类所包含的属性(Field):
(1)Field getField(String name):返回该Class对象所表示的类的指定的public属性。
(2)Field[] getFields():返回该Class对象所表示的类的所有public属性。
(3)Field getDeclaredField(String name):返回该Class对象所表示的类的指定属性,与属性的访问级别无关。
(4)Field[] getDeclaredFields():返回该Class对象所表示的类的全部属性,与属性的访问级别无关。
访问Class对象的类上所包含的注解:
(1)<A extends Annotation> A getAnnotation(Class<A> annotationClass):试图获取该Class对象所表示类上指定类型的注解;如果该类型的注解不存在则返回null。
(2)Annotation[] getAnnotations():返回此元素上存在的所有注解。
(3)Annotation[] getDeclaredAnnotations():返回直接存在与此元素上的所有注解。
访问Class对象对应类包含的内部类
(1)Class<?>[] getDeclaredClasses():返回该Class对象所对应类里包含的全部内部类。
(2)Class<?> getDeclaringClass():返回该Class对象所对应类所在的外部类。
(3)Class<?>[] getInterfaces():返回该Class对象对应类所实现的全部接口。
(4)int getModifiers():返回此类或接口的所有修饰符。必须使用Modifier工具类,才能获得真实的修饰符。
(5)Package getPackaget():获取此类的包。
(6)String getName():以字符串形式返回此Class对象所表示的类的名称。
(7)String getSimpleName():以字符串形式返回此Class对象所表示的类的简称。
(8)Class<? super T> getSuperclass():返回该Class所表示的类的超类(父类,基类)对应的Class对象。
Class对象用于判断该类是否为接口,枚举,注解类:
(1)boolean isAnnotation():返回此Class对象是否表示一个注解类型。
(2)boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):判断此Class对象上是否使用了Annotation注解修饰。
(3)boolean isAnonymousClass():返回此Class对象是否是一个匿名类。
(4)boolean isArray():返回此Class对象是否表示一个数组类。
(5)boolean isEnum():返回此Class对象是否表示一个枚举类。
(6)boolean isInterface():返回此Class对象是否表示一个接口。
(7)boolean isInstance(Object obj):判断obj是否是此Class对象的实例,该方法可以完全代替instanceof操作符。
通过Class对象,如果我们需要确定一个方法,应该由方法名和形参列表来确定。比如:clazz.getMethod("method1",String.class);这样来确定一个叫method1(String str)的方法。确定构造函数则只需要参数列表就OK了,因为同一个类的所有构造函数的名字都是相同的。
使用反射生成并操作对象
创建对象
反射创建对象有两种方式:
(1)使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对应类有默认的构造函数,而执行newInstance()方法时,实际上是利用默认的构造函数来创建类的实例。
(2)先使用Class对象获取指定的Constructor对象,在调用Constructor对象的newInstance()方法来创建该Class对象对应的实例。通过这种方式可以选择使用某个类的指定构造函数来创建实例。
//第一个:一个类调用令一个类的main方法:
package cn.itcast.day1;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//定义一个类,该类的主函数用于打印字符串数组中的元素
class MainFun{
public static void main(String[] args){
for(String arg :args)
System.out.println(arg);
}
}
public class MainMethod {
public static void main(String[] args){
String str = args[0];
Method mainMethod = null;
try {
//获取方法类的实例对象
mainMethod = Class.forName(str).getMethod("main",String[].class);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
//调用类,并传入参数
//由于main方法是静态方法,因此不能传入实例对象,用类名调用,只传入null
//需要在运行时传入MainMethod类即:cn.itcast.day1.MainMethod
mainMethod.invoke(null, new Object[]{new String[]{"sdsf","err","wwf"}});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
sdsf
err
wwf
//第二个:从配置信息中动态地获取一个集合:
//定义一个类,覆盖equals和hashCode方法。
package cn.itcast.day1;
public class ReflectValue {
private int x;
private int y;
public ReflectValue(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectValue other = (ReflectValue) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
//配置信息,HashSet集合
//把ReflectValue类写入配置信息中的集合:
package cn.itcast.day1;
import java.io.*;
import java.util.*;
public class ReflectProperties {
public static void main(String[] args) {
ReflectValue rv1= new ReflectValue(2,4);
ReflectValue rv2= new ReflectValue(5,6);
ReflectValue rv3= new ReflectValue(7,8);
ReflectValue rv4= new ReflectValue(2,4);
InputStream ips = null;
try {
ips = new FileInputStream("config.properties");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Properties props = new Properties();
try {
props.load(ips);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
ips.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String className = props.getProperty("className");
Collection<ReflectValue> coll = null;
try {
coll = (Collection<ReflectValue>)Class.forName(className).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
coll.add(rv1);
coll.add(rv2);
coll.add(rv3);
coll.add(rv4);
System.out.println(coll.size());
}
}
运行结果:
3
改变配置信息:
运行结果:
4