黑马程序员---反射笔记
反射定义:
反射会造成性能的下降,然后简而言之反射就把相应的类映射成对应的class,然后透过调用java自带的方法可以这个class对象进行相应的操作,能够完整的调用它所有的方法与属性,包换私有的
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
有时候我们说某个语言具有很强的动态性,有时候我们会区分动态和静态的不同技术与作法。我们朗 朗上口动态绑定(dynamic binding)、动态链接(dynamic linking)、动态加载(dynamic loading)等。然而“动态”一词其实没有绝对而普遍适用的严格定义,有时候甚至像对象导向当初被导入编程领域一样,一人一把号,各吹各的调。
一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机 制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的 classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、 或对其fields设值、或唤起其methods1。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
Java如何能够做出上述的动态特性呢?这是一个深远话题,本文对此只简单介绍一些概念。整个 篇幅最主要还是介绍Reflection APIs,也就是让读者知道如何探索class的结构、如何对某个“运行时才获知名称的class”生成一份实体、为其fields设值、调用其 methods。本文将谈到java.lang.Class,以及java.lang.reflect中的Method、Field、Constructor等等classes。
J2se1.6提供的API
字节码定义:
Bytecode通常指的是已经经过编译,但与特定机器码无关,需要直译器转译后才能成为机器码的中间代码。Bytecode通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令等构成的序列。
Bytecode主要为了实现特定软件运行和软件环境、硬件环境无关。Bytecode的实现方式是通过编译器和虚拟机器。编译器将源码编译成Bytecode,特定平台上的虚拟机器将Bytecode转译为可以直接执行的指令。Bytecode的典型应用为Java语言。
获得字符码的方式有三种:
1、 类名.class 例如,System.class
2、 对象.getClass(),例如,new Date().getClass();
3、 Class.forName(“类名”),例如Class.ForName(“java.util.Date”);
java 1.6提供的API信息如下:
方法摘要 |
||
boolean |
||
|
getAnnotation(Class<T> annotationClass) |
|
getDeclaredAnnotations() |
||
getDeclaringClass() |
||
Class<?>[] |
getExceptionTypes() |
|
Type[] |
getGenericExceptionTypes() |
|
Type[] |
getGenericParameterTypes() |
|
int |
getModifiers() |
|
getName() |
||
Annotation[][] |
getParameterAnnotations() |
|
Class<?>[] |
getParameterTypes() |
|
TypeVariable<Constructor<T>>[] |
getTypeParameters() |
|
int |
hashCode() |
|
boolean |
isSynthetic() |
|
boolean |
isVarArgs() |
|
newInstance(Object... initargs) |
||
toGenericString() |
||
toString() |
下面的源程序,主要是对反射字段的应用
ReflectTest类:
1 package day1;
2 import java.lang.reflect.Field;
3 public class ReflectTest{
4 public static void main(String[] args){
5 String str1="abc";
6 Class cls1=str1.getClass();
7 Class cls2=String.class;
8 //Class cls3=Class.forName("java.lang.String");
9 System.out.println(cls1==cls2);
10 // System.out.println(cls1==cls3);
11 System.out.println(cls1.isPrimitive());
12 System.out.println(int.class.isPrimitive());
13 System.out.println(int.class==Integer.class);
14 System.out.println(int.class==Integer.TYPE);
15 System.out.println(int[].class.isPrimitive());
16 try{
17 //获取相对应的字段
18 ReflectPoint pt1=new ReflectPoint(3,5);
19 Field fieldY=pt1.getClass().getField("y");
20 System.out.println(fieldY.get(pt1));
21 Field fieldx=pt1.getClass().getDeclaredField("x");
22 fieldx.setAccessible(true);
23 System.out.println("a"+fieldx.get(pt1));
24 changeStringValue(pt1);
25 System.out.println(pt1);
26 }catch(Exception e2)
27 {
28 System.out.println(e2);
29 }
30 }
31
32 private static void changeStringValue(Object obj) throws Exception {
33 Field[] fields=obj.getClass().getFields();
34 for(Field field:fields){
35 //field.getType().equals(String.class);
36 if(field.getType()==String.class)
37 {
38 //以后是取出相应的字段,然后用replace方法下替换字符
39 String oldValue=(String)field.get(obj);
40 String newValue=oldValue.replace('b', 'a');
41 field.set(obj, newValue);
42 }
43 }
44
45 }
46
47
48 }
ReflectPoint类:
1 package day1;
2
3 public class ReflectPoint{
4 private int x;
5 public int y;
6 public String str1="ball";
7 public String str2="basketball";
8 public String str3="itcast";
9 public ReflectPoint(int x, int y) {
10 super();
11 this.x = x;
12 this.y = y;
13 }
14 /* (non-Javadoc)
15 * @see java.lang.Object#toString()
16 */
17 @Override
18 public String toString() {
19 // TODO Auto-generated method stub
20 return str1+":"+str2+":"+str3;
21 }
22
23 }