注解与反射05
5.性能比对分析
// 分析性能问题
public class Test10 {
// (1) 普通方法调用
public static void method1(){
User user = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法执行10亿次:" + (endTime - startTime) + "ms");
}
// (2) 反射方法调用
public static void method2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class c1 = Class.forName("com.qinggangqiang.reflection.User");
Object o = c1.newInstance();
User user = (User) o;
Method getName = c1.getDeclaredMethod("getName", null);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式执行10亿次:" + (endTime - startTime) + "ms");
}
// (3) 反射方法调用--关闭检测
public static void method3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c1 = Class.forName("com.qinggangqiang.reflection.User");
Object o = c1.newInstance();
User user = (User) o;
Method getName = c1.getDeclaredMethod("getName", null);
getName.setAccessible(true);// 关闭检测
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式--关闭检测执行10亿次:" + (endTime - startTime) + "ms");
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
method1();
method2();
method3();
}
}
执行结果
普通方法执行10亿次:3ms
反射方式执行10亿次:1248ms
反射方式--关闭检测执行10亿次:798ms
6.获取泛型信息
反射操纵泛型
Java
采用泛型擦除的机制来引入泛型,Java
中的泛型仅仅是给编译器javac
使用的,确保数据的安全性和免去强制类型转换问题,但是一旦编译完成,所有和泛型有关的泛型全部擦除(也就是JVM
的GC
机制–垃圾回收器进行擦除)。- 为了通过反射操作这些类型,
Java
新增了ParameterizedType
,GenericArrayType
,TypeVariable
和WildCardType
几种类型来代表不能被归一到Class 类中的类型但是又和原始类型齐名的类型。 ParameterizedType
:表示一种参数化类型,比如:Collection<String>
。GenericArrayType
:表示一种元素类型是参数化类型或者类型变量的数组类型。TypeVariable
:表示是各种类型变量的公共父接口。WildCardType
:表示代表一种通配符类型表达式。
// 通过反射获取泛型
public class Test11 {
public static 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 NoSuchMethodException {
// 反射最快的方法:通过类来获取
Method method = Test11.class.getMethod("test01", Map.class, List.class);
// 获得泛型的参数类型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("#"+genericParameterType);
// 进一步获取里面的类型
// 如果属于参数化类型:进行强转并获得真实类型
if (genericParameterType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("真实的参数类型:"+actualTypeArgument);
}
}
}
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
// 获取返回值类型
method = Test11.class.getMethod("test02", null);
Type genericReturnType = method.getGenericReturnType();
// 进一步获取里面的类型
// 如果属于参数化类型:进行强转并获得真实类型
if (genericReturnType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("--返回值:*真实的参数类型:"+actualTypeArgument);
}
}
}
}
执行结果
#java.util.Map<java.lang.String, com.qinggangqiang.reflection.User>
真实的参数类型:class java.lang.String
真实的参数类型:class com.qinggangqiang.reflection.User
#java.util.List<com.qinggangqiang.reflection.User>
真实的参数类型:class com.qinggangqiang.reflection.User
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
--返回值:*真实的参数类型:class java.lang.String
--返回值:*真实的参数类型:class com.qinggangqiang.reflection.User
7.获取注解信息
反射操作注解
getAnnotations
getAnnotation
练习
了解什么是ORM
?
Object relationship Mapping
–> 对象关系映射
- 类和表结构对应
- 属性和字段对应
- 对象和记录对应
注意:
要求:利用注解和反射完成类和表结构的映射关系
代码实战
// 练习反射操作注解
public class Test12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.qinggangqiang.reflection.Student2");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();// 获得全部注解
for (Annotation annotation : annotations) {
System.out.println("#"+annotation);
}
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
// 获得指定注解的 value 的值
DatabaseName databaseName = (DatabaseName) c1.getAnnotation(DatabaseName.class);
String value = databaseName.value();
System.out.println(value);
// 获得指定字段的注解
Field declaredField = c1.getDeclaredField("name");
FieldName annotation = declaredField.getAnnotation(FieldName.class);
System.out.println("获得指定字段的注解:");
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@Data
@DatabaseName("db_student")
class Student2{
@FieldName(columnName = "db_id",type = "int",length = 10)
private int id;
@FieldName(columnName = "db_age",type = "int",length = 10)
private int age;
@FieldName(columnName = "db_name",type = "varchar",length = 255)
private String name;
}
// 类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface DatabaseName{
String value();
}
// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldName{
String columnName();
String type();
int length();
}
执行结果
#@com.qinggangqiang.reflection.DatabaseName(value=db_student)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
db_student
获得指定字段的注解:
db_name
varchar
255
实际工作中的框架的底层大量使用了注解与反射,例如:jpa 就大量使用的反射操作注解!
执行结果
#@com.qinggangqiang.reflection.DatabaseName(value=db_student)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
db_student
获得指定字段的注解:
db_name
varchar
255
实际工作中的框架的底层大量使用了注解与反射,例如:jpa 就大量使用的反射操作注解!