Java学习随笔——反射

1.Class类与Java反射
Java中反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述实现访问、检测和修改描述Java对象本身信息的功能。

所有Java类均继承了Object类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。
Class textFieldC = textField.getClass(); //textField为 JTextField类的对象。

利用Class类的对象textFieldC,可以访问用来返回该对象的textField对象的描述信息

通过反射可访问的主要描述信息
在这里插入图片描述
在通过getFields()getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法

通过方法getDeclaredFields()getDeclaredMethods()只是获得在本类中定义的所有成员变量和方法。

(a).访问构造方法
通过下列一组方法访问构造方法时,将返回Constructor类型的对象或数组。每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法。

getConstructors()。
getConstructor(Class<?>…parameterTypes)。
getDeclaredConstructors()。
getDeclaredConstructor(Class<?>…parameterTypes)。

是访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。

两种访问一个入口参数类型依次为String和int型的构造方法

objectClass.getDecclaredConstructor(String.class,int.class);
objectClass.getDecclaredConstructor(new Class[]{String.class,int.class}});

Constructor类的常用方法
在这里插入图片描述

getModifiers()方法的返 回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,既可以查看是否被指定的修饰符修饰,还可以以字符串的形式获得所有修饰符

Modifier类中的常用解析方法
在这里插入图片描述

判断对象constructor所代表的构造方法是否被private修饰,以及以字符串形式获得该构造方法的所有修饰符的典型代码如下:

int modifiers=constructor.getModifiers();
boolean isEmbellishByPrivate=Modifier.Private(modifiers);
String embellishment=Modeiier.toString(modiiers);
public class Example_01{
    String s;
    int i,i2,i3;
    private Example_01(){
    }
    protected Example_01(String s,int i){
        this.s=s;
        this.i=i;
    }
    public Example_01(String...strings)throws NumberFormatException{
        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;

public class Main_01{
    public static void main(String[] args){
        Example_01 example=new Example_01("10","20","30");
        Class<?extends Example_01>exampleC=example.getClass();//获得构造方法
        Constructor[] declaredConstructors=exampleC.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]);
            }
            Example_01 example2=null;
            while(example2==null){
                try{//如果该成员变量的访问权限为private。则抛出异常,即不允许访问
                    if(i==2)//通过执行默认没有 参数的构造方法来创建对象
                        example2=(Example_01)constructor.newInstance();
                    else if(i==1)
						//通过执行具有两个参数的构造方法创建对象 
                        example2=(Example_01)constructor.newInstance("7",5);
                    else{ //通过执行具有可变量参数的构造方法创建对象
                        Object[] parameters=new Object[]{new String[] {"100","200","300"}};
                        example2=(Example_01)constructor.newInstance(parameters);
                    }
                }catch(Exception e){
                    System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
                    constructor.setAccessible(true);//设置为允许访问
                }
            }
            if(example2!=null){
                example2.print();
                System.out.println();
            }
        }
    }
}

throw和throws关键字.

访问成员变量
通过下列一组方法访问成员变量时,将返回Field类型的对象或数组每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。

getFields()。
getField(String name)。
getDeclaredFields()。
getDeclaredField(String name)。

如果是访问指定的成员变量,可以通过该成员变量的名称来访问。如访问一个Bird的成员变量:
object. getDeclaredField(“Brid”);

Field类的常用方法
在这里插入图片描述

public class Example_02{
    int i;
    public float f;
    protected boolean b;
    private String s;
}

import java.lang.reflect.Field;
public class Main_02{
    public static void main(String[] args){
        Example_02 example=new Example_02();
        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。则抛出异常,即不允许访问
                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)){
                        System.out.println("利用方法setBoolean()修改成员变量的值");
                        field.setBoolean(example,true);
                    }else{
                        System.out.println("利用方法set()修改成员变量的值");
                        field.set(example,"MVQ");//可以为各种类型成员变量赋值
                    }
					//获得成员变量值
                    System.out.println("修改后的值为:"+field.get(example));
                }catch(Exception e){
                    System.out.println("在设置成员变量值时抛出异常,"
                            +"下面执行setAccessible()方法");
                    field.setAccessible(true);//设置为允许访问
                    isTurn=true;
                }
            }
            System.out.println();
        }
    }
} 

访问方法
在通过下列一组方法访问方法时,将返回Method类型的对象或数组。每个Method对象代表一个方法,利用Method对象可以操纵相应的方法

getMethods()。
getMethod(String name, Class<?>…parameterTypes)。getDeclaredMethods()。
getDeclaredMethod(String name, Class<?>…parameterTypes)。

如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。如访问一个名称为print、入口参数类型依次为String和int型的方法。两种方法都可以实现。

objectClass.getDeclaredMethod(“print”, String.class, int.class);

objectClass.getDeclaredMethod(“print”, new Class[]{String.class, int.class });

Method类的常用方法
在这里插入图片描述

2.使用Annotation功能
Java中提供了Annotation功能,该功能可用于类、构造方法、成员变量、方 法、参数等的声明中。

(1).定义Annotation类型
定义Annotation类型的关键字为 @interface,这个关键字的隐含意思是继承了java.lang.annotation.Annotation接口

public @interface NoMemberAnnotaion{
}

上面定义的的Annotation类型@NoMemberAnnotation未包含任何成员,这样的Annotation类型被称为marker annotation。

下面定义了一个只包含一个 成员的Annotation类型

public @interfce OneMemberAnnoation{
	String value();
}

String:成员类型。可用的成员类型有String、Class、primitive、 enumerated和annotation,以及所列类型的数组
value:成员名称。如果在所定义的Annotation类型中只包含一个成员, 通常将成员名称命名为value。

定义包含多个成员的Annotation类型

public @interace MoreMemberAnnotatioin{
	String describe();
	Class type();
}

在为Annotation类型定义成员时,也可以为成员设置默认值

public @interface DefautValueAnnotation{
	String escribe()default"<默认值>";
	Class typedefault"<默认值>";
}

定义Annotation类型时,还可以通过Annotation类型**@Target设置 Annotation类型适用的程序元素种类**。未设置@Target,则表示适用于所有程序元素。*

枚举类ElementType中的枚举常量用来设置@Targer*。
枚举类ElementType中的枚举常量
在这里插入图片描述

通过Annotation类型**@Retention可以设置Annotation的有效范围。**如果未设置@Retention,Annotation的有效范围为枚举常量CLASS表示的范围。

枚举类 RetentionPolicy中的枚举常量用来设置@Retention
枚举类RetentionPolicy中的枚举常量
在这里插入图片描述

(2).访问Annotation信息
在定义Annotation类型时将@Retention设置为 RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的 Annotation信息,如获取构造方法、字段和方法的Annotation信息。

Constructor、Field和Method均继承了AccessibleObject类,在 AccessibleObject中定义了3个关于Annotation的方法

a.方法 isAnnotationPresent(Class<? extends Annotation> annotationClass)用 来查看是否添加了指定类型的Annotation,如果是则返回true,否则返回false.

b.方法**getAnnotation(ClassannotationClass)**用来获得指定类型的Annotation,如果存在则返回相应的对象,否则返回null

c.方法 getAnnotations()用来获得所有的Annotation,该方法将返回一个Annotation数组

类Constructor和Method中还定义了方法getParameterAnnotations(), 用来获得为所有参数添加的Annotation,将以Annotation类型的二维数组返回,在数组中的顺序与声明的顺序相同,如果没有参数则返回一个长度为0的数组;如果存在未添加Annotation的参数,将用一个长度为0的嵌套数组占位。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值