反射与注解
反射
通过Java反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述,实现访问、检测和修改描述Java对象本身信息的功能。Java反射机制的功能十分强大,在java.lang.reflect包中提供了对该功能的支持。
访问构造方法
在通过下列一组方法访问构造方法时,将返回 Constructor 类型的对象或数组。每个Constructor 对象代表一个构造方法。
Constructor 类的常用方法
方法 | 说明 |
isVarArgs() | 查看该构造方法是否允许带有可变数量的参数,如果允许则返回 true,否则返回 false |
getParameterTypes() | 按照声明顺序以Class数组的形式获得该构造方法的各个参数的类型 |
getExceptionTypes() | 以Class 数组的形式获得该构造方法可能抛出的异常类型 |
newInstance(Object...initargs) | 通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法 |
setAccessible(boolean flag) | 如果该构造方法的权限为 private,默认为不允许通过反射利用 newInstance(Objectinitargs)方法创建对象。那么,先执行该方法,并将入口参数设为 true,则允许创建 |
getModifiers() | 获得可以解析出该构造方法所采用修饰符的整数 |
Modifier类中的常用解析方法
静态方法 | 说明 |
isPublic(int mod) | 查看是否被 public 修饰符修饰,如果是则返回true,否则返回 fals |
isProtected(int mod) | 查看是否被 protected 修饰符修饰,如果是则返回 true,否则返回 false |
isPrivate(int mod) | 查看是否被private 修饰符修饰,如果是则返回 true,否则返回 false |
isStatic(int mod) | 查看是否被static修饰符修饰,如果是则返回 true,否则返回 false |
isFinal(int mod) | 查看是否被 final修饰符修饰,如果是则返回true,否则返回 false、 |
toString(int mod) | 以字符串的形式返回所有修饰符 |
package com.mr;
public class Demo1 {
String s;
int i,i2,i3;
public Demo1(){
}
public Demo1(String s,int i) {
this.s=s;
this.i=i;
}
public Demo1(String...strings) {
if(0<strings.length)
i=Integer.valueOf(strings[0]);
if(1<strings.length)
i2=Integer.valueOf(strings[1]);
if(2<strings.length)
i3=Integer.valueOf(strings[2]);
}
public void print() {
System.out.println("s="+s);
System.out.println("i="+i);
System.out.println("i2="+i2);
System.out.println("i3="+i3);
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import com.mr.Demo1;
public class Demo {
public static void main(String[] args) {
Demo1 d1=new Demo1("10","20","30");
Class<?extends Demo1>Demo1Class=d1.getClass();
Constructor[] declaredConstructors=Demo1Class.getDeclaredConstructors();
for(int i=0;i<declaredConstructors.length;i++) {//遍历构造方法
Constructor<?>constructor=declaredConstructors[i];
System.out.println("查看是否允许带有可变数量的参数:"+constructor.isVarArgs());
System.out.println("该构造方法的入口参数类型依次为:");
Class[] parameterTypes=constructor.getParameterTypes();//获取所有参数类型
for(int j=0;j<parameterTypes.length;j++) {
System.out.println(""+parameterTypes[j]);
}
System.out.println("该构造方法可能抛出的异常类型为:");
//获取所有可能抛出的异常信息类型
Class[] exceptionTypes=constructor.getExceptionTypes();
for(int j=0;j<exceptionTypes.length;j++) {
System.out.println(""+exceptionTypes[j]);
}
Demo1 d2=null;
while(d2==null) {
try {//如果构造方法的访问权限为private或protected,则出现异常,即不允许访问
if(i==2)
d2=(Demo1)constructor.newInstance();
else if(i==1)
//通过执行具有两个参数的构造方法创建对象
d2=(Demo1)constructor.newInstance("7",5);
else {
Object[]parameters=new Object[] {new String[] {"100","200","300"}};
d2=(Demo1)constructor.newInstance(parameters);
}
}catch(Exception e) {
System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
constructor.setAccessible(true);//设置允许访问
}
}
if(d2!=null) {
d2.print();
System.out.println();
}
}
}
}
访问成员变量
在通过下列一组方法去访问成员变量时,将返回 Field 类型的对象或数组。
package com.mr;
public class Demo1 {
int i;
public float f;
protected boolean b;
private String s;
}
import java.lang.reflect.Field;
import com.mr.Demo1;
public class Demo {
public static void main(String[] args) {
Demo1 example=new Demo1();
Class exampleC=example.getClass();
Field[]declaredFields=exampleC.getDeclaredFields();//获取所有成员变量
for(int i=0;i<declaredFields.length;i++) {//遍历成员变量
Field field=declaredFields[i];
System.out.println("名称为:"+field.getName());
Class fieldType=field.getType();
System.out.println("类型为:"+fieldType);
boolean isTurn=true;
while(isTurn) {
//如果该成员变量的访问权限为private或protect,则抛出异常,即不允许访问
try {
isTurn=false;
//获取成员变量值
System.out.println("修改前的值为:"+field.get(example));
if(fieldType.equals(int.class)) {//判断成员变量的类型是否为int型
System.out.println("利用方法setInt()修改成员变量的值");
field.setInt(example,168);//为int型成员变量赋值
}else if(fieldType.equals(float.class)) {//判断成员变量的类型是否为float型
System.out.println("利用方法setFloat()修改成员变量的值");
field.setFloat(example,99.9F);//为float型成员变量赋值
}else if(fieldType.equals(boolean.class)){//判断成员变量的类型是否为boolean型
System.out.println("利用方法setBoolean()修改成员变量的值");
field.setBoolean(example,true);//为boolean型成员变量赋值
}else{
System.out.println("利用方法set()修改成员变量的值");
field.set(example,"MWQ");//为不同类型的成员变量赋值
}
//获取成员变量值
System.out.println("修改后的值:"+field.get(example));
}catch(Exception e) {
System.out.println("在设置成员变量值时抛出异常,"+"下面执行setAccessible()方法");
field.setAccessible(true);//设置为允许访问
isTurn=true;
}
}
System.out.println();
}
}
}
访问成员方法
在通过下列一组方法访问成员方法时,将返回 Method 类型的对象或数组。
Annotation 注解功能
Java提供了 Annotation 注解功能 ,该功能可用于类、构造方法、成员变量、成员方法、参数等的声明中。该功能不影响程序的运行,但是会对编译器警告等辅助工具产生影响。
定义 Annotation 类型
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//用于字段、方法和参数
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)//在运行时加载Annotation到JVM中
public @interface Field_Method_Parameter_Annotation {
String describe();//定义一个没有默认值的String型成员
Class type()default void.class;//定义一个具有默认值的Class型成员
}
public class Record {
@Field_Method_Parameter_Annotation(describe="编号",type=int.class)
//注释字段
int id;
@Field_Method_Parameter_Annotation(describe="姓名",type=String.class)
String name;
@MyAnnotation()
//采用默认值注释构造方法
public Record(){
}
@MyAnnotation("立即初始化构造方法")
//注释构造方法
public Record(@Field_Method_Parameter_Annotation(describe="编号",type=int.class)int id,
@Field_Method_Parameter_Annotation(describe="姓名",type=String.class)String name){
this.id=id;
this.name=name;
}
@Field_Method_Parameter_Annotation(describe="获取编号",type=int.class)
//注释方法
public int geInt() {
return id;
}
@Field_Method_Parameter_Annotation(describe="设置编号")
//成员type采用默认值注释方法
public void seInt(
//注释方法的参数
@Field_Method_Parameter_Annotation(describe="编号",type=int.class)int id){
this.id=id;
}
@Field_Method_Parameter_Annotation(describe="获取姓名",type=String.class)
public String getName() {
return name;
}
@Field_Method_Parameter_Annotation(describe="设置姓名")
public void setName(@Field_Method_Parameter_Annotation(describe="姓名",type=String.class)String name){
this.name=name;
}
}
访问 Annotation 信息
如果在定义 Annotation 类型时将@RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的 Annotation 信息,如获取构造方法、字段和方法的 Annotation 信息。