您的位置:首页 > 编程语言 > Java开发

java学习笔记之反射

2015-10-01 17:34 711 查看

1、获得Class对象(反射的源头)

三种方式:
a、类.class
b、对象.getClass()
C、Class.forName(String className) (className为完整类名,包括包名)


2、获取类名、构造函数、属性、方法

a、获取类名:
getName()  获取完整类名,包含包名
getSimpleName() 获取类名,不包含包名
b、获取构造函数 Constructor
getConstuctors()  获取public权限构造函数,无法获取其它权限构造函数
getDeclaredConstructors() 获取所有权限构造函数
getConstructor(Class... parameterTypes) 获取指定public权限构造函数
getDeclaredConstructor(Class... parameterTypes) 获取指定任意权限构造函数
c、获取属性 Field
getFields()  获取public权限属性,无法获取其它权限构造属性
getDeclaredFields() 获取所有权限属性
getField(String name) 获取指定public权限属性
getDeclaredField(String name) 获取指定任意权限属性
d、获取方法 Method
getMethods()  获取public权限方法,无法获取其它权限方法
getDeclaredMethods() 获取所有权限方法
getMethod(Class... parameterTypes) 获取指定public权限方法
getDeclaredMethod(Class... parameterTypes) 获取指定任意权限方法


代码示例:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
* 通过反射,获取类名、构造函数、属性、方法
* @author ly1
*
*/
public class GetInfo{
public static void main(String[] args) throws Exception  {
//获取Class对象=====================================================================================
Student student = new Student();
Class clazz = Student.class;
clazz = student.getClass();
clazz = Class.forName("Reflect.Student");

//获取类名===========================================================================================
String name = clazz.getName();  //完整类名,包括包名
System.out.println("获取类名:"+name);

name = clazz.getSimpleName();   //类名,不含包名
System.out.println("获取完整类名:"+name);

//获取构造函数=======================================================================================
//获取public权限构造函数,无法获取其它权限构造函数
Constructor[] constructors = clazz.getConstructors();
System.out.println("获取public权限构造函数,无法获取其它权限构造函数:");
System.out.println("\t"+constructors.length);
for (Constructor constructor : constructors) {
System.out.println("\t"+constructor);
}

//获取所有权限构造函数,包括public、default、protected、private
constructors = clazz.getDeclaredConstructors();
System.out.println("获取所有权限构造函数,包括public、default、protected、private:");
System.out.println("\t"+constructors.length);
for (Constructor constructor : constructors) {
System.out.println("\t"+constructor);
}

//根据构造函数的参数类型获取指定构造函数
Constructor constructor = clazz.getConstructor(String.class,char.class,int.class,double.class);
System.out.println("根据构造函数的参数类型获取指定构造函数:");
System.out.println("\t"+constructor);

//获取属性==========================================================================================
//获取public权限属性,无法获取其它权限属性
Field[] fields = clazz.getFields();
System.out.println("获取public权限属性,无法获取其它权限属性 :");
System.out.println("\t"+fields.length);
for(Field f : fields){
System.out.println("\t"+f);
}

//获取所有权限的属性,包括public、default、protected、private
fields = clazz.getDeclaredFields();
System.out.println("获取所有权限的属性,包括public、default、protected、private :");
System.out.println("\t"+fields.length);
for(Field f : fields){
System.out.println("\t"+f);
}

//根据属性名获取指定属性
Field field = clazz.getDeclaredField("name");
System.out.println("根据属性名获取指定属性:");
System.out.println("\t"+field);

//获取方法===========================================================================================
//获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法
Method[] methods = clazz.getMethods();
System.out.println("获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法:");
System.out.println("\t"+methods.length);
for (Method method : methods) {
System.out.println("\t"+method);
}

//获取所有权限的方法,包括public、default、protected、private
methods = clazz.getDeclaredMethods();
System.out.println("获取所有权限的方法,包括public、default、protected、private:");
System.out.println("\t"+methods.length);
for (Method method : methods) {
System.out.println("\t"+method);
}

//根据方法名和参数类型,获取指定方法
Method method = clazz.getDeclaredMethod("setName", String.class);
System.out.println("根据方法名和参数类型,获取指定方法:");
System.out.println("\t"+method);
}
}

结果:
获取类名:Reflect.Student
获取完整类名:Student
获取public权限构造函数,无法获取其它权限构造函数:
2
public Reflect.Student()
public Reflect.Student(java.lang.String,char,int,double)
获取所有权限构造函数,包括public、default、protected、private:
2
public Reflect.Student()
public Reflect.Student(java.lang.String,char,int,double)
根据构造函数的参数类型获取指定构造函数:
public Reflect.Student(java.lang.String,char,int,double)
获取public权限属性,无法获取其它权限属性 :
1
public double Reflect.Student.height
获取所有权限的属性,包括public、default、protected、private :
4
private java.lang.String Reflect.Student.name
char Reflect.Student.sex
protected int Reflect.Student.age
public double Reflect.Student.height
根据属性名获取指定属性:
private java.lang.String Reflect.Student.name
获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法:
15
public java.lang.String Reflect.Student.getName()
public void Reflect.Student.setName(java.lang.String)
public int Reflect.Student.getAge()
public char Reflect.Student.getSex()
public void Reflect.Student.setHeight(double)
public double Reflect.Student.getHeight()
public boolean java.lang.Object.equals(java.lang.Object)
public final native java.lang.Class java.lang.Object.getClass()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public native int java.lang.Object.hashCode()
public java.lang.String java.lang.Object.toString()
public final native void java.lang.Object.notifyAll()
public final native void java.lang.Object.notify()
获取所有权限的方法,包括public、default、protected、private:
8
public java.lang.String Reflect.Student.getName()
public void Reflect.Student.setName(java.lang.String)
public int Reflect.Student.getAge()
public char Reflect.Student.getSex()
public void Reflect.Student.setHeight(double)
protected void Reflect.Student.setAge(int)
private void Reflect.Student.setSex(char)
public double Reflect.Student.getHeight()
根据方法名和参数类型,获取指定方法:
public void Reflect.Student.setName(java.lang.String)


3、动态操作构造函数、属性、方法

1)操作构造函数
a、利用Class对象调用空构造:
Class对象.newInstance()  该方法得确保该类有空构造(显示或隐式)
b、利用Constructor.newInstance():
Constructor对象.newInstance()  该方法可以调用任意构造方法,如果不可访问,须设置setAccessible(true)
2)操作属性
a、操作可访问属性
Field对象.set(Object obj,Object value)
b、操作不可访问属性
须先设置 Field对象setAccessible(true)
然后 Field对象.set(Object obj,Object value)
3)操作方法
a、操作可访问方法
Method对象.invoke(Object obj,Object... args)
b、操作不可访问方法
须先设置 Method对象setAccessible(true)
然后 Method对象.invoke(Object obj,Object... args)


代码示例:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* 通过反射操作类的构造函数、属性、方法
* @author ly1
*
*/
public class OperateInfo {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException,
SecurityException, IllegalArgumentException, InvocationTargetException,
NoSuchFieldException {
//获取Class对象
Class clazz = Student.class;

//利用反射API创建对象====================================================================
//直接调用Class对象的newInstance()方法,必须保证Student对象有空构造(显示或隐式)
Student student = (Student) clazz.newInstance();
System.out.println(student);

//获取到构造函数创建对象
Constructor<Student> constructor = clazz.getConstructor(String.class,char.class,int.class,double.class);
student = constructor.newInstance("张三",'男',20,178.51);
System.out.println(student);

//利用反射API操作属性
//操作可访问属性
Field field = clazz.getField("height");
field.set(student, 188.00);
System.out.println(field.get(student));
//操作不可访问属性,设置setAccessible(true)
field = clazz.getDeclaredField("name");
field.setAccessible(true);         //使反射对象该属性在使用时不对其进行安全检查
field.set(student, "李四");
System.out.println(field.get(student));

//利用反射API操作方法
//操作可访问方法
Method method = clazz.getMethod("setName", String.class);
method.invoke(student, "王麻子");
System.out.println(student.getName());
//操作不可访问方法,设置setAccessible(true)
method = clazz.getDeclaredMethod("setSex", char.class);
method.setAccessible(true);          //使反射对象该方法在使用时不对其进行安全检查
method.invoke(student, '女');
System.out.println(student.getSex());

}
}

结果:Reflect.Student@39e2ee3f
Reflect.Student@24348ab2
188.0
李四
王麻子
女


4、反射机制性能

使用反射机制性能降低,如果禁止安全检查,性能会有所上升,但还是比不使用反射性能低。


代码测试:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* 测试反射机制的性能
* @author ly1
*
*/
public class ReflectPerformance {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName("Reflect.Student");
Student stu = (Student) clazz.newInstance();

test01(stu);
test02(clazz,stu);
test03(clazz,stu);
}

public static void test01(Student stu){
long startTime = System.currentTimeMillis();
for(int i = 0;i < 1000000000L;i++){
stu.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("不使用反射机制运行时间为:"+(endTime - startTime) +"ms");
}

public static void test02(Class clazz,Student stu){
try {
Method method = clazz.getMethod("getName");
long startTime = System.currentTimeMillis();
for(int i = 0;i < 1000000000L;i++){
method.invoke(stu, null);
}
long endTime = System.currentTimeMillis();
System.out.println("使用反射机制,进行安全检查运行时间为:"+(endTime - startTime) +"ms");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void test03(Class clazz, Student stu){
try {
Method method = clazz.getMethod("getName");
method.setAccessible(true);
long startTime = System.currentTimeMillis();
for(int i = 0;i < 1000000000L;i++){
method.invoke(stu, null);
}
long endTime = System.currentTimeMillis();
System.out.println("使用反射机制,不进行安全检查运行时间为:"+(endTime - startTime) +"ms");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

结果:不使用反射机制运行时间为:332ms
使用反射机制,进行安全检查运行时间为:1769ms
使用反射机制,不进行安全检查运行时间为:1201ms


5、反射操作泛型

1)获取泛型参数
Method对象.getGenericParameterTypes():Type[]
获取具体类型:
ParameterizedType对象.getActualTypeArguments():Type[]
2)获取泛型返回值
Method对象.getGenericReturnType():Type
获取具体类型:
ParameterizedType对象.getActualTypeArguments():Type[]


代码示例:

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
* 反射操作泛型
* @author ly1
*
*/
public class ReflectGeneric {
public static List<Integer> test(Map<String,Student> map,List<Double> list){
return null;
}

public static void main(String[] args) {
try{
Class clazz = ReflectGeneric.class;
Method method = clazz.getMethod("test", Map.class,List.class);

//获取泛型参数的类型
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
System.out.println("泛型参数:"+type);
if(type instanceof ParameterizedType){
Type[] aTypes = ((ParameterizedType)type).getActualTypeArguments();
for (Type type2 : aTypes) {
System.out.println("\t"+type2);
}
}
}

//获取泛型返回值的类型
Type type = method.getGenericReturnType();
System.out.println("泛型返回值:"+type);
if(type instanceof ParameterizedType){
Type[] aTypes = ((ParameterizedType)type).getActualTypeArguments();
for (Type type2 : aTypes) {
System.out.println("\t"+type2);
}
}
}
catch(Exception e){

}
}
}

结果:
泛型参数:java.util.Map<java.lang.String, Reflect.Student>
class java.lang.String
class Reflect.Student
泛型参数:java.util.List<java.lang.Double>
class java.lang.Double
泛型返回值:java.util.List<java.lang.Integer>
class java.lang.Integer
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: