【651-685】反射机制
2022-02-07 20:40:00 # JavaSE

概述

反射机制的作用

可以操作字节码文件
可以读和修改字节码文件
反射机制,让代码很具有通用性,可变化的内容都是写到配置文件当中,将来修改配置文件之后,创建的对象不一样了,调用的方法也不同了,但是java代码不需要做任何改动。这就是反射机制的魅力。

反射机制相关类的包

java.lang.reflect*;

反射机制相关类

java.lang.Class:代表字节码文件
java.lang.reflect.Method:代表字节码中的方法字节码
java.lang.reflect.Constructor:代表字节码中的而构造方法字节码
java.lang.reflect.Field:代表字节码中的属性字节码

获取Class的三种方式

public static Class<?> forName(String className) throws ClassNotFoundException

  1. 静态方法
  2. 方法的参数是―个字符串。
  3. 字符串需要的是一个完整类名。
  4. 完整类名必须带有包名。java.lang包也不能省略。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class _652_获取Class的三种方式 {
    public static void main(String[] args){
    try {
    Class c1 = Class.forName("java.lang.String"); // c1代表String.class文件
    Class c2 = Class.forName("java.lang.Integer");
    Class c3 = Class.forName("java.util.Date");
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    }
    }

public final native Class<?> getClass()

运行时Class文件在JVM的方法区中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class _653_获取Class的三种方式 {
public static void main(String[] args) {
Class c1 = null;
try {
c1 = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

String s = "abc";
Class x = s.getClass();

System.out.println(c1 == x); // true
}
}

任何一种数据类型都有.class属性

1
2
3
4
5
6
7
8
9
10
import java.util.Date;

public class _654_获取Class的三种方式 {
public static void main(String[] args) {
Class x = String.class;
Class y = Date.class;
Class z = int.class;
}
}

通过反射实例化对象

1
public T newInstance() throws InstantiationException, IllegalAccessException

必须保证无参构造是存在的

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
public class _655_通过反射实例化对象 {
public static void main(String[] args) {
try {
Class c1 = Class.forName("User");
// newInstance() 调用User类的无参构造方法
Object o = c1.newInstance();
System.out.println(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

/*
无参构造方法执行~
User@1b6d3586
*/
}
}

class User{
public User() {
System.out.println("无参构造方法执行~");
}

public User(String s){
System.out.println("有参构造方法执行~");
}
}

通过读属性文件实例化对象

验证反射机制的灵活性
java代码写一遍,再不改变java源代码的基础之上,可以做到不同对象的实例化。非常之灵活。(符合OCP开闭原则:对扩展开放,对修改关闭。)

1
className=User2
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
import java.io.FileInputStream;
import java.util.Properties;

public class _656_通过读属性文件实例化对象 {
public static void main(String[] args) throws Exception{
FileInputStream fis = null;
// IO流读取文件
fis = new FileInputStream("【651-685】反射机制/src/_656_通过读属性文件实例化对象.properties");

// 创建属性类对象map
Properties mp = new Properties();
// 加载
mp.load(fis);

// 拿到类名
String s = mp.getProperty("className");
System.out.println(s); // User2

// 通过反射实例化对象
Class<?> c = Class.forName(s);
Object o = c.newInstance();
System.out.println(o);

// 关闭文件
fis.close();


}
}

class User2{

}

使用forName可以只让类的静态代码块执行

导致类加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class _657_只让静态代码块执行可以使用forName {
public static void main(String[] args) {
try {
Class<?> c = Class.forName("MyClass");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

class MyClass{
// 在类加载时执行,并且只执行一次
static {
System.out.println("静态代码块执行~");
}
}

获取类路径下文件的绝对路径

什么是类路径

src下的都是类路径,src是类的根路径
IDEA中其实是在out/production下

Thread.currentThread().getContextClassLoader().getResource(“”).getPath()

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

public class _658_获取类路径下文件的绝对路径 {
public static void main(String[] args) {
// 这种方式写路径缺点是:移植性差
// FileInputStream fis = new FileInputStream("【651-685】反射机制/src/_656_通过读属性文件实例化对象.properties");

/*
Thread.currentThread() 当前线程对象
getContextClassLoader() 线程对象的方法,获取当前线程的类加载器对象
getResource("") 类加载器对象的方法,当前线程的类加载器默认从类的根路径下加载资源
*/
String path = Thread
.currentThread()
.getContextClassLoader()
.getResource("_653_获取Class的三种方式.class")
.getPath();
// 拿到文件的绝对路径
System.out.println(path);

String path2 = Thread
.currentThread()
.getContextClassLoader()
.getResource("_656_通过读属性文件实例化对象.properties")
.getPath();
System.out.println(path2);

/*
/D:/Workspace/Java/%e3%80%90JavaSE%e3%80%91BiliBili%e5%8a%a8%e5%8a%9b%e8%8a%82%e7%82%b9/out/production/%e3%80%90651-685%e3%80%91%e5%8f%8d%e5%b0%84%e6%9c%ba%e5%88%b6/_653_%e8%8e%b7%e5%8f%96Class%e7%9a%84%e4%b8%89%e7%a7%8d%e6%96%b9%e5%bc%8f.class
/D:/Workspace/Java/%e3%80%90JavaSE%e3%80%91BiliBili%e5%8a%a8%e5%8a%9b%e8%8a%82%e7%82%b9/out/production/%e3%80%90651-685%e3%80%91%e5%8f%8d%e5%b0%84%e6%9c%ba%e5%88%b6/_656_%e9%80%9a%e8%bf%87%e8%af%bb%e5%b1%9e%e6%80%a7%e6%96%87%e4%bb%b6%e5%ae%9e%e4%be%8b%e5%8c%96%e5%af%b9%e8%b1%a1.properties
*/

}
}

Thread.currentThread().getContextClassLoader().getResourceAsStream(“”)

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
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

public class _659_以流的形式直接返回 {
public static void main(String[] args) throws Exception{
// 通过这种方式得到文件路径
// 有很好的移植性
// 获取绝对路径 不支持中文 所以只是写个样子
// String path = Thread
// .currentThread()
// .getContextClassLoader()
// .getResource("_659_以流的形式直接返回.properties")
// .getPath();
//
// FileInputStream fis = new FileInputStream(path);

// 这种直接以流的形式返回
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("_659_以流的形式直接返回.properties");

Properties mp = new Properties();
mp.load(is);

System.out.println(mp.getProperty("className")); // User
}
}

资源绑定器

便于获取属性配置文件中的内容
使用以下这种方式的时候,属性配置文件 xxx.properties 必须放在类路径下
写路径是只能写 “xxx” 不能加扩展名

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.ResourceBundle;

public class _660_资源绑定器 {
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("_660_资源绑定器");
System.out.println(bundle); // java.util.PropertyResourceBundle@4554617c

String s = bundle.getString("className");
System.out.println(s); // Date

}
}

类加载机制

什么是类加载器

专门负责加载类的命令/工具
ClassLoader

JDK自带3个类加载器

  1. 启动类加载器
  2. 扩展类加载器
  3. 应用类加载器

如果自己写了一个类String,植入java.lang.String,那么首先加载启动类加载器”父”也就是java本身的String类,再从扩展类加载器加载”母”,这是双亲委派机制
最后从应用类加载器加载,也就是自己写的类

example

1
String s = "abc";

首先通过启动类加载器,寻找String.class,专门加载/jre/lib/rt.jar下的class文件
如果找不到则扩展类加载器寻找,专门加载/jre/lib/ext/*.jar下的class文件
如果还找不到则应用类加载器寻找,专门加载classpath中的jar包(计算机中的”环境变量classpath”)

Field

获取Field

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
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class _664_获取Field {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> student = Class.forName("Student");
// 获取类中所有public的属性
Field[] fields = student.getFields();
System.out.println(fields.length); // 1
System.out.println(fields[0]); // public int Student.no
System.out.println(fields[0].getName()); // no

Field[] declaredFields = student.getDeclaredFields();
System.out.println(declaredFields.length); // 4
for (int i = 0; i < declaredFields.length; i++) {
System.out.println(declaredFields[i]);
System.out.println(declaredFields[i].getModifiers() + "->" + Modifier.toString( declaredFields[i].getModifiers() ) );
System.out.println(declaredFields[i].getType());
System.out.println(declaredFields[i].getName());
}
/*
private java.lang.String Student.name
2->private
class java.lang.String
name
boolean Student.sex
0->
boolean
sex
protected int Student.age
4->protected
int
age
public int Student.no
1->public
int
no
*/
}
}

class Student{
private String name;
boolean sex;
protected int age;
public int no;
}

反编译Field

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
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class _665_反编译Field {
public static void main(String[] args) throws ClassNotFoundException {
StringBuilder s = new StringBuilder();
Class<?> student = Class.forName("Student");

s.append(Modifier.toString(student.getModifiers()) + " class " + student.getName() + " {");

Field[] declaredFields = student.getDeclaredFields();
for (Field i : declaredFields){
s.append("\n");
s.append("\t");
s.append(Modifier.toString(i.getModifiers()));
s.append(" ");
s.append(i.getType().getSimpleName());
s.append(" ");
s.append(i.getName());
s.append(";");
}
s.append("\n");
s.append("}");
System.out.println(s);

/*
class Student {
private String name;
boolean sex;
protected int age;
public int no;
}
*/
}
}

通过反射机制访问对象属性

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
import java.lang.reflect.Field;

public class _666_通过反射机制访问对象属性 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> student = Class.forName("Student2");
Object o = student.newInstance();
// 获取 no 属性
Field no = student.getDeclaredField("no");
// 给 o 对象的no属性赋值
no.set(o, 222);
// 读取属性的值
System.out.println(no.get(o)); // 222

// 获取 name 属性
Field name = student.getDeclaredField("name");
// 打破封装(反射机制的缺点:打破封装,给不法分子留机会~)
// 这样设置完后,外部也可访问private
name.setAccessible(true);
// 给 o 对象name属性赋值
name.set(o, "zhangsan");
// 读取属性值
System.out.println(name.get(o)); // zhangsan

}
}

class Student2{
private String name;
boolean sex;
protected int age;
public int no;
public final double PI = 3.1415;
}

Method

可变长度参数

  1. 可变长参数得在参数列表的最后一个
  2. 可变长参数可以当作数组来看待
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class _668_可变长度参数 {
    public static void main(String[] args) {
    f();
    f(123);
    f(123,23,4,5,6);
    f(new int[]{1,23,5,6});
    }

    public static void f(int... args){
    System.out.println("f() start~");
    for (int i : args) {
    System.out.println(i);
    }
    }

    public static void g(int n, String... args){

    }
    }

反射Method

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
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;

public class _669_反射Method {
public static void main(String[] args) throws ClassNotFoundException {
// 获取类
Class<?> userService = Class.forName("UserService");

// 获取所有的Method
Method[] methods = userService.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
System.out.println(method.getName());
System.out.println(method.getReturnType());
System.out.println(Modifier.toString(method.getModifiers()));
// 方法参数列表
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter.getType().getSimpleName());
}
}
/*
public void UserService.logout()
logout
void
public
public boolean UserService.login(java.lang.String,java.lang.String)
login
boolean
public
String
String

*/
//
}
}

class UserService{
public boolean login(String name, String password){
if(name == null) return false;
if(name.equals(password)){
return true;
}
return false;
}

public void logout(){
System.out.println("exit ok~");
}
}

反编译Method

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
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;

public class _670_反编译Method {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> userService = Class.forName("UserService");
StringBuilder s = new StringBuilder();
// System.out.println(userService);
s.append(userService);
s.append(" {");
Method[] declaredMethods = userService.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
s.append("\n");
s.append("\t");
// 获取修饰符
s.append(Modifier.toString(declaredMethod.getModifiers()));
s.append(" ");
// 获取返回类型
s.append(declaredMethod.getReturnType());
s.append(" ");
// 获取函数名
s.append(declaredMethod.getName());
s.append("(");
// 获取参数类型和参数名
Parameter[] parameters = declaredMethod.getParameters();
for (int i = 0; i < parameters.length; i++ ) {
s.append(parameters[i].getType().getSimpleName());
s.append(" ");
s.append(parameters[i].getName());
if (i != parameters.length - 1){
s.append(", ");
}
}
s.append(")");
s.append("{}");
}
s.append("\n}");
System.out.println(s);
}
}


反射机制调用Method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class _671_反射机制调用方法 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
// 获取类
Class<?> userService = Class.forName("UserService");
// 创建对象
Object o = userService.newInstance();
// 获取对应方法
Method login = userService.getDeclaredMethod("login", String.class, String.class);
// 调用该方法
Object invoke = login.invoke(o, "cc", "cc");
//
System.out.println(invoke); // true

}
}

Constructor

反射Constructor

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
import java.lang.invoke.CallSite;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class _672_反射Constructor {
public static void main(String[] args) throws Exception{
StringBuilder s = new StringBuilder();
Class<?> vip = Class.forName("Vip");

// 先拼接类
s.append(Modifier.toString(vip.getModifiers()));
s.append(" class ");
s.append(vip.getSimpleName());
s.append("{");

// 拼接构造方法
Constructor<?>[] declaredConstructors = vip.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
s.append("\n\t");
s.append(Modifier.toString(declaredConstructor.getModifiers()));
s.append(" ");
s.append(declaredConstructor.getName());
s.append("(");
// 拼接参数
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
s.append(parameterTypes[i].getSimpleName());
if(i != parameterTypes.length - 1){
s.append(", ");
}
}

s.append(")");
s.append("{}");

}

s.append("\n}");
System.out.println(s);
/*
class Vip{
public Vip(int, String){}
public Vip(int, String, String){}
public Vip(int, String, String, boolean){}
public Vip(){}
}
*/
}
}

class Vip{
int no;
String name;
String birth;
boolean sex;

public Vip() {
}

public Vip(int no, String name, String birth, boolean sex) {
this.no = no;
this.name = name;
this.birth = birth;
this.sex = sex;
}

public Vip(int no, String name, String birth) {
this.no = no;
this.name = name;
this.birth = birth;
}

public Vip(int no, String name) {
this.no = no;
this.name = name;
}
}

反射机制调用Constructor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.lang.reflect.Constructor;

public class _673_反射机制调用构造方法 {
public static void main(String[] args) throws Exception{
Class<?> vip = Class.forName("Vip");
// 直接无参构造
Object o1 = vip.newInstance();
System.out.println(o1); // Vip{no=0, name='null', birth='null', sex=false}
// 有参构造
Constructor<?> declaredConstructor = vip.getDeclaredConstructor(int.class, String.class, String.class, boolean.class);
Object o2 = declaredConstructor.newInstance(1, "a", "b", true);
System.out.println(o2); // Vip{no=1, name='a', birth='b', sex=true}
}
}

获取父类和父接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class _674_获取父类和父接口 {
public static void main(String[] args) throws Exception {
Class<?> stringClass = Class.forName("java.lang.String");
// 获取父类
Class<?> superclass = stringClass.getSuperclass();
System.out.println(superclass.getName()); // java.lang.Object

// 获取接口
Class<?>[] interfaces = stringClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface);
}
/*
interface java.io.Serializable
interface java.lang.Comparable
interface java.lang.CharSequence
*/
}
}

注解 Annotation

是一种引用数据类型,编译后也是生成xxx.class文件

如何定义注解

1
2
3
4
5
6
7
8
[修饰符列表] @interface 注解类型名{

}

public @interface MyAnnotation{

}

如何用在哪可以用

  1. 语法格式是:@注解类型名
  2. 注解可以出现在类上、属性上、方法上、变量上等
    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
    public class _675_注解怎么定义怎么用 {
    public static void main(String[] args) {

    }
    }

    @_675_注解怎么定义怎么用Annotation
    class Annotation{

    @_675_注解怎么定义怎么用Annotation
    private int no;

    @_675_注解怎么定义怎么用Annotation
    public Annotation(int no) {
    this.no = no;
    }

    @_675_注解怎么定义怎么用Annotation
    public void f(){

    }

    public void g(@_675_注解怎么定义怎么用Annotation String name){

    }
    }

    @_675_注解怎么定义怎么用Annotation
    interface MyInterface{

    }

    @_675_注解怎么定义怎么用Annotation
    enum Season{
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER
    }

JDK内置了哪些注解

java.lang包下的注释类型:
Deprecated用@Deprecated注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
Override表示一个方法声明打算重写超类中的另一个方法声明。
SuppressWarnings指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。

元注解

元注解是负责对其它注解进行说明的注解,自定义注解时可以使用元注解。
Java 5 定义了 4 个注解,分别是 @Documented、@Target、@Retention 和 @Inherited。Java 8 又增加了 @Repeatable 和 @Native 两个注解

@Target

@Target用来标注”被标注的注解”可以出现在哪些位置

@Retention

@Retention用来标注”被标注的注解”最终保存在哪
@Retention(RetentionPolicy.SOURCE):表示该注解只被保留在java源文件中。
@Retention(RetentionPolicy.CLASS):表示该注解被保存在class文件中。
@Retention(RetentionPolicy.RUNTIME):表示该注解被保存在class文件中,并且可以被反射机制锁读取

1
2
3
4
5
6
7
8
9
10
public @interface Retention{
// 属性
RetentionPolicy value();
}

public enum RetentionPolcy{
SOURCE,
CLASS,
RUNTIME
}

@Deprecated

1
2
3
4
5
6
7
8
9
10
11
12
public class _678_Deprecated注解 {
// 过时了
@Deprecated
public static void doSome(){
System.out.println("doSome~");
}

public static void main(String[] args) {
doSome();
}
}

注解中定义属性

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
public @interface _679_注解中定义属性Annotation {
/**
* 以下这个是name属性
* 看着像一个方法
* @return
*/
String name();

String color() default "red"; // 这样就写注解时可以不写这个属性
}


public class _679_注解中定义属性 {

@_679_注解中定义属性Annotation(name = "赋值", color = "red")
public static void doSome(){
System.out.println("doSome~");
}

public static void main(String[] args) {

}
}



属性是value时可以省略(属性名)

如果一个注解的属性只有一个并且是value就可行

1
2
3
4
5
6
7
8
9
10
11
public class _680_属性是value时可以省略 {
@_680_属性是value时可以省略Annotation("abc")
public static void main(String[] args) {

}
}

public @interface _680_属性是value时可以省略Annotation {
String value();
}

属性是个数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public @interface _682_属性是个数组Annotation {
int value1();
String value2();
int[] value3();
String[] value4();
Season1 value5();
Season1[] value6();
Class parameterType();
Class[] parameterTypes();
}

enum Season1{
SPRING,
SUMMER,
AUTUMN,
WINTER
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public @interface _682_属性是个数组Annotation {
int age();
String[] email();
}

// 数组只有一个元素,可省略"{}"
@_682_属性是个数组Annotation(age = 3, email = "xxx@qq.com")
public class _682_属性是个数组 {
@_682_属性是个数组Annotation(age = 3, email = {"xxx@qq.com", "xxx@gmail.com"})
public static void main(String[] args) {

}
}


反射注解

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
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

public class _683_反射注解 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> annotation = Class.forName("_683_反射注解Annotation");
// 判断该注解上是否有 某某 注解
System.out.println(annotation.isAnnotationPresent(Target.class)); // true
// 如果有 则获取该注解对象
if(annotation.isAnnotationPresent(Target.class)){
Target annotation1 = annotation.getAnnotation(Target.class);
System.out.println(annotation1);
/*
@java.lang.annotation.Target(value=[TYPE, FIELD, METHOD])
*/
ElementType[] value = annotation1.value();
for (ElementType elementType : value) {
System.out.println(elementType);
}
/*
TYPE
FIELD
METHOD
*/
}
}
}

通过反射获取注解对象属性值

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
import java.lang.reflect.Method;

public class _684_通过反射获取注解对象属性值 {
public static void main(String[] args) throws Exception {
// 获取类
Class<?> c = Class.forName("MyAnnotationTest");
// 获取doSome()
Method doSome = c.getDeclaredMethod("doSome");
// 获取注解
if (doSome.isAnnotationPresent(_684_通过反射获取注解对象属性值Annotation.class)){
_684_通过反射获取注解对象属性值Annotation annotation = doSome.getAnnotation(_684_通过反射获取注解对象属性值Annotation.class);
System.out.println(annotation.username());
System.out.println(annotation.password());
}
/*
cc
cc
*/
}
}

class MyAnnotationTest{
@_684_通过反射获取注解对象属性值Annotation(username = "cc", password = "cc")
public void doSome(){

}
}
Prev
2022-02-07 20:40:00 # JavaSE
Next