注解与反射
注解
Annotation是从JDK5.0开始引进的新技术
Annotation的作用:
1. 不是程序本身,可以对程序做出解释
2. 可以被其他程序读取
Annotation的格式:
- 注释是以"@注释名"在代码中存在的,还可以添加一些参数值,例如@SuppressWarnings(value=“unchecked”)
Annotation在哪里使用
可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问
元注解
-
元注解的作用就是负责注解其他注解,java中定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型的说明
-
这些类型和他们所支持的类在java.lang.annotation包中可以找到(@Target,@Retention,@Documented,@Inherited)
@Target:用于描述注解的使用范围(即:被描述的注解可以放在什么地方)
@Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(source<class<runtime)
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
public class Test01 {
@MyAnnotation
public void test(){
}
}
//Target 表示我们的注解可以在哪些地方使用
@Target(value = {ElementType.METHOD})
//Rentention表示注解在什么地放才有效
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
//表示子类可以继承父类的注解
@Inherited
//Documented表示是否将我们的注解生成在javadoc中
@Documented
@interface MyAnnotation{
}
自定义注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IuI2HIGK-1641526042686)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210702144900431.png)]
//自定义注解
public class Test03 {
//注解可以显式赋值,如果没有默认值,我们必须给注解赋值
@MyAnnotation01(age = 18)
public void test02(){
}
@MyAnnotation3("秦疆")
public void test04(){
}
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation01{
//注解的参数:参数类型 + 参数名 ();
String name() default "";
int age() ;
int id() default -1;// 如果默认值为-1,代表不存在,indexof,如果找不到就返回-1
String[] schools() default {"西部开源","清华大学"};
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
//如果只有一个参数,默认创建的参数名为value()
String value();
}
反射
反射机制
//什么是反射
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
//通过反射获取类的class对象
Class c1 = Class.forName("com.byhz.reflection.User");
System.out.println(c1);
Class c2 = Class.forName("com.byhz.reflection.User");
Class c3 = Class.forName("com.byhz.reflection.User");
Class c4 = Class.forName("com.byhz.reflection.User");
//返回的hashcode为同一个,所以为同一个类
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
//实体类
class User{
private String userName;
private int id;
private int age;
public User() {
}
public User(String userName, int id, int age) {
this.userName = userName;
this.id = id;
this.age = age;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
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;
}
}
获取Class类的实例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBFs880c-1641526042691)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210702162117271.png)]
测试Class类的创建方式有哪些
//测试Class类的创建方式有哪些
public class Test02 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是:" + person.name);
//方式一对象名.getClass获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//方式二Class.forName(类的路径)获得
Class c2 = Class.forName("com.byhz.reflection.Student");
System.out.println(c2.hashCode());
//类名.class获得类
Class c3 = Student.class;
System.out.println(c3.hashCode());
//获得父类类型
Class c4 = c3.getSuperclass();
System.out.println(c4);
}
}
class Person{
public String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name = "老师";
}
}
所有类型的Class对象
public class Test03 {
public static void main(String[] args) {
Class c1 = Object.class; //类
Class c2 = Comparable.class; //接口
Class c3 = String[].class; //一维数组
Class c4 = int[][].class; //二维数组
Class c5 = Override.class; //注解
Class c6 = ElementType.class; //枚举
Class c7 = Integer.class; //基本数据类型
Class c8 = void.class; //void
Class c9 = Class.class; //Class
//只要元素类型与维度一样,就是同一个class
int[] a = new int[10];
int[] b = new int[100];
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
//结果
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
356573597
356573597
类加载内存分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWNRtcX1-1641526042692)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210702165004314.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GwUNYuey-1641526042694)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705112623066.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bnMlRSET-1641526042696)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705112703020.png)]
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取 系统类加载器的父类加载器 --> 扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
//获取扩展类加载器的父类加载器---> 根加载器
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
//测试当前类是哪个加载器加载的
ClassLoader classLoader = Class.forName("com.byhz.reflection.Test04").getClassLoader();
System.out.println(classLoader);
//测试jdk内置的类是谁加载的
classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);
//如何获得系统类加载器可以加载的路径
String property = System.getProperty("java.class.path");
System.out.println(property);
/**
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;
* C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;
* D:\IdeaProjects\practiceFFmpeg\target\classes;
* D:\IdeaProjects\practiceFFmpeg\src\main\java\lib\commons-io-2.10.0.jar;
* C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar
*/
}
}
获取类运行时结构
//获得类得信息
public class Test05 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.byhz.reflection.User");
//获得类得名字
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
/**
* printResult
* com.byhz.reflection.User
* User
*/
//获得类得属性
System.out.println("==========================");
Field[] fields = c1.getFields();//只能找到public属性
System.out.println(fields);
fields = c1.getDeclaredFields();//找到全部属性
for (Field field : fields) {
System.out.println(field.getName());
}
//获得指定属性的值
Field name = c1.getDeclaredField("userName");
System.out.println(name);
//获得类的方法
System.out.println("==========================");
Method[] methods = c1.getMethods();//获取本类或者父类的全部public属性
for (Method method : methods) {
System.out.println("getMethods:" + method);
}
/**
* 本类和父类的public方法
* getMethodspublic int com.byhz.reflection.User.getId()
* getMethodspublic java.lang.String com.byhz.reflection.User.getUserName()
* getMethodspublic int com.byhz.reflection.User.getAge()
* getMethodspublic void com.byhz.reflection.User.setAge(int)
* getMethodspublic void com.byhz.reflection.User.setId(int)
* getMethodspublic void com.byhz.reflection.User.setUserName(java.lang.String)
* getMethodspublic final void java.lang.Object.wait() throws java.lang.InterruptedException
* getMethodspublic final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
* getMethodspublic final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
* getMethodspublic boolean java.lang.Object.equals(java.lang.Object)
* getMethodspublic java.lang.String java.lang.Object.toString()
* getMethodspublic native int java.lang.Object.hashCode()
* getMethodspublic final native java.lang.Class java.lang.Object.getClass()
* getMethodspublic final native void java.lang.Object.notify()
* getMethodspublic final native void java.lang.Object.notifyAll()
*/
System.out.println("==========================");
methods = c1.getDeclaredMethods();//获取本类的所有方法
for (Method method : methods) {
System.out.println("getDeclaredMethods:" + method);
}
/**
* 获取本类的所有方法
* getDeclaredMethodspublic int com.byhz.reflection.User.getId()
* getDeclaredMethodspublic java.lang.String com.byhz.reflection.User.getUserName()
* getDeclaredMethodspublic int com.byhz.reflection.User.getAge()
* getDeclaredMethodspublic void com.byhz.reflection.User.setAge(int)
* getDeclaredMethodspublic void com.byhz.reflection.User.setId(int)
* getDeclaredMethodspublic void com.byhz.reflection.User.setUserName(java.lang.String)
*/
System.out.println("=======================================");
//获得指定方法
Method getUserName = c1.getMethod("getUserName", null);
Method setUserName = c1.getMethod("setUserName", String.class);
System.out.println(getUserName);
System.out.println(setUserName);
System.out.println("=======================================");
//获得指定指定得构造器
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
/**
* public com.byhz.reflection.User()
* public com.byhz.reflection.User(java.lang.String,int,int)
*/
System.out.println("============================================");
constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
/**
* public com.byhz.reflection.User()
* public com.byhz.reflection.User(java.lang.String,int,int)
*/
System.out.println("============================================");
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("指定构造器为:" + declaredConstructor);
/**
* 指定构造器为:public com.byhz.reflection.User(java.lang.String,int,int)
*/
}
}
动态创建对象执行方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PbHnCtYD-1641526042700)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705150018816.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I6zPRH8Y-1641526042702)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705150048860.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GsbMm4hi-1641526042705)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705150127510.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tCSh3yht-1641526042707)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705150229274.png)]
//动态创建对象,通过反射public class Test06 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //获得Class对象 Class clazz = Class.forName("com.byhz.reflection.User"); //构造一个对象 User user = (User)clazz.newInstance();//本质上是调用了无参构造器 System.out.println(user.toString()); //通过构造器创建对象 Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class, int.class); User instance = (User)constructor.newInstance("李叶琦", 1, 23); System.out.println(instance); //通过反射调用普通方法 User person = (User)clazz.newInstance(); //通过反射获取方法 Method setUserName = clazz.getDeclaredMethod("setUserName", String.class); //激活 //(对象,"方法的值") setUserName.invoke(person,"狂神"); System.out.println(person.getUserName()); //通过反射操作属性 User person1 = (User)clazz.newInstance(); Field userName = clazz.getDeclaredField("userName"); System.out.println("================================="); //不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true) userName.setAccessible(true); userName.set(person1,"狂神2"); System.out.println(person1.getUserName()); }}
性能对比分析
//分析性能问题public class Test07 { //普通方式调用 public static void test01(){ User user = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { user.getUserName(); } long endTime = System.currentTimeMillis(); System.out.println("普通方式执行10亿次:" + (endTime - startTime)); } //反射调用 public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getUserName = c1.getDeclaredMethod("getUserName", null); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getUserName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("反射方式执行10亿次:" + (endTime - startTime) + "ms"); } //反射方式调用 关闭检测 public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getUserName = c1.getDeclaredMethod("getUserName", null); getUserName.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getUserName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("反射方式关闭检测执行10亿次:" + (endTime - startTime) + "ms"); } public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { test01(); test02(); test03(); /** * 普通方式执行10亿次:5 * 反射方式执行10亿次:4716ms * 反射方式关闭检测执行10亿次:1899ms */ }}
获取注解信息
//联系反射操作注解public class Test09 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("com.byhz.reflection.Student2"); //通过反射获取注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获得注解value的值 TableLi tableLi = (TableLi)c1.getAnnotation(TableLi.class); String value = tableLi.value(); System.out.println(value); System.out.println("=============================================== "); Field name = c1.getDeclaredField("id"); FieldKuang annotation = name.getAnnotation(FieldKuang.class); System.out.println(annotation.columnName()); System.out.println(annotation.length()); System.out.println(annotation.type()); }}@TableLi("db_student")class Student2{ @FieldKuang(columnName = "db_id",type = "int",length = 10 ) private int id; @FieldKuang(columnName = "db_age",type = "int",length = 10) private int age; @FieldKuang(columnName = "db_name",type = "varchar",length = 3) private String name; public Student2() { } public Student2(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 "student2{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; }}//类名的注解@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@interface TableLi{ String value();}//属性的注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface FieldKuang{ String columnName(); String type(); int length();}