注解和反射
1.反射的三种方式
- 通过对象获得
Student student=new Student(); Class class1=student.getClass();
- 通过forName获得
Class class2=Class.forName("com.kuang.reflection.Student");
- 通过类名.class获得
Class class3=Student.class;
2.Java内存分析
2.1Java内存
- 堆 存放new的对象和数组,可以被所有线程共享
- 栈 存放基本变量类型(会包含这个基本类型的具体数值)
引用对象的变量(会存放这个引用在堆里面的具体地址) - 方法区 可以被所有线程共享,包含所有的class和static变量
3.内加载器
测试类是哪个加载器加载的
ClassLoader classLoader=Class.forName("com.kuang.reflection.Student").getClassLoader();
4.获取类的运行时结构
Class class2=Class.forName("com.kuang.reflection.Student");
class2.getName();//**获取全类名**
class2.getSimpleName();//**获取简单类名**
Field[] fields=class2.getFields();//**获取类的所有public属性**
Field[] fields=class2.getDeclaredFields();//**获取所有本类私有的属性**
Field field=class2.getDeclaredFields("name");//**获取指定属性值**
Method[] methods=class2.getMethods();//**获取本类及父类的所有public的方法**
Method[] methods=class2.getDeclaredMethods();//**获取所有本类所有的方法**
Method method=class2.getMethod("setName","String.class");//**获取指定方法**
Constructor[] constructors=class2.getConstructor();//**获取本类的所有public构造器方法**
Constructor[] constructors=class2.getDeclaredConstructor();//**获取所有本类所有构造器方法**
Constructor constructor=class2.getDeclaredConstructor("String.class","int.class","int.class"); constructor=class2.getDeclaredConstructor("String.class","int.class","int.class");//**获取所有本类所有构造器方法**
5.动态创建对象,通过反射
通过反射获取到class对象,调用getMethod()方法获取到Method对象,调用Method对象的invoke方法可以调用方法,需要指定方法参数
若原方法声明为private,则需要在调用此incoke()方法钱,显式调用方法对象的setAccessible(true)方法。
setAccessible
- Method、Field、Constructor对象都有setAccessible()方法
- 作用是启动和禁用访问安全检查的开关
- 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查
如果代码频繁被调用,请设置为true
使得原本无法访问的私有成员可以访问
Class class2=Class.forName("com.kuang.reflection.Student");
//创建一个对象
Student student=(Student) class2.newInstance();
//通过构造器创建对象
Constructor constructor=class2.getDeclaredConstructor("String.class","int.class","int.class");
Student student2=(Student) constructor.newInstance("老王",001,18);
//通过反射获取一个方法
Method setName=class2.getMethod("setName","String.class");
setName.invoke(student,"狂神")
//通过反射操作属性
Field name=class2.getDeclaredFields("name");
name.setAccessile(true);//不能直接操作私有属性,需要关闭程序的安全检测,会降低程序效率
name.set(student,"狂神2");
6.通过反射获取泛型
-
Java采用泛型擦除的机制来引入泛型 , Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性
和免去强制类型转换问题 , 但是 , 一旦编译完成 , 所有和泛型有关的类型全部擦除 -
为了通过反射操作这些类型 , Java新增了 ParameterizedType , GenericArrayType ,
TypeVariable 和 WildcardType 几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型. -
ParameterizedType : 表示一种参数化类型,比如Collection
-
GenericArrayType : 表示一种元素类型是参数化类型或者类型变量的数组类型
public class test11 {
public void test01(Map<String,Student> map,List<Student> list){
System.out.println("test01");
}
public Map<String,Student> 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);
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);
}
}
}
method=test11.class.getMethod("test02", null);
Type genericReturnType = method.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
标签:反射,class,获取,Method,Student,注解,class2,Class
From: https://www.cnblogs.com/KxWanna/p/17280820.html