什么是注解?
内置注解
元注解
// 定义一个注解
// 定义一个注解
@Target(value = { ElementType.METHOD, ElementType.TYPE }) // 使用范围
@Retention(value = RetentionPolicy.RUNTIME) // 生效范围
@Documented // 表示是否将我们的注解生成在JAVADOC中
@Inherited // 子类可以继承父类的注解
public @interface MyAnnotaion {
// 注解的参数: 参数类型 + 参数名 +() default 默认值 使用注解时,如果不传就为默认值
String value() default "";
// int id() default 0;
// String[] sole() default {};
}
ElementType 范围:
@Target(value = { ElementType.METHOD, ElementType.TYPE }) // 多个一起使用时
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
反射
类加载机制
什么时候会发生类初始化
获得类的信息
public static void main(String[] args)
throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException {
Class<?> c1 = Class.forName("com.java.reflection.Student");
// 获得类的名字
System.out.println(c1.getName()); // com.java.reflection.Student
System.out.println(c1.getSimpleName()); // Student
// 获得类的属性
System.out.println("======================================================");
Field[] fields = c1.getFields(); // 只能获取被public 修饰的属性
System.out.println(Arrays.toString(fields)); // []
Field[] declaredFields = c1.getDeclaredFields(); // 获取全部属性
System.out.println(Arrays.toString(declaredFields)); // [private java.lang.String
// com.java.reflection.Student.name,
// private int com.java.reflection.Student.id....
// Field field = c1.getField("id"); // 获取指定属性 只限于public
// System.out.println(field);
Field declaredField = c1.getDeclaredField("id"); // 获取指定属性
System.out.println(declaredField);
// 获得类的方法
System.out.println("======================================================");
Method[] methods = c1.getMethods(); // 获得本类以及父类的所有public 方法
for (Method m : methods) {
System.out.println(m);
}
Method[] declaredMethods = c1.getDeclaredMethods(); // 获取本来全部
// 获得指定方法
Method method = c1.getMethod("getName", null);
Method method2 = c1.getMethod("setName", String.class); // (方法名字,参数类型)
System.out.println(method);
System.out.println(method2);
// 获得指定构造器
Constructor<?>[] constructors = c1.getConstructors();
Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
Constructor<?> constructor = c1.getConstructor(String.class, int.class, int.class);
System.out.println(constructor);
}
有了Class对象 能做什么?
public static void main(String[] args) throws Exception {
// 获得Class 对象
Class<?> c1 = Class.forName("com.java.reflection.Student");
// 构造一个对象
Student newInstance = (Student) c1.newInstance(); // 本质是调用了类的无参构造器
// 通过有参构造器创建对象
Constructor<?> constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
Student newInstance2 = (Student) constructor.newInstance("小红", 15, 15);
System.out.println(newInstance2);
// 通过反射调用普通方法一
Student student = (Student) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(student, "Lang"); // invoke 执行 (执行对象,参数);
System.out.println(student);
// 通过反射调用普通方法二
Student stu = (Student) c1.newInstance();
Method print = c1.getDeclaredMethod("print", int.class, int.class); // (方法名称,参数) 参数为空就传入null
print.setAccessible(true); // 不能直接操作私有方法,我们需要关闭程序的安全检测 。默认false
int invokeResult = (int) print.invoke(stu, 1, 2); // 方法 有返回值时就正常返回 无返回值则返回null
System.out.println(invokeResult);
System.out.println("================================");
// 通过反射操作属性
System.out.println("============");
Student student2 = (Student) c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true); // 不能直接操作私有属性,我们需要关闭程序的安全检测 。默认false
name.set(student2, "Lang");
System.out.println(student2);
}
性能对比分析
public static void test1() {
User user = new User();
long begin = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getAge();
}
long end = System.currentTimeMillis();
System.out.println("普通方式 用时 :" + (end - begin) + "ms");
}
public static void test2() throws Exception {
Class<?> c1 = Class.forName("com.java.reflection.User");
User user = (User) c1.newInstance();
Method method = c1.getDeclaredMethod("getAge", null);
long begin = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
method.invoke(user, null);
}
long end = System.currentTimeMillis();
System.out.println("反射方式 用时 :" + (end - begin) + "ms");
}
public static void test3() throws Exception {
Class<?> c1 = Class.forName("com.java.reflection.User");
User user = (User) c1.newInstance();
Method method = c1.getDeclaredMethod("getAge", null);
method.setAccessible(true); // 关闭安全检查
long begin = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
method.invoke(user, null);
}
long end = System.currentTimeMillis();
System.out.println("关闭安全检查反射方式 用时 :" + (end - begin) + "ms");
}
反射操作泛型
// 通过反射获取泛型
public class Test5 {
public void test01(Map<String, User> map, List<User> list) {
System.out.println("test01");
}
public Map<String, User> test02() {
System.out.println("test02");
return null;
}
public static void main(String[] args) throws Exception {
// 获取参数泛型类型
Method method = Test5.class.getMethod("test01", Map.class, List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes(); // 获取参数泛型类型
for (Type g : genericParameterTypes) {
System.out.println(g); // java.util.Map<java.lang.String, com.java.reflection.User>
// java.util.List<com.java.reflection.User>
if (g instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) g).getActualTypeArguments();
for (Type a : actualTypeArguments) {
System.out.println(a);
}
}
}
System.out.println("---");
// 获取方法返回值泛型类型
Method method1 = Test5.class.getMethod("test02", null);
Type returnType = method1.getGenericReturnType(); // 获取返回值泛型类型
if (returnType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
for (Type a : actualTypeArguments) {
System.out.println(a);
}
}
}
}
反射获取注解信息
案例:
实体类:
@TableLang("table_Teacher")
class Teacher {
@FieldLang(columnName = "t_name", type = "varchar", length = 25)
private String name;
@FieldLang(columnName = "t_age", type = "int", length = 3)
private Integer age;
@FieldLang(columnName = "t_id", type = "int", length = 15)
private Long id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
自定义注解:
// 自定义注解-类注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableLang {
String value();
}
// 自定义注解-字段注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldLang {
String columnName();
String type();
int length();
}
public static void main(String[] args) throws Exception {
Class<?> c1 = Class.forName("com.java.reflection.Teacher");
// 获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation a : annotations) {
System.out.println(a);
}
// 获得注解的值
TableLang annotation = c1.getAnnotation(TableLang.class);
String value = annotation.value();
System.out.println(value);
// 获得类指定注解
Field field = c1.getDeclaredField("name");
FieldLang fieldLang = field.getAnnotation(FieldLang.class);
System.out.println(fieldLang.columnName());
System.out.println(fieldLang.type());
System.out.println(fieldLang.length());
}