文章目录

  • 一、获得类的运行时结构
  • 1. 获得类的名字
  • 2. 获得类的属性
  • 获取属性列表
  • 获取指定属性
  • 3. 获取类的方法
  • 获得类的方法列表
  • 获得指定方法
  • 4. 获得的构造器
  • 获得构造器列表
  • 获得指定构造器
  • 二、通过反射动态创建对象
  • 1. 使用newInstance()
  • 2.先获取构造器再创建对象
  • 三、通过反射调用对象的方法
  • 四、通过反射操作对象的属性
  • 五、通过反射获取泛型信息
  • 1. 获取方法参数类型
  • 2. 获取方法带泛型的参数类型
  • 3. 从参数类型(ParameterizedType)中获取泛型信息
  • 六、通过反射获取注解信息
  • 获取注解
  • 1. 获取类上的注解
  • 2. 获取属性上的注解
  • 获取注解中携带的属性值


一、获得类的运行时结构

1. 获得类的名字

getName():包名+类名
getSimpleName():类名

Class c1 = Class.forName("reflection.User");
// 获得类的名字
System.out.println(c1.getName());       //包名+类名
System.out.println(c1.getSimpleName()); //获得类名
====================运行结果====================
reflection.User
User

getFields()
getDeclaredFields()
User
class User{
    private String name;
    private int id;
    private int age;
    // getter、setter、构造函数
}

// 获得类的属性
Field[] fields =c1.getFields();    // 只能找到public属性
Arrays.stream(fields).forEach(System.out::println);
System.out.println("==============");
fields = c1.getDeclaredFields();    // 可以找到所有属性
Arrays.stream(fields).forEach(System.out::println);
=====================运行结果=====================
==============
private java.lang.String reflection.User.name
private int reflection.User.id
private int reflection.User.age

getField(String fieldName)
getDeclaredField(String fieldName)
//获得指定属性的值
Field name = c1.getDeclaredField("name");
=====================打印结果=====================
private java.lang.String reflection.User.name

getMethods()
public
getDeclaredMethods()
private
//获得本类和父类的public方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
    System.out.println(method);
}
System.out.println("==============");
//只获得本类的所有方法
methods = c1.getDeclaredMethods();
for (Method method : methods) {
    System.out.println(method);
}

=====================打印结果=====================
public java.lang.String reflection.User.getName()
public java.lang.String reflection.User.toString()
public void reflection.User.setName(java.lang.String)
public int reflection.User.getId()
public void reflection.User.setAge(int)
public int reflection.User.getAge()
public void reflection.User.setId(int)
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
==============
public java.lang.String reflection.User.getName()
public java.lang.String reflection.User.toString()
public void reflection.User.setName(java.lang.String)
public int reflection.User.getId()
public void reflection.User.setAge(int)
public int reflection.User.getAge()
public void reflection.User.setId(int)

getMethods()
Object

getMethod(String methodName, Class<?> ...parameterTypes):获得本类和父类指定的public方法
getDeclaredMethods(String methodName, Class<?> ...parameterTypes):只获得本类指定的方法(包括private的方法)
其中methodName是方法名,...parameterTypes是参数列表的参数类型的Class对象,因为java中存在函数重载,可以存在多个名字相同的方法,通过参数列表不同进行区分。

// 获得指定方法
Method getName = c1.getMethod("getName", null);
Method setAge = c1.getMethod("setAge", int.class);
System.out.println(getName);
System.out.println(setAge);

=====================打印结果=====================
public java.lang.String reflection.User.getName()
public void reflection.User.setAge(int)

getConstructors()
public
getDeclaredConstructors()
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
    System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors) {
    System.out.println("#" + constructor);
}

public reflection.User()
public reflection.User(java.lang.String,int,int)
#public reflection.User()
#public reflection.User(java.lang.String,int,int)

getConstructor(Class<?> ...parameterTypes)
getDeclaredConstructor(Class<?> ...parameterTypes)
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("指定: " + declaredConstructor);

指定: public reflection.User(java.lang.String,int,int)
  • 类必须有一个无参数的构造器
  • 类的构造器的访问权限需要足够
// 获得Class对象
Class<?> c1 = Class.forName("reflection.User");
// 创造一个对象
User user = (User) c1.newInstance();// 本质是使用无参构造器

// 通过构造器创造对象
Constructor<?> constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) constructor.newInstance("秦疆", 1, 18);

Method
method
method.invoke(Object obj, Object ...args)
obj
args
// 通过反射调用普通方法
User user3 = (User) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
// (对象,方法的参数)
setName.invoke(user3,"狂神");

Field
field
field.set(Object obj, Object value)
obj
value
// 通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
// 不能直接操作私有属性,需要打开访问权限
name.setAccessible(true);
name.set(user4,"狂神2");

setAccessible(true)
method.getParameterTypes()
method
Method
Class<?>[]
public class Test11 {
    public void test01(Map<String, User> map, List<User> list){
        System.out.println("test01");
    }
    public Map<String, User> test02(){
        System.out.println("test02");
        return null;
    }
    public static void main(String[] args) throws NoSuchMethodException {
        // 获取泛型参数类型
        Method method = Test11.class.getMethod("test01", Map.class, List.class);
        Class<?>[] parameterTypes = method.getParameterTypes();
        Arrays.stream(parameterTypes).forEach(System.out::println);
    }
}

interface java.util.Map
interface java.util.List

method.getGenericParameterTypes()
method
Method
Type[]
Type[] genericParameterTypes = method.getGenericParameterTypes();
Arrays.stream(genericParameterTypes).forEach(System.out::println);

java.util.Map<java.lang.String, reflection.User>
java.util.List<reflection.User>

ParameterizedType
getActualTypeArguments()
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
    System.out.println("#"+genericParameterType);
    if(genericParameterType instanceof ParameterizedType){
        Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
        for (Type actualTypeArgument : actualTypeArguments) {
            System.out.println(actualTypeArgument);
        }
    }
}

#java.util.Map<java.lang.String, reflection.User>
class java.lang.String
class reflection.User
#java.util.List<reflection.User>
class reflection.User

Student2
class Student2{
    private int id;
    private int age;
    private String name;
    // getter、setter、toString
}

@Tablekuang
@Fieldkuang
  • @Tablekuang用于修饰一个类,用于说明这个类和数据库中的哪个表相对应
  • @Fieldkuang用于说明和数据库的哪个字段对应,类型是什么,长度是多少
// 类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tablekuang{
    String value();
}

// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldkuang{
String columnName();
String type();
int length();
}

然后我们使用注解在Student2类上进行标注:

@Tablekuang("db_student")
class Student2{
    @Fieldkuang(columnName = "db_id", type = "int", length = 10)
    private int id;
    @Fieldkuang(columnName = "db_age", type = "int", length = 10)
    private int age;
    @Fieldkuang(columnName = "db_name", type = "varchar", length = 3)
    private String name;
    // getter、setter、toString
}

Class
getAnnotations()
Annotation[]
getAnnotation(Class annotationClass)
Annotation
Class<?> c1 = Class.forName("reflection.Student2");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
    System.out.println(annotation);
}

@reflection.Tablekuang(value=db_student)

Field
getAnnotations()
Annotation[]
getAnnotation(Class annotationClass)
Annotation
注解对象.属性名()
// 获得注解的value值
Tablekuang tablekuang = c1.getAnnotation(Tablekuang.class);
System.out.println(tablekuang.value());
// 获得某字段上的注解
Field f = c1.getDeclaredField("id");
Fieldkuang annotation = f.getAnnotation(Fieldkuang.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());

db_student
db_id
int
10