Java反射学习

原创
2021/06/24 10:46
阅读数 240

1 Class的表示

在面向对象的世界中,万事万物皆为对象.
(Java语言中,静态的成员,普通数据类型除外)
类也是对象,类是java.lang.Class的对象,有三种表示方式:

  1. 静态成员变量
Class c1=Foo.class;
  1. 根据对象获取对应类(同样为静态获取,编译时即可获取)
Class c2=foo.getClass();
  1. 通过类名获取对应类(动态获取,运行时才能获取)
//此处省略try...catch...
Class c3=Class.forName("com.imooc.reflect.Foo");

同时,也可根据类获取其中的实例对象.

//此处省略try...catch...
Foo foo=(Foo)c1.newInstance();

2 Class的方法: 获取对象的名称,域,方法,构造函数

//称为int的类类型(class type)
Class c1=int.class;
//称为String的类类型,也被老师称为String的字节码(原因是两个字符串的类,其类类型总是相等的)
Class c2=String.class;

Class c5=void.class;

类的名称的获取:

//java.lang.String
String className=c1.getName();
//String
String classSimpleName=c1.getSimpleName();

类的方法的获取:

//getMethods()获取所有public函数,包括父类继承的
Method[] ms=c1.getMethods();
//getDeclaredMethods()获取所有该类自己声明的方法,不论访问权限
Method[] ms2=c1.getDeclaredMethods();
//Method也是一个对象,属于方法对象,可以获取方法名,方法参数,方法返回值
for(Method m:ms2){
    String methodName=m.getName();
    Class returnType=m.getReturnType();
    Class[] paramTypes=m.getParameterTypes();
}

类的域的获取:

//getFields()获取所有的public的成员变量的信息
Field[] fs=c.getFields();
//getDeclaredFields()获取该类自己声明的成员变量信息
Field[] fs2=c.getDeclaredFields();
//Field也是一个对象
for(Field f:fs){
    //获取成员变量的类型
    Class fieldType=f.getType();
    //获取成员变量的名称
    String fieldName=f.getName();
}

类的构造函数的获取

//获取所有的public构造函数
Constructor[] cs=c.getContructors();
//得到所有的构造函数
Constructor[] cs2=c.getDeclaredConstructors();
//Constructor没有返回值,差别在于参数,获取方法名同Method

3 Method扩展: 方法的反射

method.invoke(方法名,参数列表)

  1. 方法的名称和方法的参数列表,才能唯一决定某个方法
//此处忽略try...catch...
Class c=Foo.class;
//两种获取方法...args和数组方式,均可获取
Method m=c.getMethod("print",int.class,int.class);
Method m2=c.getMethod("print",new Class[]{String.class,String.class});
  1. 方法反射的操作
Foo foo=new Foo();
//两种操作方法均可行
m.invoke(foo,new Class[]{int.class,int.class});
m.invoke(foo,String.class,String.class);
  1. 为什么要用方法的
    譬如可通过标注JavaBean的属性获取其属性值.
  2. 通过Class,Method来认识泛型的本质
ArrayList list = new ArrayList();
		
ArrayList<String> list1 = new ArrayList<String>();
list1.add("hello");
//list1.add(20);错误的
Class c1 = list.getClass();
Class c2 = list1.getClass();
System.out.println(c1 == c2);
//反射的操作都是编译之后的操作

/*
 * c1==c2结果返回true说明编译之后集合的泛型是去泛型化的
 * Java中集合的泛型,是防止错误输入的,只在编译阶段有效,
 * 绕过编译就无效了
 * 验证:我们可以通过方法的反射来操作,绕过编译
 */
try {
	Method m = c2.getMethod("add", Object.class);
	m.invoke(list1, 20);//绕过编译操作就绕过了泛型
	System.out.println(list1.size());
	System.out.println(list1);
	/*for (String string : list1) {
		System.out.println(string);
	}*///现在不能这样遍历
} catch (Exception e) {
  e.printStackTrace();
}

end

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部