【总结篇】Java反射笔记总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun8112133/article/details/89349362

版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/89349362








一、动态语言概述

动态语言: 在程序运行时,可以改变程序结构或变量类型。

如: Python, Ruby, JavaScript等都属于动态语言。

下面是一段 JS代码:

function test(){
    var s="var a=3; var b=5; alert(a+b)";
    eval(s);     // 动态执行了s这个字符串,改变了整个程序的结构。
}

注: C、C++、Java不是动态语言,但是Java有一定的动态性,可以通过反射机制、字节码操作获得类似动态语言的特性,Java语言又可以称为 “准动态语言”



二、反射概述

1、反射机制

Java反射机制 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java语言的反射机制

2、Class对象

Class对象 是内存中对应类的对象。一个类被加载后,JVM会创建一个对应类的Class对象,类的整个结构信息会放到对应的 Class对象 中。这个 Class对象 就像一面镜子一样,通过这面镜子我们可以看到对应类的全部信息。

加载完类之后,在堆内存中,就产生了一个Class类型的对象(一个类只有一个 Class对象)。这个对象也称为 反射对象。同一个类,它只会被加载一次,同一个类只会有一个反射对象。



三、获取Class对象的方式及其使用场景

1、对象名.getClass()

使用场景: 判断两个对象是否是同一个字节码文件

2、Class.forName(“全类名”)

使用场景: 读取配置文件

3、类名.class

使用场景: 锁对象

注: 数组也有Class对象,元素类型相同的数组,获取到的Class对象是同一个。



四、通过反射获取各种信息

1、获取类的名字

基本的数据类型的数组的类名: (getClass().getName())
  byte : [B
  short : [S
  int : [I
  long : [J
  float : [F
  double : [D
  boolean : [Z
  char : [C

1)全类名

c.getName();

2)类名

c.getSimpleName();

2、获取属性信息

1)本类及其父类中全部public的属性

Field[] fields = c.getFields();

2)本类全部的属性

Field[] fields = c.getDeclaredFields();

3)指定的public属性

Field[] field = c.getField("gender");

4)指定的属性

Field field = c.getDeclaredField("age");

3、获取方法信息

1)全部的方法

Method[] methods = c.getDeclaredMethods();

2)指定的方法

Method method = c.getDeclaredMethod("setName", String.class);

3)方法的名字

method.getName();

4)方法的注解

Annotation[] annos = method.getAnnotations();

5)方法的权限修饰符

String str = Modifier.toString(method.getModifies());

6)方法的返回值类型

Class returnType = method.getReturnType();

7)方法的参数列表类型

Class params = method.getParamerTypes();

8)方法的异常类型

Class exps = method.getExceptionTypes();

4、获取构造器信息

1)所有的构造器

Constructor[] constructors = c.getDeclaredConstructors();

2)指定的构造器

Constructor[] con = c.getConstructor(int.class, String.class);

5、获取父类信息

1)获取运行时的父类

Class superClass = c.getSuperclass();

2)获取带泛型的父类

Type type = c.getGenericSuperclass();

3)获取父类的泛型

Type type = c.getCenericSuperclass();
ParameterizedType param = (ParameterizedType) type;
Type[] args = param.getActualTypeArguments();

6、获取接口信息

Class[] interfaces = c.getInterfaces();

7、获取包信息

Package package = c.getPackage();

8、获取注解信息

Annotation[] annos = c.getAnnotations();


五、调用构造器、方法、属性

1、调用构造器

Teacher t = (Teacher) c.newInstance(); // 调用Teacher的无参构造器
Constructor con = c.getDeclaredConstructor(int.class, String.class);
Teacher t2 = (Teacher) con.newInstance(1, "sunkuan");

2、调用普通方法

Teacher t3 = (Teacher) c.newInstance();
Method m = c.getDeclaredMethod("sserName", String.class);
M.invoke(t3, "sun"); // 相当于t3.serName("sun");

3、操作属性

Teacher t4 = (Teacher) c.newInstance();
Field field = c.getDeclaredField("name");
field.serAccessible(true); // 设置访问权限为可见
field.ser(t4, "br"); // 为属性设置值
System.out.println(field.get(t4)); // 输出属性值


六、通过反射越过泛型

案例: ArrayList<Integer>,在这个集合中添加一个字符串数据,如果实现呢?

注意: 泛型只在编译期有效,在运行期会被擦除。

main {
    // 创建List集合
    ArrayList<Integer> list = new ArrayList<Integer>();
    // 添加数据
    list.add(1111);
    list.add(2222);
    // 通过反射获取List集合的Class对象
    Class clazz = Class.forName("java.util.ArrayList");
    // 通过反射获取添加方法的反射对象
    Method m = clazz.getMethod("add", Object.class);
    // 调用添加方法添加数据
    m.invoke(list, "abc");
}



猜你喜欢

转载自blog.csdn.net/sun8112133/article/details/89349362