-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
Java基础之反射
1.什么反射机制,反射机制的作用:
简单的来说,反射机制指的是程序在运行时能够获取自身的信息。只要给 定类的名字,就可以通过反射机制来获得类的所有信息,并调用类的方法。
要了解反射机制的作用就涉及到了动态与静态的概念:
静态编译:在编译时确定类型,绑定对象。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
反射机制的作用就是可以实现动态创建对象和编译,体现出很大的灵活性,基于这个特性为设计的程序框架有极大的灵活性(java程序框架中大量用到此特性)。
2.反射机制实现原理:
jdk在运行时可以将每个类封装成一个叫“Class”的类,此类是对运行的类进行描述与封装的类,是反射机制运用的基石,通过这个类我们可以得到任何类的内部结构(字段、方法、注解甚至是修饰关键字),进而调用这个为原方法,利用这个类的相关属性等等。也就是说通过这个机制程序在设计时可以不指定具体的需要运行的类,在实际运行的时候才确定具体的类,都可以运行。
3.反射机制的基石:Class类
此类是反射机制的基石(可以把它看成一个普通的类就好理解了),通过这个类可以得到任意一个类的信息,获得Class对象的方式主要有三种:
1、调用某个类的class属性获取Class对象,如Person.class会返回Person类对应的Class 对象;
2、使用Class类的forName(StringclassName)静态方法,className表示全限定名;
3、调用某个对象的getClass()方法。该方法属于Object类;
**********************************************************************
//方式一
Class c1 = Person.class;
//方式二(最为常用,最好用)
Class c2 = Class.forName("com.chenpj.reflection.Person");
//方式三
Class c3 = newPerson().getClass();
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
**********************************************************************
4.常用方法:
方法摘要 | ||
| getAnnotation | |
getAnnotations | ||
getClassLoader | ||
getConstructor | ||
getConstructors | ||
getDeclaredAnnotations | ||
Class | getDeclaredClasses | |
getDeclaredConstructor | ||
getDeclaredConstructors | ||
getDeclaredField | ||
Field | getDeclaredFields | |
getDeclaredMethod | ||
Method | getDeclaredMethods | |
Class | getDeclaringClass | |
T | getEnumConstants | |
getField | ||
Field | getFields | |
Type | getGenericInterfaces | |
getGenericSuperclass | ||
Class | getInterfaces | |
getMethod | ||
Method | getMethods | |
| getModifiers | |
getName | ||
getPackage | ||
getProtectionDomain | ||
getSuperclass | ||
TypeVariable | getTypeParameters | |
| isAnnotation | |
| isAnnotationPresent | |
| isAnonymousClass | |
| isArray | |
| isAssignableFrom | |
| isEnum | |
| isInstance | |
| isInterface | |
| isLocalClass | |
| isMemberClass | |
| isPrimitive | |
| isSynthetic | |
newInstance |
例如:通过Class类得到某个对象的方法,字段以及构造器:
**********************************************************************
//得到Class对象
Classc2=Class.forName("com.chenpj.reflection.Person");
//得到所有方法(包括私有方法)
Method[]methods=c2.getDeclaredMethods();
System.out.println("---------得到所有方法--------------");
for(Method method:methods){
System.out.println("方法权限修饰:"
+Modifier.toString(method.getModifiers()));
method.setAccessible(true);//将方法设为可访问(包括私有的方法)
System.out.println("方法名:"+method.getName());
System.out.println("方法返回类型:"+method.getReturnType());
System.out.println("方法参数类型:"+method.getParameterTypes());
System.out.println("~~~~~~~~~~~~~~~~~~");
}
System.out.println("---------得到所有字段--------------");
//得到所有字段
Field[]fields=c2.getDeclaredFields();
for(Field field:fields){
System.out.println(field);
}
System.out.println("---------得到所有造器--------------");
//得到所有构造器(此方法不能得到私用构造方法,具体看API)
Constructor[]constructor=c2.getConstructors();
for(Constructor constructor2:constructor){
System.out.println(constructor2);
}
**********************************************************************
利用反射实例化对象:
方式一:通过默认的无参构造器;
方式二:通过指定的构造器,例如:
**********************************************************************
Class c2=Class.forName("com.chenpj.reflection.Person");
//方式一:通过默认构造方法:
Personperson=(Person)c2.newInstance();
person.eat("面条");
//方式二:通过指定的构造方法:
Constructorconstructor=c2.getConstructor(int.class,String.class,String.class);
Personperson=(Person)constructor.newInstance(20,"tom","USA");
System.out.println(person);
**********************************************************************
使用反射调用方法
步骤:
1.通过类名得到Class;
2.通过Class的getMethod,getDeclaredMethod,得到指定的方法对应的Method类;
3.利用Method的invoke方法调用方法的执行,例如:
**********************************************************************
Classc2=Class.forName("com.chenpj.reflection.Person");
//一,访问public修饰方法
MethodeatMethod=c2.getMethod("eat",String.class);
eatMethod.invoke(c2.newInstance(),"面包");//方法调用需要传递一个对象及方法的参数
//二、访问private修饰方法
Methodtest1Method=c2.getDeclaredMethod("test1",.class);
test1Method.setAccessible(true);//设置方法可以访问
test1Method.invoke(c2.newInstance(),"测试参数");
//三,访问可变参数方法
Methodtest3Method=c2.getDeclaredMethod("test3",int[].class);
test3Method.invoke(c2.newInstance(),newint[]{1});
**********************************************************************
默认情况下private修饰的方法是不可访问的,需要调用getDeclaredMethod(string,ags)方法得到,并调用Method对象的setAccessible(boolean)方法,传递”true”参数,将方法设置为可以访问。
使用反射给对象属性赋值:
第1步:通过类名得到Class
第2步:通过Class对象的getDeclaredField(string)方法得到指定的属性对应的Field类;
第3步:调用Field类setAccessible(boolean),设置属性可以修改;
第4步:通过Field类set(obj,value)方法为属性赋值。
**********************************************************************
Classc2=Class.forName("com.chenpj.reflection.Person");
//得到根据属性名得到对应的Field类
Fieldfield_name=c2.getDeclaredField("name");
Fieldfield_aget=c2.getDeclaredField("age");
//将属性设置为可设置
field_name.setAccessible(true);
field_aget.setAccessible(true);
//得到一个属性所在的对象
Objectobject=c2.newInstance();
//高用set方法设置值
field_name.set(object,"tomcat");
field_aget.set(object,25);
System.out.println(object);
**********************************************************************