-
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() + "\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();
}
}
}
四、源码:
-
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/p/13800493.html
最新更新
带有参数的装饰器
类装饰器
django中的auth模块与admin后台管理
python的日期处理
字符串常用方法
基本数据类型概述
python-map()函数基本用法
python带你实现任意下载AcFun视频数据~
bbs项目之注册功能
变量的定义和使用
三大常用数据库事务详解之三:事务运行
三大常用关系型数据库事务详解之二:基
三大关系型数据库事务详解之一:基本概
MongoDB常用命令(2)
MongoDB基本介绍与安装(1)
SQLServer触发器调用JavaWeb接口
SQL Server索引的原理深入解析
SqlServer2016模糊匹配的三种方式及效率问题
SQL中Truncate的用法
sqlserver 多表关联时在where语句中慎用tri
VB.NET中如何快速访问注册表
ASP.NET中图象处理过程详解
Vue(1)Vue安装与使用
JavaScript 语言入门
js将一段字符串的首字母转成大写
纯原生html编写的h5视频播放器
H5仿原生app短信验证码vue2.0组件附源码地
TypeScript(4)接口
TypeScript(3)基础类型
TypeScript(2)WebStorm自动编译TypeScript配置