一、定义注解

  • 使用前提:使用@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() + "\n";
   }else if(aField.isAnnotationPresent(ApplianceSaler.class)) {
    //字段的注解是ApplianceSaler类型
    ApplianceSaler aSaler;
    aSaler=(ApplianceSaler)aField.getAnnotation(ApplianceSaler.class);
    saler+=aSaler.name()+" ";
    saler+=aSaler.id() +" ";
    saler+=aSaler.address() + "\n";
   }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
posted on 2020-10-12 00:14  心悦君兮君不知-睿  阅读(182)  评论(0编辑  收藏  举报