什么是注解(Annotation)
- 不是程序本身,可以对程序作出解释
- 可以被其他程序(比如:编译器等)读取
- 可以附加在package,class,method和field等上面,相当于给他们添加了额外的辅助信息
- 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
- 如果注解中只有一个参数,通常参数名取为value;在使用注解传参的时候可以省略”value=”
元注解
- @Target(用于描述注解使用的范围)
- @Retention(表示需要在什么级别保存该注释信息,用于描述注解的生命周期)
- @Documented
- @Inherited
/**
* 自定义注解
* @author L J
*/
//表示该注解可以用在方法上面,还可以用在类上面
@Target(value={ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LjAnnotation {
//注解的参数
String studentName() default "";
int age() default 0;
int id() default -1; //如果没有传参数,表示不存在
}
//测试自定义注解
@LjAnnotation(id=1, age=12, studentName="小明")
public class LjAnnotationTest {
@LjAnnotation
public void test() {
}
}
反射读取注解信息
/**
* 用于对象关系映射
* 表示类和表结构对应
* @author L J
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
//表名
String value();
}
/**
* 用于对象关系映射
* 表示属性和字段对应
* @author L J
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LField {
//字段名
String columnName();
//字段类型
String type();
//字段长度
int length();
}
//学生类
@Table("tb_student")
public class Student {
@LField(columnName="id", type="int", length=10)
private int id;
@LField(columnName="sname", type="varchar", length=10)
private String studentName;
@LField(columnName="age", type="int", length=3)
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
* 使用反射读取注解的信息
* 模拟处理注解信息的流程
* @author L J
*/
public class AnnotationDemo {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.belief.annotation.Student");
//获得所有修饰类的有效注解
Annotation[] annotation = clazz.getAnnotations();
for (Annotation a : annotation) {
System.out.println(a);
}
//获得修饰类的指定的注解
Table t = (Table) clazz.getAnnotation(Table.class);
System.out.println(t.value()); //tb_student
//获得类的属性的注解
Field f = clazz.getDeclaredField("studentName");
LField field = f.getAnnotation(LField.class);
//sname-->varchar-->10
System.out.println(field.columnName() + "-->" + field.type() + "-->" + field.length());
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射
//用户类
public class User {
private Integer id;
private Integer age;
private String uname;
public User() {
}
public User(Integer id, Integer age, String uname) {
this.id = id;
this.age = age;
this.uname = uname;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
}
Class对象的获取方式:
/**
* 测试java.lang.Class对象的获取方式
* @author L J
*/
@SuppressWarnings("all")
public class ClassGetTest {
public static void main(String[] args) {
String path = "com.belief.reflection.User";
try {
//一个类被加载后,JVM会创建一个对应该类的Class对象
//类的整个结构信息会放到对应的Class对象中
Class clazz = Class.forName(path);
System.out.println(clazz); //class com.belief.reflection.User
Class strClazz = String.class;
//对象.getClass()方法也可以获得对应类的Class对象
Class strClazz2 = path.getClass();
System.out.println(strClazz == strClazz2); //true
//基本数据类型获取Class对象的方式
Class intClazz = int.class;
System.out.println(intClazz);
//数组的Class对象和维数有关
int[] arr1 = new int[1];
int[] arr2 = new int[2];
int[][] arr3 = new int[1][2];
System.out.println(arr1.getClass() == arr2.getClass()); //true
System.out.println(arr1.getClass().hashCode()); //1383884648
System.out.println(arr2.getClass().hashCode()); //1383884648
System.out.println(arr3.getClass().hashCode()); //1701381926
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
获取类的信息:
/**
* 获取类的信息(类的名字、属性、方法、构造器等)
* @author L J
*/
@SuppressWarnings("all")
public class ReflectionDemo {
public static void main(String[] args) {
String path = "com.belief.reflection.User";
try {
Class clazz = Class.forName(path);
//获取类的名字
System.out.println(clazz.getName()); //获取包名+类名 com.belief.reflection.User
System.out.println(clazz.getSimpleName()); //获取类名 User
//获取属性信息
//Field[] fields = clazz.getFields(); //只能获得public的属性
Field[] fields = clazz.getDeclaredFields(); //获得所有的属性
Field f = clazz.getDeclaredField("uname"); //获得单个属性
for(Field temp : fields) {
System.out.println("属性:" + temp);
}
//获得方法信息
Method[] methods = clazz.getDeclaredMethods();
Method m1 = clazz.getDeclaredMethod("getUname", null);
//如果方法有参数,则必须传递参数类型对应的Class对象
Method m2 = clazz.getDeclaredMethod("setUname", String.class);
for (Method method : methods) {
System.out.println("方法:" + method);
}
//获得构造器信息
Constructor[] constructors = clazz.getDeclaredConstructors();
for(Constructor temp : constructors) {
System.out.println("构造器:" + temp);
}
Constructor c = clazz.getDeclaredConstructor(Integer.class, Integer.class, String.class);
System.out.println("获得构造器:" + c);
} catch (Exception e) {
e.printStackTrace();
}
}
}
通过反射API动态的操作:构造器、方法、属性
/**
* 通过反射API动态的操作:构造器、方法、属性
* @author L J
*/
@SuppressWarnings("all")
public class reflectionDemo2 {
public static void main(String[] args) {
String path = "com.belief.reflection.User";
try {
Class<User> clazz = (Class<User>) Class.forName(path);
//通过反射API调用构造方法,构造对象
//其实是调用了User的无参构造方法
User user = clazz.newInstance();
System.out.println(user);
//调用有参构造器
Constructor<User> c = clazz.getDeclaredConstructor(Integer.class, Integer.class, String.class);
User user2 = c.newInstance(1001, 18, "小明");
System.out.println(user2.getUname()); //小明
//通过反射调用普通方法
User user3 = clazz.newInstance();
Method method = clazz.getDeclaredMethod("setUname", String.class);
method.invoke(user3, "隔壁老王");
System.out.println(user3.getUname()); //隔壁老王
//通过反射操作属性
User user4 = clazz.newInstance();
Field f = clazz.getDeclaredField("uname");
f.setAccessible(true);
f.set(user4, "哈哈");
System.out.println(f.get(user4)); //哈哈
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用反射操作泛型:
/**
* 使用反射操作泛型
* @author L J
*/
@SuppressWarnings("all")
public class ReflectionDemo3 {
public static void main(String[] args) {
try {
// 获得指定方法的参数泛型信息
Method m = ReflectionDemo3.class.getMethod("test01", Map.class,
List.class);
Type[] t = m.getGenericParameterTypes();
for (Type paramType : t) {
System.out.println(paramType);
if (paramType instanceof ParameterizedType) {
Type[] genericTypes = ((ParameterizedType) paramType)
.getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("泛型类型:" + genericType);
}
}
}
// 获得指定方法返回值泛型类型
Method m2 = ReflectionDemo3.class.getMethod("test02", null);
Type returnType = m2.getGenericReturnType();
System.out.println(returnType);
if (returnType instanceof ParameterizedType) {
Type[] genericTypes = ((ParameterizedType) returnType)
.getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("泛型类型:" + genericType);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void test01(Map<String, User> map, List<User> list) {
System.out.println("ReflectionDemo3.test01()");
}
public Map<Integer, User> test02() {
System.out.println("ReflectionDemo3.test02()");
return null;
}
}