黑马程序员——Java基础---反射总结
2015-07-05 17:58
471 查看
定义:
JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。
用于描述字节码的类就是Class类,创建对象,可以提取字节码文件中的内容,如字段、构造函数、一般函数。该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的。想要对一个类文件进行解剖,只要获取到该类的字节码文件对象即可。
1、可以通过
Class.forName(String className)使用装载当前类的类装载器来装载指定类。因为class.forName(String className)方法内部调用了Class.forName(className,true, this.getClass().getClassLoader())方法,如你所见,第三个参数就是指定类装载器,显而易见,它指定的是装载当前类的类装载器的实例,也就是this.getClass().getClassLoader();
classLoader.loadClass(StringclassName , boolean resolve);需要手动指定类装载器的实例。所以这两种类装载方式的区别之一是一个默认使用装载当前类实例的类装载器来装载指定类,而另一个则需要手动指定一个类装载器的实例。
2、如何产生该类的对象呢
3、获取字段值
实际开发中一些常用,但又容易写错,遗忘的
// 使用反射技术得到T的真实类型
// 获取当前new的对象的 泛型的父类 类型
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
// 获取第一个类型参数的真实类型
this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
使用反射获取Method,可以使用getMethod(String name, Class<?>...
parameterTypes)来获取,第一个参数是方法的名字,第二个是参数类表
但是这个方法没参数呢?比如:
一个简单的Person 类
public class Person {
public String name="zhangsan";
public int age;
public String str1 = "ball";
public String str2 = "baskecballl";
public Person(){
this.str1=str1;
this.str2=str2;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + ", str1=" + str1
+ ", str2=" + str2 + "]";
}
}
复制代码
如果是调用set方法很简单,根据规则
Method methodName = p.getClass().getMethod("setName",String.class);
System.out.println(methodName.invoke(p, "张三"));
复制代码
这样就获取了,但是如果是get 方法呢,参数列表是空,怎么做的?
这样可以
Method methodName = p.getClass().getMethod("getName",null);
System.out.println(methodName.invoke(p,null));
复制代码
这样更好
Method methodName = p.getClass().getMethod("getName");
System.out.println(methodName.invoke(p));
复制代码
JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。
用于描述字节码的类就是Class类,创建对象,可以提取字节码文件中的内容,如字段、构造函数、一般函数。该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的。想要对一个类文件进行解剖,只要获取到该类的字节码文件对象即可。
1、可以通过
Class.forName(
"Reflect.Demo"
)得到类对应的Class 对象。
Class.forName(String className)使用装载当前类的类装载器来装载指定类。因为class.forName(String className)方法内部调用了Class.forName(className,true, this.getClass().getClassLoader())方法,如你所见,第三个参数就是指定类装载器,显而易见,它指定的是装载当前类的类装载器的实例,也就是this.getClass().getClassLoader();
classLoader.loadClass(StringclassName , boolean resolve);需要手动指定类装载器的实例。所以这两种类装载方式的区别之一是一个默认使用装载当前类实例的类装载器来装载指定类,而另一个则需要手动指定一个类装载器的实例。
2、如何产生该类的对象呢
Class clazz = Class.forName(name); //调用Person的空参构造函数 Object obj = clazz.newInstance();
Class clazz = Class.forName(name); //获取到了指定的构造函数对象 Constructor constructor = clazz.getConstructor(int.class,String.class); //通过该构造器对象的newInstance方法进行对象的初始化。 Object obj = constructor.newInstance(38,"小明");
3、获取字段值
/* * 获取字节码文件中的字段。 */ public static void getFieldDemo() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); //getField只能获取所有可访问公共字段,private获取不到。 //Field field = claszz.getField("age"); //getDeclaredField可以获取到公共字段,也可以获取到私有字段。 Field field = clazz.getDeclaredField("age"); //对私有字段的访问取消权限检查,暴力访问。 field.setAccessible(true); Object obj = clazz.newInstance(); //为对象的属性赋值 field.set(obj,89); //获取某对象的某属性值 Object o = field.get(obj); System.out.println(field); } }4、获取类的方法
Method[] methods = clazz.getMethods();//获取的都是公有的方法 methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包括私有。
实际开发中一些常用,但又容易写错,遗忘的
// 使用反射技术得到T的真实类型
// 获取当前new的对象的 泛型的父类 类型
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
// 获取第一个类型参数的真实类型
this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
使用反射获取Method,可以使用getMethod(String name, Class<?>...
parameterTypes)来获取,第一个参数是方法的名字,第二个是参数类表
但是这个方法没参数呢?比如:
一个简单的Person 类
public class Person {
public String name="zhangsan";
public int age;
public String str1 = "ball";
public String str2 = "baskecballl";
public Person(){
this.str1=str1;
this.str2=str2;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + ", str1=" + str1
+ ", str2=" + str2 + "]";
}
}
复制代码
如果是调用set方法很简单,根据规则
Method methodName = p.getClass().getMethod("setName",String.class);
System.out.println(methodName.invoke(p, "张三"));
复制代码
这样就获取了,但是如果是get 方法呢,参数列表是空,怎么做的?
这样可以
Method methodName = p.getClass().getMethod("getName",null);
System.out.println(methodName.invoke(p,null));
复制代码
这样更好
Method methodName = p.getClass().getMethod("getName");
System.out.println(methodName.invoke(p));
复制代码
相关文章推荐
- 百度研发工程师面试题
- 最正确的学习方法,程序员如何学习一项你之前完全不了解的新技术?
- 黑马程序员——Java基础---线程的另一个总结(10)--练习,空中网面试题总结
- 不能上网怎么解决
- 面试题37:两个链表的第一个公共结点
- 黑马程序员——Java集合框架—整理笔记
- 面试题33:把数组排成最小的数
- 面试题31:连续子数组的最大和
- 黑马程序员——引入头文件
- 黑马程序员——java基础---多线程
- 面试二叉树问题集锦
- 黑马程序员---Unix相关---常用命令
- 《程序员的修炼-培养思维潜能的9个习惯》 读书笔记
- Java并发3-多线程面试题
- 招聘初级程序员必须考虑的6个因素
- iOS面试题(3)----内存管理
- IOS面试题(2)----线程
- IOS面试题(1)----分类
- 黑马程序员——Java基础--内部类总结
- 黑马程序员——用函数实现两变量值交换