一、反射技术 reflect
反射的官方定义:指程序可以访问、检测和修改它本身状态或行为的一种能力。
我对反射的理解:在正常的编程中,必须先有一个对象,才能调用类中定义的方法,访问类中的成员变量。通过反射,我们可以在没有具体对象的情况下,通过类的Class 属性,通过Class可以获取类的构造方法,字段,以及方法。然后我们可以调用构造方法,设置字段的值,以及调用类的方法。
反射的应用领域:大部分框架都是通过反射实现的。
反射的应用方法:
package com.sun;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, NoSuchFieldException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1.获取Class
//方法一
Class<String> cla1 = String.class;
Class cla2 = int.class;
//方法二
String str = "";
Class cla3 = str.getClass();
//方法三
Class.forName("java.lang.String");//抛出异常ClassNotFoundException
//2.获取构造方法
//获取无参构造函数
Constructor con1 = cla1.getConstructor();
//获取参数类型为String的有参构造方法 -------方法参数为构造方法参数对应的Class
Constructor con2 = cla1.getConstructor(String.class);
//获取本类中所有构造方法
Constructor[] con3 = cla1.getDeclaredConstructors();
//获取所有公共的构造方法
Constructor[] con4 = cla1.getConstructors();
//3. Constructor的常用操作
//创建对象----没加泛型创建的是Object对象,可以进行强转。
String str1 = (String)con1.newInstance();
//4. 获取字段
Class cla5 = Book.class;
//根据指定字段名获取字段---包括私有。
Field f1 = cla5.getDeclaredField("count");
//根据指定字段名的public字段
Field f2 = cla5.getField("pub");
//获取本类中所有的字段----包括私有
Field fs1[] = cla5.getDeclaredFields();
//获取所有public字段。----包括从父类继承的
Field fs2[] = cla5.getFields();
//5.Field 相关操作
Book book = Book.class.getConstructor().newInstance();
//给字段赋值---在访问权限之内的才可以赋值。
//f2 是上面获取到的price字段 ----book是新建的一个Book对象。---12是需要给字段赋的值
f2.setInt(book, 12);
//获取字段的值
System.out.println(f2.get(book));
//给私有字段赋值----不推荐使用
f1.setAccessible(true);
f1.setInt(book, 22);
System.out.println(f1.get(book));
//获取字段类型 Class
f1.getType();
//获取通用的类型 Type
f1.getGenericType();
//获取字段所属的类的Class
f1.getDeclaringClass();
//6.获取方法
Class cla = Book.class;
//获得所有public的方法,-----包括从父类那里继承的。
Method[] m = cla.getMethods();
//获得 本类的所有方法。------包括公共的和私有的。
Method[] m1 = cla.getDeclaredMethods();
//获得某个特定的public方法。指定 方法名 和 参数对应的Class -----
Method m2 = cla.getMethod("setCount", int.class);//获取方法名为substring,参数为int的方法。
//获取本类中指定方法名和参数的方法-----包括私有的
Method m3 = cla.getDeclaredMethod("setCount", int.class);//获取本类中方法名为substring,参数为int的方法。
//7. Method相关操作
//方法的调用
//m3 是获取到的方法实例 book是所要方法所属类的对象。 32是方法执行的参数
m3.invoke(book, 32);
//获取返回值类型
m3.getReturnType();
//获取参数类别对应的Class数组
m3.getParameterTypes();
}
}
二、内省机制introspector
官方说法:内省(Introspector)是Java 语言对Bean类属性、事件的一种缺省处理方法。
理解:内省就是通过反射,对JavaBean的属性及方法进行操作。主要目的是为了操作JavaBean的属性,主要体现在对set/get方法的操作。内省是对反射的一个封装。
内省相关的类在JDK的java.beans包下。主要用法如下:
package com.sun.introspection;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import org.junit.Test;
public class IntrospectionDemo {
@Test
public void test() throws IntrospectionException {
//1.通过Introspector类提供的静态方法getBeanInfo(Class<?> beanClass); 获取到一个BeanInfo对象
BeanInfo bean = Introspector.getBeanInfo(Book.class);
//2.获取bean的属性
PropertyDescriptor[] pds = bean.getPropertyDescriptors();
//【注意】:属性不等于字段。如果一个类的成员变量,但是没有提供get/set方法,那么这个字段就不是属性。
//【注意】:属性是根据get/set方法来判断的,返回值不是void的get方法,参数列表补位空的set方法,都算是类的一个属性
//当然 void setA(int a);int getA();这2个方法同时存在只说明类有一个a属性
//3.PropertyDescriptor属性相关应用
for (PropertyDescriptor pd : pds) {
//获取属性的名称----包括从父类继承的。
System.out.println(pd.getName());
//获取属性的类型
pd.getPropertyType();
//获取属性对应的读、写方法,即get/set方法 如果没有对应的方法返回null.Method相关方法见《反射》
Method mw = pd.getWriteMethod();
Method mr = pd.getReadMethod();
}
//4.获取bean中的方法 包括从父类继承的方法 方法包装在MethodDescriptor对象中
MethodDescriptor[] mds = bean.getMethodDescriptors();
//MethodDescriptor 详细方法
for (MethodDescriptor md : mds) {
System.out.println(md);
}
}
}
三、beanUtils