- 在java中,使用反射的代码实例如下:
class Student {
String name;
Integer age;
public Student(String name, Integer age) {
= name;
= age;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
= age;
}
}
abstract class BaseService<T> {
abstract int save(T t);
}
interface StudentService<T> {
List<T> findStudent(String name, Integer age);
}
class StudentServiceImpl extends BaseService<Student> implements StudentService<Student> {
@Override
int save(Student student) {
return 0;
}
@Override
public List<Student> findStudent(String name, Integer age) {
return (new Student[]{new Student("Jack", 20), new Student("Li", 30)});
}
}
public class JDemo {
public static void main(String[] args) {
StudentServiceImpl studentService = new StudentServiceImpl();
(new Student("Tom", 30));
("Jack", 20);
//反射API调用示例
final Class<? extends StudentServiceImpl> studentServiceClass = ();
//getClasses得到该类及其父类所有的public的内部类。
//getDeclaredClasses得到该类所有的内部类,除去父类的。
Class<?>[] classes = ();
Annotation[] annotations = ();
ClassLoader classLoader = ();
Field[] fields = ();
Method[] methods = ();
try {
methods[0].getName();
methods[0].invoke(studentService,"jack",20);
} catch (IllegalAccessException e) {
();
} catch (InvocationTargetException e) {
();
}
}
}
通过反射,可以获取一个类的注解、方法、成员变量等。那么能不能通过反射获取到泛型信息呢?我们知道java中的泛型擦除。在程序运行时,无法得到自己本身的泛型信息。而当这个类继承了一个父类,父类中有泛型的信息时,那么可以通过getGenericSuperclass()方法得到一个父类的泛型信息。getGenericSuperclass()是Generic继承的特例,对于这种情况子类会保持父类的Generic参数类型。返回一个ParameterizedType。另外我们所说的java泛型在字节码中会被擦除,并不总是擦除为Object类型,而是擦除到上限类型。
在Kotlin也是一样的泛型机制。所以通过反射能拿到的也只能是有继承父类泛型信息的子类泛型。
class A<T>
open class C<T>
class B<T> : C<Int>()
fun fooA() {
val parameterizedType = A<Int>():: as ParameterizedType
val actualTypeArguments =
for (type in actualTypeArguments) {
val typeName =
println("typeName=$typeName")
}
}
运行fooA(),会报错
Exception in thread "main" : cannot be cast to
at (:11)
at (:24)
fun fooB(){
val parameterizedType = B<Int>():: as ParameterizedType
val actualTypeArguments =
for (type in actualTypeArguments) {
val typeName =
println("typeName=$typeName")
}
}
执行下面的代码可以运行成功。
typeName=
- 下面通过一个简单的实例来说明Kotlin中反射怎样获取泛型代码的基本信息。
/**
* 声明一个父类 BaseContainer
*/
open class BaseContainer<T>
/**
* 声明一个Container 继承BaseContainer
*/
class Container<T : Comparable<T>> : BaseContainer<Int> {
val elements: MutableList<T>
constructor(elements: MutableList<T>) : super() {
= elements
}
fun sort(): Container<T> {
()
return this
}
override fun toString(): String {
return "Container(elements=$elements)"
}
}
object Test {
@JvmStatic
fun main(args: Array<String>) {
//声明一个Container实例
val container = Container(mutableListOf(1, 2, 3, 4, 5))
// 获取Container的KClass对象引用
val kClazz = container::class
// KClass对象的typeParameters属性中存有类型参数的信息
val typeParameters =
//typeParameters 取数组的第一个
val kTypeParameter: KTypeParameter = typeParameters[0]
// kTypeParameter有下面等属性
println() // false
println() // T
println() // [<T>]
println() // INVARIANT
val constructors =
for (KFunction in constructors) {
{
val name =
val type =
println("name=$name") // name=elements
println("type=$type") // type=<T>
for (KTypeProjection in ) {
println() // T
}
}
}
}
}