java反射学习

反射学习

类知识

  1. 一个类在内存中只有一个Class对象,创建的对象可以通过hashCode进行判定
  2. 一个类被加载后,类的整体结构都会被封装在Class对象中

哪些类型可以有Class对象

  1. class:外部类、成员(成员内部类、静态内部类)、局部内部类、匿名内部类

  2. interface:接口

  3. []:数组

  4. enum:枚举

  5. annotation:注解

  6. primitive type:基本数据类型

  7. void

    Class c1 = Object.class;    //对象
    Class c2 = Comparable.class; //接口
    Class c3 = String [].class; //一维数组
    Class c4 = int [][].class;  //二维数组
    Class c5 = Override.class; //注解
    Class c6 = ElementType.class; //枚举
    Class c7 = Integer.class; //基本数据类型
    Class c8 = void.class; //void
    Class c9 = Class.class; //Class
    

获得Class类的方式

  1. 使用对象.getClass()的方式,所有的都继承于Object类,Object类中存在getClass()方法

  2. 使用Class.forName("包路径.类名")获取

  3. 具体的类.class获取 -->最高效也是最安全的做法

  4. 基本内置类型的包装类都有TYPE属性,可直接通过.TYPE获取,例如Integer.TYPE得到int的Class

    Person ps=new Student();
    //获得Class类的方式1
    Class ps1 = ps.getClass();
    //获得Class类的方式2
    Class<?> ps2 = Class.forName("com.lwp.reflect.Student");
    //获得Class类的方式3
    Class ps3 = Student.class;
    //基本内置类型的包装类都有Type属性
    Class c4=Integer.TYPE;
    

Class类的常用方法

  1. 类信息获取

    Person ps=new Person();
    Class cl = ps.getClass();
    //获取类的包名+类名
    String name = cl.getName();
    //获取类名
    String simpleName = cl.getSimpleName();
    
  2. 字段获取

    //获取指定的字段-->只能获取public的
    Field age = cl.getField("name");
    //获取指定的字段,可获取私有
    Field age1 = cl.getDeclaredField("age");
    //获取所有的public修饰的字段
    Field[] fields = cl.getFields();
    //获取所有的字段,含private
    Field[] declaredFields = cl.getDeclaredFields();
    
  3. 方法获取

    //获取指定的无参方法,第二个参数为null即可
    Method method = cl.getMethod("show",null);
    //获取指定的有参方法,参数个数根据方法的参数决定,参数类型为方法参数的class对象
    Method age = cl.getDeclaredMethod("age", int.class);
    //获取本类的所有public方法以及父类的public方法
    Method[] methods = cl.getMethods();
    //只获取本类的所有方法
    Method[] declaredMethods = cl.getDeclaredMethods();
    
  4. 构造方法获取

    //获取类中所有的public构造方法
    Constructor[] constructors = cl.getConstructors();
    //获取类中所有的构造方法
    Constructor[] declaredConstructors = cl.getDeclaredConstructors();
    //获取类中无参的构造方法
    Constructor constructor = cl.getConstructor();
    //获取类中指定参数的构造方法
    Constructor declaredConstructor = cl.getDeclaredConstructor(String.class, int.class);
    

使用反射操作类

Class cl = Class.forName("com.lwp.reflect.Person");
//通过newInstance调用类的无参构造方法创建对象
Person ps=(Person)cl.newInstance();
System.out.println(ps);

//通过构造函数指定参数创建对象
Constructor constructor = cl.getDeclaredConstructor(String.class, int.class);
//当操作私有构造方法、方法、属性时必须设置该值为true,表示无障碍阻挡
constructor.setAccessible(true);
//根据构造方法的数据类型传递对应的数据
Object person = constructor.newInstance("刘文蒲", 18);
System.out.println(person);

//操作类中的方法
Method method = cl.getDeclaredMethod("age", int.class);
method.setAccessible(true);
//调用方法并接收返回值:invoke需要的参数,参数1:操作的对象,参数..根据方法决定,无参不需要传
Object invoke = method.invoke(ps, 18);
System.out.println(ps);
System.out.println(invoke);

//操作类中的属性
Field field = cl.getField("name");
//参数为:参数1:需要操作的对象,参数1:给字段设定的值
field.set(ps,"刘文蒲");
System.out.println(ps);

被操作的Person类

public class Person {
    public String name;
    private String sex;
    private int age;
    int num;
    public Person(){}

    public Person(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    private Person(String name, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public void show(){
        System.out.println("我叫"+name);
    }

    private String age(int age){
        this.age=age;
        return "我叫"+name+"今年"+age+"岁";
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", num=" + num +
                '}';
    }
}

使用反射操作泛型

获取泛型内的参数类型

Class cl = Person.class;
System.out.println("-------------参数泛型--------------");
Method method = cl.getDeclaredMethod("test01", Map.class, List.class,String.class);
//获取泛型参数类型
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
	//判断参数是否是泛型
	if(type instanceof ParameterizedType){
		ParameterizedType pt=(ParameterizedType)type;
		//获取泛型里的参数类型
		Type[] actualTypeArguments = pt.getActualTypeArguments();
		System.out.print(type+"----->");
		for (Type on : actualTypeArguments) {
			System.out.print(on+"\t");
		}
		System.out.println();
	}
}
System.out.println("-------------返回值泛型--------------");
Method method2 = cl.getDeclaredMethod("test02", null);
//获取泛型返回值类型
Type genericReturnType = method2.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
	ParameterizedType on=(ParameterizedType)genericReturnType;
	Type[] actualTypeArguments = on.getActualTypeArguments();
	System.out.println(genericReturnType);
	for (Type actualTypeArgument : actualTypeArguments) {
		System.out.println(actualTypeArgument);
		if(actualTypeArgument instanceof ParameterizedType){
			ParameterizedType on1=(ParameterizedType)actualTypeArgument;
			for (Type typeArgument : on1.getActualTypeArguments()) {
				System.out.print(typeArgument+"\t");
			}
		}
	}

}

使用反射操作泛型填充数据

----待补充

使用反射操作注解

定义注解相关类

自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MzTable {

    String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MzColumn {

    String value();

    int length() default 50;

    String type() default "varchar2";
}

类中使用注解

@MzTable("mz_Student")
public class Student extends Person{
    @MzColumn(value = "mz_age",length = 3,type = "number")
    private int age;

    @MzColumn("mz_name")
    private String name;

    @MzColumn(value = "mz_sex",length = 4)
    private String sex;
}

读取注解信息

Class cl = Student.class;
//获取类的指定注解
Annotation annotation = cl.getAnnotation(MzTable.class);
System.out.println(annotation);
//获取类的所有注解
Annotation[] annotations = cl.getAnnotations();
Field[] declaredFields = cl.getDeclaredFields();
for (Field declaredField : declaredFields) {
	//获取字段上的指定注解
	MzColumn mzColumn = declaredField.getAnnotation(MzColumn.class);
	System.out.println(mzColumn);
	//获取字段上的所有注解
	declaredField.getAnnotations();
}

反射操作类封装

参考博客:https://blog.csdn.net/huangliniqng/article/details/88554510

posted @ 2021-07-03 11:00  幸运刘  阅读(46)  评论(0)    收藏  举报