Java注解和反射
@author:HB、ocean
@time:2020-3-20
本文目录:
Annotation 注解
Comment 注释
Reflection 反射
pojo entity 实体类
注解
什么是注解
- JDK5.0引入的技术
- 可以被其他程序如编译器读取
- 格式:@注释名(参数值)
- 注解可以检查和约束程序
内置注解
- @Overrid 方法重写
- @Deprecated 危险不鼓励的写法
- @SuppressWarnnings 抑制编译时警告信息(可传递定义好的参数:all、unchecked、value={“unckecked”,“deprecation”}等)
元注解
- @Traget 注解使用范围
- @Retention 注解生命周期·(SOURCE<CLASS<RUNTIME)
- @Document 包含javadoc中
- @Inherited 说明子类可以继承父类中注解
自定义注解
-
@interface 注解名
-
注解的参数:参数类型 + 参数名(); (可添加 default 默认值、只有一个参数使用value可省略,默认值为-1代表找不到返回-1)
// 自定义注解 @MyAnnotation(name = "田一百五十六",age = 18,schools = {"北京大学","TINGHUA"}) public void test() { } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation{ // 注解的参数:参数类型 + 参数名();; String name() default "李四"; int age() default 0; int id() default -1;// 如果默认值为-1,代表不存在 String[] schools(); }
反射
反射概述
- 动态语言与静态语言
- 动态语言:运行时可以改变其结构 Object-C、C#、JavaScript、PHP、Python等
- 静态语言:运行时结构不可变 Java、C、C++
- Java可以被称为“准动态语言”,有一定的动态性 反射机制
- JavaScript 程序运行后改变x值
function f() {
var x = "var a = 3;var b = 5;alert(a+b)";
eval(x)
}
- 反射机制允许程序在执行期间借助于Reflection API获得任何类的内部信息,并能操作任意对象内部属性与方法
Class c = Class.forName("java.lang.String")
- 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),对象包含完整类结构信息,通过对象可以看到类结构,称之为:反射(AOP动态代理)
- 优缺点
- 优:可以实现动态创建对象和编译,灵活性
- 缺:对性能有影响,基本上是解释操作,告诉JVM,JVM满足要求,慢于直接执行相应操作
反射相关主要API
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造器
- ……
Class类
Object 类定义了以下方法 返回Class类,反射的源头
public final Class getClass()
Class类常用方法
- static ClassforName(String name) 返回制定类名name的Class对象
- Object newInstance() 调用缺省构造参数,返回Class对象的一个实例
- getName() 返回此Class对象所表示的实体(类、接口、数组类或void)的名称
- Class getSuperClass() 返回当前Class对象的父类的Class对象
- Class[] getinterfaces() 返回当前Class对象的接口
- ClassLoader getClassLoader() 返回该类的类加载器
- Constructor[] getConstructors() 返回一个包含某些Constructor对象的数组
- Method getMethoed(String name,Class… T) 返回一个Method对象,此对象的形参类型为paramType
- Field[] getDeclareFields() 返回Field对象的一个数组
获取Class类的方法
-
已知具体的类 通过类的calss属性 安全可靠 性能高
Class c1 = Person.class;
-
已知某个类的实例 调用该实例的getClass方法
Class c2 = person.getClass();
-
已知一个类的全类名,且该类在类路径下 通过Class类静态方法forName() 肯能抛出异常 ClassNotFoundException .
Class c3 = Class.forName("java.lang.String");
-
内置基本数据类型 类名.TYPE
Class c4 = Integer.TYPE;
-
ClassLoader的使用
含有calss对象
Class c3 = Object.class; // 类
Class c4 = Comparable.class; // 接口
Class c5 = String[].class; // 一维数组
Class c6 = int[][].class; // 二维数组
Class c7 = Override.class; // 注解
Class c8 = ElementType.class; // 枚举
Class c9 = Integer.class; // 基本数据类型
Class c10 = void.class; // void
Class c11 = Class.class; // Class
类的加载过程
类的初始化
-
类的主动引用(一定会发生类的初始化)
- 虚拟机启动 先初始化main方法所在的类
- 通过new一个类的对象
- 调用类静态成员(除了final常量)和静态方法
- 通过反射 java.lang.reflect
-
类的被动引用(不会发生类的初始化)
-
当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量 不会导致子类初始化
-
通过数组定义类引用 不会触发此类的初始化(仅分配名字空间)
Son[] array = new Son[5];
-
引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池当中了)
-
类加载器
- 作用
获取系统的类加载器
// 获取系统的类加载器 sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
// 获取系统类加载器的父类加载器-->扩展类加载器 sun.misc.Launcher$ExtClassLoader@1b6d3586
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
// 获取系统类加载器的父类加载器-->根加载器(C/C++) 获取不到
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
// 测试当前类加载器是哪个类加载的
ClassLoader classLoader = Class.forName("com.hb.prc.BHprc2").getClassLoader();
System.out.println(classLoader);
// 测试JDK内置类 (根加载器)
classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);
// 获得类加载器可以加载的路径
System.out.println(System.getProperty("java.class.path"));
// 双亲委派机制 向上找包 保证安全性 没有才可以运行 自己写的包名
创建运行时类的对象
-
getName 与 getSimpleName
Simple获得的是类名 不加 则是全类名(含包名)
-
getFields 与 getDeclaredFields 与 getField 与 getDeclaredField
Declared 可以获得私有的字段 不加则只能获得public
-
getMethods 与 getDeclaredMethods 同理
获得本类与父类public方法 Declared获得本类所有方法
-
获取指定方法 getMethod 与 getDeclaredMethod 有参数因为方法的重载需要参数如:String.class
-
获取构造器 getConstructors 与 getDeclaredConstructors
-
获取指定构造器 getConstruor 参数如:String.class、int.class
动态创建对象执行方法
-
获取Class对象
-
getInstance()构造对象 调用无参构造器
-
通过构造器创建对象 c1.getDeclaredConstructor(String.class……).getInstance(“李四”……)
-
获取方法 getDeclaredMethod(setName,String.class)
激活 对象 方法的值 setName.invoke(user3,“李四”)
-
操作属性 需要设置 setAccessible(true) 关闭Java 语言访问检查
-
属性字段.set(名称)来进行赋值
-
setAccessible(true)可以提高反射的效率,私有成员可访问
-
System.currentTimeMillis() 获取系统时间
反射操作泛型
例如:
package com.hb.prc;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
// 通过反射获取泛型
public class BHprc6 {
// 泛型传参
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 void test03(int a) {
System.out.println("test03");
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = BHprc6.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);
}
}
}
method = BHprc6.class.getMethod("test02",null);
Type genericReturnType = method.getGenericReturnType();
System.out.println("返回类型"+genericReturnType);
if (genericReturnType instanceof ParameterizedType) {// 泛型参数类型属于参数化类型
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();// 获得真实类型
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("真实泛型信息"+actualTypeArgument);
}
}
method = BHprc6.class.getMethod("test03", int.class);
genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("普通参数"+genericParameterType);
}
}
}
反射操作注解
ORM—对象关系映射Object relationship Mapping
注解和反射完成类和表结构映射关系
package com.hb.prc;
import java.lang.annotation.*;
import java.lang.reflect.Field;
// 反射操作注解
public class BHprc7 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.hb.prc.Student");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("注解"+annotation);// 获取注解
}
// 获得注解的value值
Bhtable bhtable = (Bhtable)c1.getAnnotation(Bhtable.class);
String value = bhtable.value();
System.out.println("注解的value:"+value);
// 获得类指定的注解
Field name = c1.getDeclaredField("name");// 获取指定的属性
Bhfield annotation = name.getAnnotation(Bhfield.class);// 获取属性的注解
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
Field id = c1.getDeclaredField("id");// 获取指定的属性
annotation = id.getAnnotation(Bhfield.class);// 获取属性的注解
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
Field age = c1.getDeclaredField("age");// 获取指定的属性
annotation = age.getAnnotation(Bhfield.class);// 获取属性的注解
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@Bhtable("db_student")
class Student{
@Bhfield(columnName = "db_id",type = "int",length = 10)
private int id;
@Bhfield(columnName = "db_age",type = "int",length = 10)
private int age;
@Bhfield(columnName = "db_name",type = "varchar",length = 10)
private String name;
public Student() {
}
public Student(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
// 类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Bhtable {
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Bhfield{
String columnName();
String type();
int length();
}