Java注解与反射

注解

概念

也叫元数据,标签

注解和注释

注释:是写给程序员看的 帮助开发人员理解代码

注解:给java程序看的,帮助程序理解代码 也叫标签

学习注解的好处

1.使代码简洁、清爽

2.以后使用别人的注解(公司自己开发的框架 开源框架(Spring SpringMvc SpringBoot))

3.装逼… 一个注解完成一系列功能

4.分析别人代码

注解作用

1.生成文档

2.分析代码

3.校验

4.自定义注解可以根据情况添加功能

注解的使用(三要素)

1.拿到注解 (定义注解)

2.在适当位置使用 (作用范围)

3.完成某项功能

JDK四大内置注解

@Override 校验是否方法覆写

@deprecated 标记方法过时 过时的方法依然可以使用,但不建议

@SupperssWarings 抑制警告

@SafeVarargs 抑制堆污染警告 有了这个注解jvm就不会再去校验 比如定义泛型时传入类型不一致

元注解

是注解里面的注解,约束注解的范围,生命周期,生成文档,能够被子类方法

@Target 用来约束注解作用范围(类 方法 构造方法 字段)

@Retention 约束注解的生命周期(Java源文件 字节码文件 运行时)

@Documented 自定义注解的时候,使用此元注解,就会把自定义的注解一并生成到API中

@Inherited 自定义的注解使用了此元注解修饰,在类上使用自定义注解的时候 从这个类的子类上也能获取该注解的信息

自定义注解

1.作用范围

2.完成功能

语法

@Inherited 子类可以获得父类上面的注解信息

@Documented 生成API文档

@Retention 声明生命周期

@Target 指定作用范围 默认不指定范围的时候是全局都可以使用

public @interface 注解名{

}

反射

基本概念

通过字节码文件去获取到类中的信息(无论私有还是公有)

程序运行的时候动态地区获取到类中的相关信息

类中的信息:字段 方法 构造方法 注解

全限定名:包名.类名

优点:功能强大 灵活

缺点:破坏封装 效率较低

获取对象字节码文件

类:

1.类名.class 2.对象名.getClass() 3.Class.forName(全限定名:包名+类名)
接口:

1.接口名.class 2.Class.forName(全限定名:包名+类名)
数组:

1.对象名.getClass() 2.数组类型.class
基本数据类型

1.基本数据类型.class 2.对应包装类型.Type
Void:

类名.class

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.ifueen.classtest.reflect;

import static org.junit.Assert.*;

import java.util.Date;

import org.junit.Test;

/**
* @author admin
*获取字节码文件
*/
public class ByteCode {

@Test
public void test() throws Exception {

ByteCode byteCode = new ByteCode();
//通过类名.class获取
Class<ByteCode> b1 = ByteCode.class;
System.out.println(b1);
//通过对象名.getclass
Class<? extends ByteCode> class1 = byteCode.getClass();
System.out.println(class1);
//通过全限定名来获取
Class forName = Class.forName("com.ifueen.classtest.reflect.ByteCode");
System.out.println(forName);
//接口获取一:通过接口名.class获取
Class<MyInterface> m1 = MyInterface.class;
System.out.println(m1);
//通过全限定名获取接口的字节码文件
Class forName2 = Class.forName("com.ifueen.classtest.reflect.MyInterface");
System.out.println(forName2);
//数组获取一:通过对象名.getClass获取
int [] arr = new int[5];
Class<? extends int[]> class2 = arr.getClass();
System.out.println(class2);
//数组获取二:通过数组[].class获取
Class class3 = int[].class;
System.out.println(class3);
//基本数据类型获取一:通过类名.class
String name = "山泥若";
Class<String> class4 = String.class;
System.out.println(class4);
}

}

通过反射获取对象

如果是获取共有的不用设置访问权限 如果是私有的则需要设置访问权限
获取构造方法:
公共无参的: 字节码对象.newInstance 公共有参的: 字节码对象.getConstructor(参数的字节码);
获取方法: 字节码对象.getMethod(方法名称,参数字节码); 执行: 方法对象.invoke(对象,实际参数);
获取字段: 字节码对象.getFiled(字段名称); 设置值 :字段对象.set(对象,实际参数);
获取注解 : 字节码对象.getAnnotation(注解的字节码); 注解对象.对应的方法 获取值

Demo

自定义注解:MyAnnotation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.ifueen.classtest.reflect;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnnotation {
String star();
}

JavaBean类:MyTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.ifueen.classtest.reflect;

@MyAnnotation(star="我们分手吧")
public class MyTest {
public String name;
public Integer age;
private String str;
public MyTest() {
// TODO Auto-generated constructor stub
}
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;
}
private MyTest(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "MyTest [name=" + name + ", age=" + age + "]";
}
public MyTest(String name) {
super();
this.name = name;
}
public void eat(){
System.out.println("我要吃汉堡");
}
private void show(String name){
System.out.println("这是一个结婚的车队"+name);
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}

}

测试类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package com.ifueen.classtest.reflect;

import static org.junit.Assert.*;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;import java.util.Set;

import org.junit.Test;

import com.sun.org.apache.bcel.internal.generic.NEW;

public class ReflectTest {

/**
* 测试反射
* @throws Exception
*/
@Test
public void test() throws Exception {
//拿到字节码文件
Class<MyTest> forName = (Class<MyTest>) Class.forName("com.ifueen.classtest.reflect.MyTest");
//调用无参构造方法
/*MyTest m1 = forName.newInstance();
m1.setName("人民不需要自由");
m1.setAge(34);
System.out.println(m1);*/

//调用有参构造方法
/*Constructor<MyTest> c1 = forName.getConstructor(String.class);
MyTest m2 = c1.newInstance("给我吃一口好不好");
System.out.println(m2);*/

//调用私有化的构造方法
/*Constructor<MyTest> c2 = forName.getDeclaredConstructor(String.class,Integer.class);
//设置权限
c2.setAccessible(true);
MyTest m2 = c2.newInstance("你在干什么啊",65);
System.out.println(m2);*/

}

/**
* 通过反射获取方法
* @throws Exception
*/
@Test
public void testmethod() throws Exception{

//通过反射调用公有方法
Class<MyTest> forName = (Class<MyTest>) Class.forName("com.ifueen.classtest.reflect.MyTest");
/*Method method = forName.getMethod("eat");
MyTest m1 = forName.newInstance();
//调用方法
method.invoke(m1);*/
//私有方法
/*Method method = forName.getDeclaredMethod("show", String.class);
//设置权限
method.setAccessible(true);
MyTest m2 = forName.newInstance();
method.invoke(m2, "王小波");*/


}

/**
* 通过反射获取字段
* @throws Exception
*/
@Test
public void testfield() throws Exception {
Class<MyTest> forName = (Class<MyTest>) Class.forName("com.ifueen.classtest.reflect.MyTest");
//获取公有字段,参数为字段名
/*Field f1 = forName.getField("name");
String name = "太宰治";
//通过反射获取新的对象
MyTest myTest = forName.newInstance();
f1.set(myTest, name);
System.out.println(myTest.name);*/
//获取私有字段
/*Field f2 = forName.getDeclaredField("str");
//设置权限
f2.setAccessible(true);
MyTest myTest = new MyTest();
f2.set(myTest, new String("吃薯条"));
System.out.println(myTest.getStr());*/
}

/**
* 获取注解
* @throws Exception
*/
@Test
public void testAnnotation() throws Exception {
Class<MyTest> forName = (Class<MyTest>) Class.forName("com.ifueen.classtest.reflect.MyTest");
//拿到注解
MyAnnotation a1 = forName.getAnnotation(MyAnnotation.class);
System.out.println(a1);
//拿到注解里面的方法
String star = a1.star();
System.out.println(star);
//测试注解是否被继承
/*Class<Separate> s1 = Separate.class;
MyAnnotation a2 = s1.getAnnotation(MyAnnotation.class);
String star = a2.star();
System.out.println(star);*/
}

}
❤赏点钱让我买杯快乐水8❤