前言
JAVA不是动态语言,但JAVA具有一个突出的动态语言机制:
反射的反射机制是指程序运行时动态自检的能力:
- 能够获得任意一个类的全部信息,包含其属性和方法
- 能够任意访问一个对象的属性和方法
反射能让你执行一些正常情况下无法实现的操作:
- 访问私有属性和私有方法
- 不通过new关键字,而通过类名来实例化对象
反射常用四个API:
- Class:表示反射的核心类
- Method:表示类的方法
- Filed:表示类的属性
- Constructor:表示类的构造方法
获取calss对象
//一:类名.class
Class<FileNoUploadDto> aClass = FileNoUploadDto.class;
//二:全限定名:包名.类名
Class<?> aClass = Class.forName("com.joyintech.tams.wwp.outersvc.ValuationNoImp.dto.FileNoUploadDto");
//三:通过实例对象.getClass()
FileNoUploadDto dto = new FileNoUploadDto();
Class<? extends FileNoUploadDto> aClass1 = dto.getClass();
获取calss对象中的相关信息
//一:获取类名
Class<?> aClass = FileNoUploadDto.class;
String name = aClass.getName();
//二:获取类的修饰符
int modifiers = aClass.getModifiers();
//可以判断修饰符是否包含public,private,final,static...
Modifier.isPublic(modifiers);
Modifier.isStatic(modifiers);
//三:获取父类
Class<?> superclass = aClass.getSuperclass();
通过反射获取对象
//创建对象方式一:newInstance():适用于无参构造
Class<?> aClass = FileNoUploadDto.class;
FileNoUploadDto dto = (FileNoUploadDto) aClass.newInstance();
//创建对象方式二:getConstructor:适用于公共的构造
Constructor<?> constructor = aClass.getConstructor(String.class);
(FileNoUploadDto)constructor.newInstance("portfolioName");
//创建对象方式三:类构造方法私有时,暴力获取构造getDeclaredConstructor(),适用于所有构造
Constructor<?> constructor1 = aClass.getDeclaredConstructor(String.class, int.class);
//设置允许访问私有
constructor.setAccessible(true);
FileNoUploadDto dto1= constructor.newInstance("", 20);
用Field访问属性
-
从class对象中获取类的属性
-
Class<?> aClass = FileNoUploadDto.class; //公有属性的获取 Field portfolioName = aClass.getField("portfolioName"); //其他属性的获取 Field portfolioName1 = aClass.getDeclaredField("portfolioName");
-
-
访问对象中的该属性
-
//通过反射获取对象中所有属性于fields //获取对象中指定属性值:FileNoUploadDto.class.getDeclaredFields("ID/NAME..."); Field[] fields = FileNoUploadDto.class.getDeclaredFields(); //我这里是需要循环获取对象中的属性判断是否有注解,有再另做处理 for(int i=0;i<fields.length;i++){ Field field = fields[i]; //获取到有注解的属性 if(null!=field.getAnnotation(ExcelField.class)){ //通过注解里的属性名获取到值,如下获取属性name中注解ExcelField中的name值: //@ExcelField(name = "组合名称") //private String name; String name = field.getAnnotation(ExcelField.class).name(); if(null!=name){ //对获取到注解里的值(即"组合名称")另做所需处理 //..... } } }
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelField {
/**
* @return String
*/
String name() default "";
}
用Method调用方法
- 从class对象中获取类的方法
//从class对象中获取类的属性
Class<?> aClass = FileNoUploadDto.class;
//公有方法的获取
Method getPortfolioName = aClass.getMethod("getPortfolioName");
//其他方法的获取
Method getPortfolioName1 = aClass.getDeclaredMethod("getPortfolioName");
- 调用对象中的该方法
Class<?> aClass = FileNoUploadDto.class;
Method getPortfolioName = aClass.getMethod("getPortfolioName");
String name = (String)getPortfolioName.invoke(obj);
获取有参、私有的方法
- 获取有参的方法
Class<FileNoUploadDto> aClass = FileNoUploadDto.class;
FileNoUploadDto fileNoUploadDto = aClass.newInstance();
Method setPortfolioName = aClass.getMethod("setPortfolioName", String.class);
String s = (String) setPortfolioName.invoke(fileNoUploadDto, "");
- 获取私有的方法
Class<FileNoUploadDto> aClass = FileNoUploadDto.class;
FileNoUploadDto fileNoUploadDto = aClass.newInstance();
Method getPortfolioName = aClass.getDeclaredMethod("getPortfolioName");
getPortfolioName.setAccessible(true);
getPortfolioName.invoke(fileNoUploadDto);