【java学习笔记】反射基础

时间:2023-02-24 18:53:48

一.反射

  反射就是在剖析一个类,了解这个类的构造,创建这个类对应的对象。

Class 代表字节码的类,代表类的类
Field 代表属性的类
Method 代表方法的类
Constructor 代表构造方法的类
Annotation 代表注解的类
Package 代表包的类

 

 

 

 

 

 

 

二.Class类

2.1 获取Class对象:必须有意义

    ①通过类名.class的方式来获取对应类的字节码对象

【java学习笔记】反射基础【java学习笔记】反射基础
 1 import java.util.List;
2
3 public class ClassDemo {
4 @SuppressWarnings("rawtypes")
5 public static void main(String[] args) {
6
7 // 每一个Class对象对应了一个实际的类,因此要求每一个Class都必须有意义
8 // 如果允许随意创建Class对象,就会导致Class对象没有实际对应的类
9 // Class clz0 = new Class();
10
11 // 通过类名.class的方式来获取一个字节码对象
12 // clz表示的就是String的字节码
13 Class<String> clz = String.class;
14 System.out.println(clz);
15
16 // clz2表示的就是List的字节码
17 Class<List> clz2 = List.class;
18 System.out.println(clz2);
19
20 // clz3表示的就是String[]的字节码
21 Class<String[]> clz3 = String[].class;
22 System.out.println(clz3);
23
24 }
25 }
类名.class

 

    ②通过对象.getClass()方法来获取这个对象对应的实际类的字节码对象

【java学习笔记】反射基础【java学习笔记】反射基础
 1 public class ClassDemo {
2 @SuppressWarnings("unchecked")
3 public static void main(String[] args) {
4 Object str = "abc";
5 Class<String> clz = (Class<String>) str.getClass();
6 System.out.println(clz);
7 }
8 }
9
10 //输出:class java.lang.String
对象.getClass()

 

    ③通过Class.forName(类的全路径名)的方法来获取指定类的字节码对象

【java学习笔记】反射基础【java学习笔记】反射基础
 1 import java.util.List;
2
3 public class ClassDemo {
4 @SuppressWarnings("unchecked")
5 public static void main(String[] args) throws ClassNotFoundException {
6 Class<String> clz = (Class<String>) Class.forName("java.lang.String");
7 System.out.println(clz);
8
9 Class<List> clz2 = (Class<List>) Class.forName("java.util.List");
10 System.out.println(clz2);
11 }
12 }
13
14 //输出:
15 //class java.lang.String
16 //interface java.util.List
Class.forName(类的全路径名)

 

 

2.2创建由此对象表示的类的新实例

2.2.1 newInstance

字节码对象.newInstance();

 

用处之举例:

    Cat和Dog都实现了Animal接口,利用向上造型,将字符串利用Properties进行更改,可实现任意创建Cat对象或者Dog对象。

【java学习笔记】反射基础【java学习笔记】反射基础
 1 public class TestClassDemo {
2 @SuppressWarnings("unchecked")
3 public static void main(String[] args) throws Exception {
4
5 // 表示获取了Animal类对应的字节码
6 //"cn.hdu.reflection.Cat"可以用Properties进去获取
7 Class<Animal> clz = (Class<Animal>) Class.forName("cn.hdu.reflection.Cat");
8
9 // 要求类中必须有无参构造
10 Animal a = clz.newInstance(); //产生对象
11 System.out.println(a);
12
13 }
14
15 }
16
17 interface Animal {
18 }
19
20 class Dog implements Animal {
21
22 @Override
23 public String toString() {
24 return "Dog";
25 }
26
27 }
28
29 class Cat implements Animal {
30
31 @Override
32 public String toString() {
33 return "Cat";
34 }
35
36 }
AnimalCatDog

 

2.2.2 通过构造方法创建新实例

//只能获取public构造方法
Constructor<?>[] getConstructors()
Constructor
<T> getConstructor(类<?>... parameterTypes)

//不区分是否是public的构造方法
Constructor<?>[] getDeclaredConstructors()
Constructor
<T> getDeclaredConstructor(类<?>... parameterTypes)
//需要用 Constructor对象.setAccessible(true);进行设置

 

举例:

【java学习笔记】反射基础【java学习笔记】反射基础
 1 import java.lang.reflect.Constructor;
2
3 public class ClassGetConstructorDemo {
4 public static void main(String[] args) throws Exception {
5
6 // clz代表String类的字节码
7 Class<String> clz = String.class;
8
9 // String(String)
10 // 只能获取public修饰的构造方法
11 Constructor<String> constructorPublic = clz.getConstructor(String.class);
12 String str = constructorPublic.newInstance("abc");
13 System.out.println(str);
14
15 // String(byte[], int, int)
16 Constructor<String> constructorParameters = clz.getConstructor(byte[].class, int.class, int.class);
17 String str2 = constructorParameters.newInstance(new byte[] { 97, 98, 99, 100 }, 1, 3);
18 System.out.println(str2);
19
20 // 获取指定的构造方法,不区分是否是public的
21 Constructor<String> constructorPrivate = clz.getDeclaredConstructor(char[].class, boolean.class);
22 // 暴力破解/暴力拆除
23 constructorPrivate.setAccessible(true);
24 String str3 = constructorPrivate.newInstance(new char[] { 'a', 'b', 'c' }, true);
25 System.out.println(str3);
26 }
27
28 }
getConstructor

在String源码中是默认的,非public

【java学习笔记】反射基础

 

2.3 获取方法

//public
Method getMethod(String name, 类<?>... parameterTypes)
Method[] getMethods() //获取所有公有方法(包含了父类的方法也包含Object类) 

//非public
Method getDeclaredMethod(String name, 类<?>... parameterTypes)
Method[] getDeclaredMethods() //获取所有的成员方法,包括私有的(不包括继承的)
//m.setAccessible(true);

//使用所指定的方法:Method的对象.invoke(Object obj, Object... args);

 

【java学习笔记】反射基础【java学习笔记】反射基础
 1 import java.lang.reflect.Constructor;
2 import java.lang.reflect.Method;
3
4 public class ClassGetMethodDemo {
5
6 public static void main(String[] args) throws Exception {
7
8 Class<String> clz = String.class;
9
10 // 表示String(String)
11 Constructor<String> c = clz.getConstructor(String.class);
12 String str = c.newInstance("abcdefg");
13
14 // 获取charAt(int)
15 // 只能获取public修饰的方法
16 Method m = clz.getMethod("charAt", int.class);
17 // 执行方法对象
18 // 相当于char ch = str.charAt(3);
19 char ch = (char) m.invoke(str, 3);
20 System.out.println(ch);
21
22 // 获取指定的方法
23 Method m2 = clz.getDeclaredMethod("lastIndexOfSupplementary", int.class, int.class);
24 m2.setAccessible(true);
25 int i = (int) m2.invoke(str, 2, 3);
26 System.out.println(i);
27 }
28
29 }
getMethod

 

 

2.4 获取属性

//public
Field getField(String name)
Field[] getFields()

//非public
Field getDeclaredField(String name)
Field[] getDeclaredFields()
//f.setAccessible(true);

//Field类
获取:Object get(Object obj)
设置:
void set(Object obj, Object value)
void setChar(Object obj, char c)
void setDouble(Object obj, double d)
void setInt(Object obj, int i)
... ...
【java学习笔记】反射基础【java学习笔记】反射基础
 1 import java.lang.reflect.Constructor;
2 import java.lang.reflect.Field;
3
4 public class ClassGetFieldDemo {
5 public static void main(String[] args) throws Exception {
6
7 Class<String> clz = String.class;
8
9 // 表示String(String)
10 Constructor<String> c = clz.getConstructor(String.class);
11 String str = c.newInstance("abcdefg");
12
13 // 获取类中指定的属性
14 Field f = clz.getDeclaredField("hash");
15 f.setAccessible(true);
16 System.out.println(f.get(str));
17 // 设置属性的值
18 f.set(str, 125);
19 // 获取属性的值
20 System.out.println(f.get(str));
21 }
22 }
getField

 

 

2.5 获取注解

<A extends Annotation>A getAnnotation(类<A> annotationClass)  
Annotation[] getAnnotations()

<A extends Annotation>A getDeclaredAnnotation(类<A> annotationClass)
Annotation[] getDeclaredAnnotations()

 

 

2.6 Class类其它常用方法

 1 import java.lang.reflect.TypeVariable;
2 import java.util.ArrayList;
3 import java.util.List;
4
5 public class ClassDemo {
6
7 @SuppressWarnings("rawtypes")
8 public static void main(String[] args) {
9
10 Class<String> clz = String.class;
11
12 // 获取这个类实现的所有的接口
13 Class[] ins = clz.getInterfaces();
14 for (Class c : ins) {
15 System.out.println(c);
16 }
17
18 // 获取父类
19 Class superc = clz.getSuperclass();
20 System.out.println(superc);
21
22 // 获取类的全路径名
23 System.out.println(clz.getName());
24 // 获取类的简称
25 System.out.println(clz.getSimpleName());
26
27 // 获取所在的包
28 System.out.println(clz.getPackage());
29
30 List<String> list = new ArrayList<>();
31 Class lclz = list.getClass();
32 TypeVariable[] ts = lclz.getTypeParameters();
33 for (TypeVariable typeVariable : ts) {
34 System.out.println(typeVariable);
35 }
36
37 // 判断是否是一个枚举
38 System.out.println(clz.isAnnotation());
39 // 判断是否是一个基本类型
40 System.out.println(clz.isPrimitive());
41
42 // 判断参数是否是指定类型的实例的
43 Object str = "abc";
44 System.out.println(clz.isInstance(str));
45 System.out.println(str instanceof String);
46
47 // 判断两个类之间是否有继承关系
48 System.out.println(Object.class.isAssignableFrom(String.class));
49
50 }
51
52 }