zoukankan      html  css  js  c++  java
  • Java连载144-反射和自定义注解

    一、定义注解

    • 使用前提:使用@interface来进行声明,会自动继承java.lang.annotation.Annotation接口
    • 注解中的每一个方法实际上是声明了一个配置参数,方法的名称就是参数的名称,返回值的类型就是参数的类型,返回值只能是基本类型、Class、String、Enum,可以通过default关键字声明参数的默认值
    • 语法如下
    [public|final@interface 注解名
    {
     注解元素
    }
    • 注意:(1)不可与i继承其他注解或者接口;(2)@interface只能用来声明一个注解;(3)注解元素是一个无参数方法,方法的类型表示注解的类型
    • 注解元素的语法语法如下:
    数据类型  注解元素名()   [default 默认值];
    • 如果只有一个注解元素,在注解元素名为value的情况下,在使用的时候就可以不写出注解元素名,只需要给出注解值即可。
    • 使用位置:前一行或者同一行,并且在自定义注解后面的括号中写出注解的值。(不写则是默认值)

    1.注解元素的值

    • 注解元素一定要有确切的值,可以在定义的时候指定他的默认值,也可以在使用注解的时候指定默认值,非基本类型的注解元素的值不能为null,因此经常使用空字符串或者0作为默认值。
    package com.bjpowernode.java_learning;

    import java.lang.annotation.Retention;
    import java.lang.reflect.Field;

    @Retention(RetentionPolicy.RUNTIME)//元注解,运行时保留注解,必须有,否则注解值读不出来
    @interface ApplianceMaker     //定义注解
    {
     //定义注解元素,都有默认值
     public String type() default "电视机";
     public String id() default "001";
     public String maker() default "TCL有限公司";
     public String address() default "广东省惠州市";
    }

    @Retention(RetentionPolicy.RUNTIME)
    @interface ApplianceSaler {
     public String name() default "京东";
     public String id() default "001";
     public String address() default "北京";

    }

    @Retention(RetentionPolicy.RUNTIME)
    @interface AppliancePrice{
     //注解元素只有一个,名为value
     public int value() default 1200;
    }

    class Appliance{
     //为域maker加注解,给部分元素赋值,其余使用默认值
     //如果注解元素都用默认值,则直接写@ApplianceMaker
     @ApplianceMaker(type="电脑",id="201")
     public String maker;
     
     @ApplianceSaler(name="苏宁",id="222",address="南京")
     public String saler;      //域有注解
     
     @AppliancePrice(999)     //也可以写成"value=999",因为只有一个,此处只写出值即可
     public int price;        //域有注解
     
     public void setMaker(String m) {
      maker = m;
     }
     
     public String getMaker() {
      return maker;
     }
     
     public void setSaler(String saler) {
      this.saler = saler;
     }
     
     public String getSaler() {
      return saler;
     }
     
     public void setPrice(int price) {
      this.price = price;
     }
     
     public int getPrice() {
      return price;
     }
    }


    public class D144_1_Test {
     public static void main(String[] args) {
      System.out.println(readAnnotation(Appliance.class));
     }
     
     //读取注解信息
     private static String readAnnotation(Class aClass) {
      String maker="制造商:";
      String saler="销售商:";
      String price="价格:";
      
      Field fields[] = aClass.getDeclaredFields();   //获取Appliance类的所有字段
      
      for(Field aField:fields) {
       //对每一个字段判断其注解类型
       if(aField.isAnnotationPresent(ApplianceMaker.class)) {
        ApplianceMaker aMaker;         //声明一个注释变量
        //调用getAnnotation()方法获得在aField域上的注解“实例”
        aMaker = (ApplianceMaker)aField.getAnnotation(ApplianceMaker.class);
        maker+=aMaker.type() + " ";  //获取type元素的值
        maker+=aMaker.id() + " ";
        maker+=aMaker.maker() + " ";
        maker+=aMaker.address() + " ";
       }else if(aField.isAnnotationPresent(ApplianceSaler.class)) {
        //字段的注解是ApplianceSaler类型
        ApplianceSaler aSaler;
        aSaler=(ApplianceSaler)aField.getAnnotation(ApplianceSaler.class);
        saler+=aSaler.name()+" ";
        saler+=aSaler.id() +" ";
        saler+=aSaler.address() + " ";
       }else if(aField.isAnnotationPresent(AppliancePrice.class)) {
        AppliancePrice thePrice;
        thePrice = (AppliancePrice)aField.getAnnotation(AppliancePrice.class);
        price+=thePrice.value();
       }
            
      }
      return maker+saler+price;
     }
    }

    二、反射

    • 定义:程序可以访问、检测和修改它本身状态或者行为的一种能力
    • 作用:使程序代码能够得到装载到Java虚拟机中的类的内部信息
    • Java语言的反射机制:对于任何一个对象,都能够知道这个对象所在的类的所有方法和属性,都能够调用它的任意一个方法和访问属性
    • 反射机制的功能:(1)运行时判断任意一个对象所属的类;(2)运行时构造人一个类的对象;(3)运行时判断人一个类所具有的成员变量和方法;(4)生成动态代理。

    1.反射类的内容

    • 包括java.lang.Class类和java.lang.reflect包中的Field类、Constructor类、Method类和Array类
    • 接下来一一介绍

    2.Class类

    • 该类的实例表示正在运行的Java应用程序中的类和接口,它是Java反射的基础,对于任何一个类,首先要产生一个Class对象,然后才可以通过Class类获得其他信息。

    3.Field类

    • 该类提供有关类和接口的单个字段的信息以及对它的动态访问权限,反射的字段可能是一个类(静态)字段或者实例字段,该类封装了反射类的属性。

    4.Method类

    • 该类提供了关于类和接口上单独某个方法的信息,该方法可能时类方法或者实例方法(包括抽象方法)。该类是用来封装反射类的方法。

    5.Constructor类

    • 该类提供了关于类的单个构造方法的信息以及对它的访问权限,该类封装了反射类的构造方法

    6.Array类

    • 该类提供了动态创建和访问Java数组的方法,它提供的方法都是静态方法。

    三、讲解Class类

    • 获取Class对象的三种方式
    Object obj = new Object();
    Class c1 = obj.getClass();//通过Object类中的getClass()方法来获取Class对象

    class c2 = Class.forName("java.lang.Integer");
    //通过Class类的静态方法forName()来获取Class类的对象
    //方法中的参数必选是类或者接口的全名,注意要捕捉ClassNotFoundException

    Class c3 = Integer.class;//通过类名直接获取
    • Class类的常用方法
    类型 方法 说明
    Class forName(String className) 返回指定字符串名的类或者接口的Class类对象
    String getName() 返回此Class对象所表示的实体的全限定名
    Constructor getConstructor(Class.. parameterTypes) 返回此Class对象所表示的实体的指定public构造方法
    Constructor[] getConstructor() 返回所有的public构造方法
    Constructor getDeclaredConstructor(Class.parameterTypes) 返回Class类对象所表示的实体的指定构造方法
    Constructor[] getDeclaredConstructors() 返回所有的构造方法
    Annotation[] getDeclardAnnotations() 返回此元素上的所有的注解
    Field getField() 返回此Class对象所表示的类或者接口指定的public字段
    Field[] getFields() ...............实体的所有的public字段
    Field[] getDeclaredFields(String name) .......实体的所有字段
    Class[] getInterface() .......类或者接口实现的所有接口Class列表
    Method getMethod(String name,Class...paramterTypes) 返回指定的方法,name时指定的方法的名称,parametersTypes是指定方法的参数数据类型
    package com.bjpowernode.java_learning;
    import java.lang.reflect.*;


    public class D144_4_ClassTest {
     public static void main(String[] args) {
      try {
       //获取指定类的Class对象
       Class c = Class.forName("java.util.Date");
       //获取类的包信息
       Package p = c.getPackage();
       //包名
       String pname = p.getName();
       System.out.println("Date类包信息:"+p);
       System.out.println("Date类包名"+pname);
       //获取类的修饰符
       int m = c.getModifiers();
       String str = Modifier.toString(m);
       System.out.println("Date的修饰符:"+str);
       System.out.println("Date类名:"+c.getName());
       
       //获取Date类的字段
       Field[] f = c.getDeclaredFields();
       System.out.println("---循环输出Date类中的字段名---");
       for(Field field:f) {
        System.out.print(field.getName() + " ");
       }
       System.out.println();
       
       //获取类的构造方法
       Constructor[] con = c.getDeclaredConstructors();
       System.out.println("--循环输出Date类中的构造方法信息---");
       for(Constructor cc:con) {
        System.out.println(cc.getName() + "的修饰符:"+Modifier.toString(cc.getModifiers()));
        Parameter[] ps = cc.getParameters();
        System.out.println(cc.getName() + "的参数:");
        for(Parameter pp :ps) {
         System.out.print(pp.getName() + " ");
        }
        System.out.println();
       }
       
       
       
       
      }catch(ClassNotFoundException e) {
       e.printStackTrace();
      }
     }

    }
    144.1
    144.1

    四、源码:

    • D144_1_Test.java
    • D143_2_SubClass.java
    • D143_3_Test.java
    • D144_4_ClassTest.java
    • https://github.com/ruigege66/Java/blob/master/D144_1_Test.java
    • https://github.com/ruigege66/Java/blob/master/D143_2_SubClass.java
    • https://github.com/ruigege66/Java/blob/master/D143_3_Test.java
    • https://github.com/ruigege66/Java/blob/master/D144_4_ClassTest.java
    • https://github.com/ruigege66/Java/tree/master/ibank
    • CSDN:https://blog.csdn.net/weixin_44630050
    • 博客园:https://www.cnblogs.com/ruigege0000/
    • 欢迎关注微信公众号:傅里叶变换,个人账号,仅用于技术交流
    • 1000.0
      1000.0
  • 相关阅读:
    Sudoku POJ 2676 [dfs]
    a>b和(*a).b
    lowbit()操作
    Anniversary party HDU 1520树形dp
    Lifting the Stone HDU 1115 求多边形的重心
    Boolean Expressions POJ 2106 【递归】
    Shaolin HDU 4585 STL map||Treap树
    取石子游戏 HDU 1527 威佐夫游戏
    A Simple Problem with Integers POJ 3468 区间修改线段树lazy—tag大法
    社会性网络软件SNS 帮助你认识比尔盖茨 java程序员
  • 原文地址:https://www.cnblogs.com/ruigege0000/p/13800493.html
Copyright © 2011-2022 走看看