Jacky's blog
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)

Jack Yang

编程; 随笔
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)
  • shell

  • tool

  • 网络

  • algo

  • compute_base

  • blog

  • growth

  • java

    • java base
    • Java 面试高频问题指南
    • other

    • throwable
    • thread
    • jvm
    • weakreference
    • UnSafe
    • collections
    • Class
      • api
        • getGenericSuperclass
      • getSuperclass
      • getDeclaredField/getField
      • snip
        • access static field
      • FAQ
        • Java 反射真的很慢吗?
        • Class.forName vs ClassLoader.loadClass
    • classloader
  • C&C++

  • ai

  • secure

  • cms

  • english

  • 生活

  • 金融学

  • more

  • other
  • java
Jacky
2023-08-22
目录

Class

# api

# getGenericSuperclass

getGenericSuperclass 是 Java 中 java.lang.Class 类的方法之一。它用于获取表示某个类的父类的 Type, 其中 Type 是 Java 泛型类型的表示形式。这个方法通常与 Java 泛型一起使用, 以便在运行时获取类的泛型信息

Type getGenericSuperclass()
1

返回类型: Type, 表示该类的父类的泛型类型

getGenericSuperclass 的常见使用场景包括:

  • 获取父类的泛型类型信息: 通过 getGenericSuperclass, 您可以在运行时获取类的父类的泛型类型信息。这对于实现泛型工具类或进行运行时类型检查非常有用。例如, 可以获取某个类的直接父类的泛型类型, 然后进一步分析这些泛型参数

  • 实现通用的序列化和反序列化: 当您需要将对象序列化为字节数组或反序列化为对象时, getGenericSuperclass 可以帮助您获取类的父类的泛型信息, 以便正确地序列化和反序列化泛型对象

  • 构建通用的数据访问层(DAO): 在数据访问层中, 您可能需要动态地根据模型类来构建 SQL 查询。通过 getGenericSuperclass, 您可以获取模型类的泛型信息, 以便根据泛型类型生成合适的 SQL 查询

  • 动态代理: 使用 Java 动态代理机制时, 您可能需要获取被代理类的泛型信息。getGenericSuperclass 可以帮助您确定代理类需要实现的接口和泛型参数

  • 反射操作: 对于任何需要在运行时进行反射操作的情况, getGenericSuperclass 可以提供更多有关类层次结构和泛型类型的信息

需要注意的是, getGenericSuperclass 方法只能获取直接父类的泛型信息, 如果类的层次结构更加复杂, 您可能需要进一步递归检查超类以获取完整的泛型信息。此外, 泛型类型的擦除规则也会影响到 getGenericSuperclass 返回的类型。因此, 在使用这个方法时, 要仔细考虑泛型类型的实际情况

示例: 获取参数的Class类文件对象
public class Base<T,R> {
  T t;
  R r;
}

public class A extends Base<String,Integer> {

}
1
2
3
4
5
6
7
8

获取 A 文件第一个参数 String 的类对象可以这样做, 如下:

// => getParamTypeForSuper(Base.class,1);

public <T> Class<T> getParamTypeForSuper(Class<?> clazz, int index) {
  while (clazz != null) {
    Type superclass = clazz.getGenericSuperclass();
    if (superclass instanceof Class) {
      clazz = clazz.getSuperclass();
      continue;
    }
    ParameterizedType parameterized = (ParameterizedType) superclass;
    Type type = parameterized.getActualTypeArguments()[index];
    if (type instanceof ParameterizedType)
      return (Class<T>) ((ParameterizedType) type).getRawType();
    else
      return (Class<T>) type;
  }

  throw new RuntimeException("Missing type parameter.");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# getSuperclass

getSuperclass 返回直接继承的父类(由于编译擦除, 没有显示泛型参数)

# getDeclaredField/getField

  1. getDeclaredField: 获取 Class 类对象所有声明的 field,不包含父类声明的 field
  2. getField: 获取当前类对象申明的 field,包含父类的非 private 的 field。 如果要获取父类 private field,需要通过 superClass 获取

# snip

# access static field

val c = Class.forName("android.app.ActivityThread")
val currentActivityThread = c.getDeclaredMethod("currentActivityThread")
var acc = currentActivityThread.isAccessible
if (!acc) {
    currentActivityThread.isAccessible = true
}
// 调用static方法
val o = currentActivityThread.invoke(null)
if (!acc) {
    currentActivityThread.isAccessible = acc
}
val f = c.getDeclaredField("mInstrumentation")
acc = f.isAccessible
if (!acc) {
    f.isAccessible = true
}
val currentInstrumentation = f[o] as Instrumentation
val ins: Instrumentation = ApmInstrumentation(currentInstrumentation)
f[o] = ins
if (!acc) {
    f.isAccessible = false
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# FAQ

# Java 反射真的很慢吗?

Java 反射真的很慢吗? (opens new window)

  • 反射调用过程中会产生大量的临时对象, 这些对象会占用内存, 可能会导致频繁 gc, 从而影响性能
  • 反射调用方法时会从方法数组中遍历查找, 并且会检查可见性等操作会耗时
  • 反射在达到一定次数时, 会动态编写字节码并加载到内存中, 这个字节码没有经过编译器优化, 也不能享受 JIT 优化
  • 反射一般会涉及自动装箱/拆箱和类型转换, 都会带来一定的资源开销
总结
  • 不要在性能敏感的应用中, 频繁调用反射
  • 如果反射执行的次数小于 1000 这个数量级, 反射的耗时实际上与正常调用无太大差异
  • 反射对内存占用还有一定影响的, 在内存敏感的场景下, 谨慎使用反射

# Class.forName vs ClassLoader.loadClass

  • Class.forName
    • 装载、链接、初始化;静态代码块会被执行.
  • ClassLoader.loadClass
    • 装载
#反射#class
上次更新: 2025/10/09, 23:53:03
collections
classloader

← collections classloader→

最近更新
01
npx 使用指南
10-12
02
cursor
09-28
03
inspect
07-20
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Jacky | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式