注解和反射
注解和反射
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);
            }
        }
    }
}
                    
                
                
            
        
浙公网安备 33010602011771号