java中的反射(不讲概念,只是怎么用)

反射作用于分析类
要想分析一个类,必须有这个类的元数据,java中描述类的元数据的类是Class类,元数据就是类自己的数据
要想得到Class类对象,可以有多种方法
1、通过Class.forName加载类
2、通过对象.getClass

1、基础类

下面的所有的探寻反射的方法都是基于下面这个类修改来的

package com.test;

import java.io.Serializable;

public class TestPojo implements Serializable,Cloneable{
	
	public String a;
	private Test t;
	public TestPojo() {
		
	}
	public TestPojo(String s) {
		
	}
	public void f1() {
		System.out.println("没有参数的f1");
	}
	public void f1(String s) {
		System.out.println("有一个String参数的f1");
		
	}
	public void f1(int s) {
		System.out.println("有一个int参数的f1");
	}
	public void f1(String s,int i) {
		System.out.println("有两个参数的分别为String和int的f1");
	}
	
}

2、Class方法

Class clazz = Class.forName("com.test.TestPojo");//得到类对象
(1)得到类的修饰符
clazz.getModifiers()

我就不分开了,下面的表格是类,方法,成员变量的修饰符

修饰符
不写0
public1
final16
protected4
private2
static8
volatile64
transient128
synchronized32
abstract1024
native256

注意
你可能会遇上值为17或者不是上面这些值的,尤其是在下面的操作中,这是因为类的修饰符为 public final修饰的,是16+1=17;如果得出其他的值请不要慌张或者我靠,试试上面的某些值相加是否得出你的值

(2)获得类的接口
Class[] interfaces = clazz.getInterfaces();
		for(Class i : interfaces) {
		    //获得Class的简单名字,如果直接打印i,会打印出接口的包名.类名
			System.out.println(i.getSimpleName()); 
		}

在这里插入图片描述

(3)获得对象的成员变量

获得对象可见变量

Field [] fd = clazz.getFields();//得到可见的成员变量		
		for(Field f : fd) {
			System.out.println(f.getName()); //变量的别名
			System.out.println(f.getType());  //修饰符
			System.out.println(f.getModifiers()); //成员变量的修饰符值
		}

在这里插入图片描述
获得对象所有变量(不管可见不可见),俗称暴力破解

Field [] fd = clazz.getDeclaredFields(); //获得全部变量
		for(Field f : fd) {
			System.out.println(f.getName()); //变量的别名
			System.out.println(f.getType());  //修饰符
			System.out.println(f.getModifiers()); //成员变量的修饰符值
		}

在这里插入图片描述
这是成员变量暴力破解,要和下面方法的暴力破解做出区分

3、方法Method

(1)Method方法获得方法的信息

获得公开的方法
获得Class里f1,且无参的方法赋给m

Method m = clazz.getDeclaredMethod("f1", null);  
Method m = clazz.getMethod("f1", null);  

把隐藏的方法公开,暴力破解方法
f1的修饰符换成private

Method m = clazz.getDeclaredMethod("f1", null); //不能用getMethod,要不会报错
m.setAccessible(true); //true 可以显示隐藏的

如果有参数null 换成 参数类型.class

m.getModifiers(); //也有获得方法的修饰符的值
m.getName();  //获得方法的名字,也就是上面的f1
m.getReturnType();  //返回类型,比如 void
(2)执行方法
Object obj = clazz.newInstance(); //首先实例化class
Method m = clazz.getDeclaredMethod("f1", int.class); //找出class的方法
m.invoke(obj, 5);   //执行方法,参数:类的对象,方法的参数

提醒
如果是数组类型的怎么写呢?
答:那就以int数组为例,上面的获得class里执行方法里的第二个参数换成int[ ].class
例:clazz.getDeclaredMethod("f1", int[].class)

4、实例化class方法

有两种:

  1. 类对象直接实例化
  2. 用构造方法实例化对象

区别:第一种不能带参数,第二种可以带参数
第一种方式

Object obj = clazz.newInstance();

第二种方式

Constructor c1 = clazz.getDeclaredConstructor(String.class); //参数为一个String
Object obj = c1.newInstance("55");  //写生你构造器的参数

5、获得注解

(1)方法上的注解

把基础类的一个方法加上注解

@Deprecated
@SuppressWarnings("unused")
	public void f1(int s) {
		System.out.println("有一个int参数的f1");
	}

执行

Method m = clazz.getDeclaredMethod("f1", int.class);
Annotation[] anns = m.getDeclaredAnnotations();
for(Annotation ann : anns) {
		System.out.println(ann);
	}

在这里插入图片描述
只有一个,因为注解 @SuppressWarnings(“unused”) 不是运行时注解,所以执行时就不会找到

(2)类上的注解
Annotation[] anns = clazz.getDeclaredAnnotations();

6、获得类上的泛型

目前本人只知道这一种方法,不是说只有这一种
通过继承父类的方式来反射泛型

父类

public class TestPojo <T>{
	private Class genericityClass;//泛型
	
	public Class getGenericityClass() {
		if(genericityClass == null) {
			genericityClass = Until.getGenericityClass(this.getClass()); //获得泛型
		}
		return genericityClass;
	}
}	

子类(空的)

public class TestPojoExte extends TestPojo<String> {

}

工具类

public  class  Until {
	public static Class getGenericityClass(Class clazz) {
		
		return getGenericityClass(clazz, 0); //调下面的方法
		
	}
	private static Class getGenericityClass(Class clazz,int index) {
		
		Type type = clazz.getGenericSuperclass(); 
		if(type instanceof ParameterizedType) {
			Type[] params = ((ParameterizedType) type).getActualTypeArguments();
			if(params != null && (params.length >= (index - 1))) {
				return (Class) params[index];
			}
		}
		
		return clazz;
		
	}
}

执行

public static void main(String[] args) throws Exception{
		TestPojo<String> t = new TestPojoExte();
		System.out.println(t.getGenericityClass());
	
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值