JSE7-反射和注解

1.反射

1.1 反射概述

反射(Reflection)是 Java特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。例如,使用它能获得 Java 类中各成员的名称并显示出来。

1.2 示例

package cn.htmlv5.bobshute.jse.javasihu.reflect7;

import java.lang.reflect.*;

public class ReflectTest {

    public static final int i = 11;

    public  String str;

    private int j;

    private String [] strArray;


    public static void main(String args[]) throws Exception {
        //1.返回类的各方法名以及它们的限制符和返回类型
        reflectDeclaredMethods();
        //2.判断是否一类-isInstance
        reflectInstance();
        //3.获取方法详细信息:方法名,所在类,参数信息,异常信息,返回类型
        reflectMethodsDetail(null,null);
        //4.获取方法详细信息:方法名,所在类,参数信息,异常信息
        reflectConstructor();
        //5.类的属性字段(域字段)
        reflectFields();
        //6.通过实例化构造方法,实例化对象
        reflectNewInstance();
        //7.根据方法名称执行方法
        reflectExecMethod();
        //8.修改类的属性值
        changeFiledValue();
        //9.操作数组1-普通数组
        reflectArray();
        //10.操作数组2-多维数组
        reflectArrayDim();
    }

    /**
     * 1. 返回类的各方法名以及它们的限制符和返回类型
     运行结果:
     private static java.lang.Object java.util.Collections.get(java.util.ListIterator,int)
     public static java.lang.Object java.util.Collections.min(java.util.Collection,java.util.Comparator)
     public static java.lang.Object java.util.Collections.min(java.util.Collection)
     ...
     public static java.util.SortedSet java.util.Collections.unmodifiableSortedSet(java.util.SortedSet)
     static java.lang.Object[] java.util.Collections.zeroLengthArray(java.lang.Class)
     */
    public static void reflectDeclaredMethods() throws Exception {
        Class c = Class.forName("java.util.Collections");

        Method m[] = c.getDeclaredMethods();
        for (int i = 0; i < m.length; i++){
            System.out.println(m[i].toString());
        }

    }

    /**
     * 2. 判断是否一类-isInstance
     */
    public static void reflectInstance() throws Exception {
        Class c1 = Long.TYPE;
        Class c2 = long.class;
        Class c3 = Long.class;
        //long-long-class java.lang.Long
        System.out.println(c1+"-"+c2+"-"+c3);   

        Class cls = Class.forName(Long.class.getName());
        boolean b1 = cls.isInstance(new Integer(37));
        //b1->false
        System.out.println("b1->"+b1);
        boolean b2 = cls.isInstance(new Long(37));
        //b2->true
        System.out.println("b2->"+b2);
    }

    /**
     * 3. 打印方法详细信息:方法名,所在类,参数信息,异常信息,返回类型
     只列出当前方法的:
    <---第2个method开始---
    method name => reflectMethodsDetail
    declaring class = class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
    method param [0] => class java.lang.Object
    method param [1] => class java.lang.String
    exception types [0] =>class java.lang.Exception
    return type => void
    ---第2个method结束--->
     */
    public static void reflectMethodsDetail(Object o,String str) throws Exception {
        try {
            Class cls = Class.forName("cn.htmlv5.bobshute.jse.javasihu.reflect7.ReflectTest");
            Method methlist[] = cls.getDeclaredMethods();
            for (int i = 0; i < methlist.length; i++) {
                System.out.println("<---第"+i+"个method开始---");
                Method m = methlist[i];
                System.out.println("method name => " + m.getName());
                System.out.println("declaring class = " + m.getDeclaringClass());
                Class pvec[] = m.getParameterTypes();
                for (int j = 0; j < pvec.length; j++)
                    System.out.println("method param [" + j + "] => " + pvec[j]);

                Class evec[] = m.getExceptionTypes();
                for (int j = 0; j < evec.length; j++)
                    System.out.println("exception types [" + j + "] =>" + evec[j]);

                System.out.println("return type => " + m.getReturnType());
                System.out.println("---第"+i+"个method结束--->");
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 4.查询构造方法信息
     * 
    <---第0个Constructor method开始---
    declaredConstructors name => cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
    declaredConstructors class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
    ---第0个Constructor method结束--->
    <---第1个Constructor method开始---
    declaredConstructors name => cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
    declaredConstructors class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
    param [0]=> class java.lang.String
    param [1]=> int
    ---第1个Constructor method结束--->
    <---第2个Constructor method开始---
    declaredConstructors name => cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
    declaredConstructors class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
    param [0]=> class java.lang.String
    param [1]=> class [Ljava.lang.String;
    ---第2个Constructor method结束--->
     * 
     */
    public static void reflectConstructor(){
        try {
            Class cls = Class.forName(cn.htmlv5.bobshute.jse.javasihu.reflect7.ReflectTest.class.getName());
            Constructor ctorlist[] = cls.getDeclaredConstructors();
            for (int i = 0; i < ctorlist.length; i++) {
                System.out.println("<---第"+i+"个Constructor method开始---");
                Constructor ct = ctorlist[i];
                System.out.println("declaredConstructors name => " + ct.getName());
                System.out.println("declaredConstructors class => " + ct.getDeclaringClass());

                Class pvec[] = ct.getParameterTypes();
                for (int j = 0; j < pvec.length; j++)
                    System.out.println("param [" + j + "]=> " + pvec[j]);
                Class evec[] = ct.getExceptionTypes();
                for (int j = 0; j < evec.length; j++)
                    System.out.println("exception types [" + j + "] =>" + evec[j]);
                System.out.println("---第"+i+"个Constructor method结束--->");
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 5.类的属性字段(域字段), 包括:属性名称,类型及修饰符
        <---第0个field开始---
        field name =>i
        declaring class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
        type =>int
        modifiers =>public static final
        ---第0个field结束--->
        <---第1个field开始---
        field name =>str
        declaring class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
        type =>class java.lang.String
        modifiers =>public
        ---第1个field结束--->
        <---第2个field开始---
        field name =>j
        declaring class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
        type =>int
        modifiers =>private
        ---第2个field结束--->
        <---第3个field开始---
        field name =>strArray
        declaring class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
        type =>class [Ljava.lang.String;
        modifiers =>private
        ---第3个field结束--->
     */
    public static void reflectFields(){
        try {
            Class cls = Class.forName(ReflectTest.class.getName());
            Field fieldlist[] = cls.getDeclaredFields();
            for (int i = 0; i < fieldlist.length; i++) {
                System.out.println("<---第"+i+"个field开始---");
                Field fld = fieldlist[i];
                System.out.println("field name =>" + fld.getName());
                System.out.println("declaring class => " + fld.getDeclaringClass());
                System.out.println("type =>" + fld.getType());
                int mod = fld.getModifiers();
                System.out.println("modifiers =>" + Modifier.toString(mod));
                System.out.println("---第"+i+"个field结束--->");
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }


    /**
     * 
    6. 实例化构造方法,通过构造方法实例化对象
     Constructor->str:Constructor str,j:47
     reflectobj.str->Constructor str,reflectobj.j->47
     */
    public static void reflectNewInstance(){
        try {
            Class cls = Class.forName(ReflectTest.class.getName());

            Class partypes[] = new Class[2];
                partypes[0] = String.class;
                partypes[1] = Integer.TYPE;
            Constructor ct = cls.getConstructor(partypes);  //准备构造方法

            Object arglist[] = new Object[2];
                arglist[0] = new String("Constructor str");
                arglist[1] = new Integer(47);
            ReflectTest reflectobj = (ReflectTest)ct.newInstance(arglist);//构造方法来实例化对象

            System.out.println("reflectobj.str->"+reflectobj.str+",reflectobj.j->"+reflectobj.j);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 7.根据方法名称及参数执行方法
     * reflectMethod-return->str147
     */
    public static void reflectExecMethod(){
        try {
            Class cls = Class.forName(ReflectTest.class.getName());

            Class partypes[] = new Class[2];
                partypes[0] = String.class;
                partypes[1] = Integer.TYPE;
            Method meth = cls.getMethod("testMethod2", partypes);

            // 先创建对象实例
            Object obj = cls.newInstance();
            // 然后调用方法
            Object arglist[] = new Object[2];
                arglist[0] = new String("str1");
                arglist[1] = new Integer(47);

            Object retobj = meth.invoke(obj, arglist);
            String retval = (String) retobj;
            System.out.println("reflectMethod-return->"+ retval);
        } catch (Throwable e) {
            System.err.println(e);
        }
    }

    /**
     * 8.修改类的属性
     * 注意:静态属性不能改变, Can not set static final int field,
     * private类型的也不行
     *
        str-1->null
        str-2->changeStrValue
     */
    public static void changeFiledValue() throws  Exception{
        Class cls = Class.forName(ReflectTest.class.getName());
        Field fld = cls.getField("str");
        Object obj = cls.newInstance();
        System.out.println("str-1->" + ((ReflectTest) obj).str);
        fld.set(obj, "changeStrValue");
        System.out.println("str-2->" + ((ReflectTest) obj).str);
    }

    /**
     * 9.操作数组1-普通数组
     *
     * this is a test5
     */
    public static void reflectArray() throws  Exception{
        Class cls = Class.forName("java.lang.String");
        Object arr = Array.newInstance(cls, 10);
        Array.set(arr, 5, "this is a test5");
        String s = (String) Array.get(arr, 5);
        System.out.println(s);
    }

    /**
     * 10.操作数组2-多维数组
     *
     cls->class [I
     arrcast[3][5][10]->137
     */
    public static  void reflectArrayDim() throws  Exception{
        int dims[] = new int[] { 5, 10, 15 };
        Object arr = Array.newInstance(Integer.TYPE, dims);
        Object arrobj = Array.get(arr, 3);
            Class cls = arrobj.getClass().getComponentType();
            System.out.println("cls->"+cls);
                arrobj = Array.get(arrobj, 5);
                    Array.setInt(arrobj, 10, 137);
        int arrcast[][][] = (int[][][]) arr;
        System.out.println("arrcast[3][5][10]->"+arrcast[3][5][10]);
    }

    //普通方法1
    public void testMethod1(String str1,int ii){
        System.out.println("testMethod1 is calling->str1:"+str1+",ii:"+ii);
    }

    //普通方法2
    public String testMethod2(String str1,int ii){
        System.out.println("testMethod2 is calling->str1:"+str1+",ii:"+ii);
        return str1+ii;
    }

    //Constructor-构造方法1
    public ReflectTest(){
    }

    //Constructor-构造方法2
    public ReflectTest(String str,int j){
        System.out.println("Constructor->str:"+str+",j:"+j);
        this.str = str;
        this.j = j;
    }

    //Constructor-构造方法3
    public ReflectTest(String str, String [] strArray){
        this.str = str;
        this.strArray = strArray;
    }

}


反射获取注解情况
//注意:只有@Retention(RetentionPolicy.RUNTIME)为runtime时才能通过注解获取到
public class TestMyAnno {
    /**
     * flag->true
     ma.myfiled()->myfiledvalue,ma.myfiled2()->myfiledvalue2
     */
    public static void main(String[] args) throws Exception {
        Class c = Class.forName(UseAnno.class.getName());
        System.out.println("c->"+c.getName());
        //判断时候存在注解
        boolean flag = c.isAnnotationPresent(MyAnno.class);
        System.out.println("flag->"+flag);
        if (flag) {
            MyAnno ma = (MyAnno) c.getAnnotation(MyAnno.class);
            System.out.println("ma.myfiled()->"+ma.myfiled()+",ma.myfiled2()->"+ma.myfiled2());
        }
    }
}

2.注解

2.1概述

  • 元数据
    所谓元数据就是数据的数据。也就是说,元数据是描述数据的。就象数据表中的字段一样,每个字段描述了这个字段下的数据的含义。

    元数据可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。许多元数据工具,如 XDoclet,将这些功能添加到Java中,成为 Java 编程功能的一部分。

    元数据的好处分为三类:文档编制、编译器检查和代码分析。代码级文档最常被引用。元数据提供了一种有用的方法来指明方法是否取决于其他方法,它们是否完整,特定类是否必须引用其他类,等等。

  • 注解
    注解就是 Java 源代码的元数据,也就是说注解是用来描述 Java 源代码的。基本语法就是@后面跟注解的名称。Java5 以上的版本都支持,有预定义的注解,也可以自定义注解。
    如: Override(覆盖父类方法),Deprecated(已过期),SuppressWarnings(抑制警告).

2.2 自定义注解

//自定义注解
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//父类的注解并不会被子类继承。加上Inherited注解后可以继承
@Inherited
//默认生成文档时不保留,加上该注解生成文档时保留
@Documented
//注解保持性(有效性),注意,只有为runtime时才可以被反射获取到
@Retention(RetentionPolicy.RUNTIME)
//target指明注解的使用范围,只有type和method
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface MyAnno {
    public String myfiled();    //成员
    public String myfiled2() default "filed2";  //有默认值的成员
}
//使用注解

@MyAnno(myfiled="myfiledvalue",myfiled2 = "myfiledvalue2")
public class UseAnno {

}

2.3 对注解的注解

  • Target 允许何种程序元素具有定义的注解类型
package java.lang.annotation;
public enum ElementType {       
    TYPE,   // Class,   interface, or enum (but not annotation)
    FIELD,  // Field (including enumerated values)
    METHOD, // Method   (does not include constructors)
    PARAMETER,  // Method   parameter
    CONSTRUCTOR,    // Constructor
    LOCAL_VARIABLE, // Local    variable or catch clause
    ANNOTATION_TYPE,    // Annotation Types (meta-annotations)
    PACKAGE // Java package
}       
  • Retention 设置保持性,元注释和Java 编译器处理注解的注解类型的方式有关.
public enum RetentionPolicy {

    SOURCE, // Annotation is discarded by the compiler

    CLASS, // Annotation is stored in the class file, but ignored by the VM 

    RUNTIME // Annotation is stored in the class file and read by the VM
}

source://注解仅存在于源码中,在class字节码文件中不包含
class://默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
runtime:// 注解会在class字节码文件中存在,在运行时可以通过反射获取到

  • Documented
    在默认的情况下在使用 javadoc 自动生成文档时,注解将被忽略掉。如果想在文档中也包含注解,必须使用 Documented 为文档注解。

  • Inherited
    在默认的情况下,父类的注解并不会被子类继承。如果要继承,就必须加上 Inherited 注解。

2.4 获取类注解情况

//注意:只有@Retention(RetentionPolicy.RUNTIME)为runtime时才能通过注解获取到
public class TestMyAnno {
    /**
     * flag->true
     ma.myfiled()->myfiledvalue,ma.myfiled2()->myfiledvalue2
     */
    public static void main(String[] args) throws Exception {
        Class c = Class.forName(UseAnno.class.getName());
        System.out.println("c->"+c.getName());
        //判断时候存在注解
        boolean flag = c.isAnnotationPresent(MyAnno.class);
        System.out.println("flag->"+flag);
        if (flag) {
            MyAnno ma = (MyAnno) c.getAnnotation(MyAnno.class);
            System.out.println("ma.myfiled()->"+ma.myfiled()+",ma.myfiled2()->"+ma.myfiled2());
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值