反射Reflection

1:获取Class实例的三种方式

Class clazz=Person.class;

Class clazz=new person().getClass;

Class clazz=Class.forName("包名+类名");//用的最多

2:Class的实例对应加载到内存中的一个运行时类

3:创建运行时类的对象

Class clazz=Person.class;

Person p=(Person)clazz.newInstance();//必须有空参构造器,不低于private

  1 /**
  2  * 1:Reflection:反射:反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息,
  3  * 并能直接操作任意对象的内部属性与方法
  4  * 2:加载完类以后,在堆空间的方法区中就产生了一个Class类型的对象(一个类只有一个class对象)
  5  * 这个对象包含了完整的类的内部信息,我们可以通过这个对象看到类的结构,称之为反射!
  6  * 3:************实例化对象的区别
  7  * 正常方式:导入相应的类的名称----new实例化------取得实例化对象
  8  * 反射方式:实例化对象----getClass方法----得到完整的包类名称
  9  * 4:反射机制提供的功能:
 10  *    1在运行时判断任一对象所属的类
 11  *    2在运行时改造任意一个类的对象
 12  *    3在运行时判断任意一个类所具有的成员变量与方法
 13  *    4在运行时获取泛型信息
 14  *    5在运行时调用任意一个对象的成员变量与方法
 15  *    6在运行时处理注解
 16  *    7生成动态代理
 17  *
 18  * 5:反射相关的主要API
 19  * java.lang.Class:代表一个类
 20  * java.lang.reflect.Method:代表类的方法
 21  * java.lang.reflect.Field:代表类的成员变量
 22  * java.lang.reflect.Constructor:代表类的构造器
 23  *
 24  * **************************疑问?*******************
 25  *1:通过直接new的方式或者反射的方式都可以创建对象,那么开发中具体用哪个:建议直接用new创建对象
 26  *2:什么时候会使用反射的方式:动态性
 27  *3:反射机制与封装性是否矛盾,怎么看待?  :不矛盾,封装时私有化不建议你直接调用,
 28  * 如果真想用使用反射调用也是可以的,只是一个建议
 29  *
 30  * ***********Class类的理解**************
 31  * 1:类的加载过程:程序在经过javac.exe命令后,会生成一个或者多个字节码文件(.class结尾)
 32  * 接着我们使用java.exe命令对某个字节码文件进行解释运行相当于将字节码文件加载到内存中,
 33  * 此过程称为类的加载.加载到内存中的类称为运行时类,此运行时类就作为Class的一个实例
 34  * 2:换句话说,Class的实例就对应着一个运行时类
 35  * 3:加载到内存中的运行时类会缓存一定时间,在此时间之内,我们可以通过不同方式来获取此运行时类
 36  * *****哪些类型可以有Class对象******
 37  * 1:class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
 38  * 2:interface:接口 3:数组 4:枚举enum 5:注解annotation  6:primitive tape;基本数据类型
 39  * 7:void
 40  *
 41 // */
 42 public class ReflectionTest {
 43    @Test
 44     public void test(){
 45        //*******不使用反射
 46        //1创建Person类对象:
 47        Person person=new Person("hpp",23);
 48        System.out.println(person);
 49        person.setAge(50);
 50        System.out.println(person.age);
 51        //在Person类外部不可以通过对象调用私有的结构,属性,方法,构造器等等
 52    }
 53    @Test
 54     public void test2()throws NoSuchMethodException {
 55        //***********使用反射
 56        Class clazz=Person.class;
 57        Constructor constructor=clazz.getConstructor(String.class,int.class);
 58 
 59    }
 60 
 61    /**
 62     * 获取Class实例的4种方式:前3种需要掌握,第三种方式使用最多
 63     *
 64     */
 65    @Test
 66    public void test3()throws ClassNotFoundException{
 67       //方式1:调用运行时类的属性.class
 68       Class clazz1=Person.class;
 69       System.out.println(clazz1);
 70       //方式2:通过运行时类的对象,调用getClass方法
 71       Person person=new Person();
 72       Class clazz2=person.getClass();
 73       System.out.println(clazz2);
 74       //方式3:通过调用Class的静态方法forName(String classPath)包名+类名
 75       Class clazz3=Class.forName("Reflection.Person");
 76       System.out.println(clazz3);
 77       //方式4:使用类的加载器,classLoader了解即可
 78    }
 79    @Test
 80    public void test4(){
 81       //Class
 82       Class c1=Object.class;
 83       Class c2=int[].class;
 84       Class c6=int[][].class;
 85       Class c3=void.class;
 86       Class c4=int.class;
 87       Class c5=String.class;
 88       System.out.println(c2==c6);//元素类型与维度一致就是同一个Class,对于数组里面的长度没关系
 89    }
 90    /**
 91     * 二:创建运行时类的对象
 92     *
 93     */
 94    @Test
 95    public void test5()throws Exception{
 96       Class<Person> clazz=Person.class;//首先创建Class的实例
 97       Object obj=clazz.newInstance();//其次创建运行时类的对象,通过调用newInstance方法会返回一个实例,
 98       //newInstance方法调用了运行时类的空参构造器,
 99       //换句话说,要想使用此方法,1:必须要有空参构造器,2:构造器访问权限不能低于等于private,通常设置为public
100       Person person=(Person) obj;//记得进行强转
101       Person per=(Person)clazz.newInstance();//缩成一行
102       System.out.println(per);
103    }
104    @Test
105    public void test6(){
106       for (int i = 0; i < 100; i++) {
107          String classpath="";
108          int num= new Random().nextInt(3);
109          switch (num){
110             case 0:
111                classpath="java.util.Date";
112                break;
113             case 1:
114                classpath="java.lang.Object";
115                break;
116             case 2:
117                classpath="Reflection.Person";
118                break;
119          }
120          try {
121             Object obj=getInstance(classpath);
122             System.out.println(obj);
123             System.out.println("************");
124          } catch (Exception e) {
125             e.printStackTrace();
126          }
127       }
128    }
129    public Object getInstance(String str)throws Exception{
130       //对于输入的字符串创建相应的对象
131       Class clazz=Class.forName(str);
132       return clazz.newInstance();
133    }
134    /**
135     * 获取当前运行时类的属性结构
136     *
137     *
138     */
139    @Test
140 public void test7()throws Exception {
141       //Class clazz=Class.forName("包名");
142       Class clazz1=Person.class;
143       Class clazz2=new Person().getClass();
144       System.out.println(clazz2);
145 
146 
147    }
148    /**
149     * 获取当前运行时类中的方法结构
150     */
151 @Test
152    public void test8(){
153    Class clazz=Person.class;
154    System.out.println(clazz.getPackage());//获取包名
155    System.out.println(clazz.getConstructors());//获取构造器
156    //getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
157    Method[] methods=clazz.getMethods();
158    //getDeclareMethods():获取当前运行时类里声明的所有方法(不包含父类)
159    Method[] demethods=clazz.getDeclaredMethods();
160    for (Method m:methods){
161       System.out.println(m);
162    }
163    for (Method m1:demethods){
164       System.out.println("*****");
165       System.out.println(m1);
166    }
167 }
168 /**
169  * 获取运行时类的方法的内部结构:了解就行
170  * 权限修饰符 返回值类型 方法名(参数类型 参数名){}
171  */
172 /**
173  * 调用运行时类的指定的结构:属性,方法,构造器:方法最重要
174  *
175  */
176 @Test
177 //如何调用运行时类里的指定属性,需要掌握
178    public void test9()throws Exception{
179    Class<Person> clazz=Person.class;
180    //创建运行时类对象
181    Person p=clazz.newInstance();
182    Person p1=clazz.newInstance();
183    //getDeclareFiled(String fieldName):获取运行时类中指定变量名的属性
184    Field name=clazz.getDeclaredField("name");
185    name.setAccessible(true);//保证当前属性可以访问,否则在private条件下无法访问修改
186    name.set(p,"Tom");
187    p.setName("hello");
188    System.out.println(p.getName());
189 }
190 /**
191  * 如何调用运行时类的指定方法:掌握
192  */
193 @Test
194    public void test10()throws Exception{
195     //创建class实例
196    Class<Person> clazz=Person.class;
197    //创建运行时类对象
198    Person p=clazz.newInstance();
199     //1:获取指定的某个方法getDeclaredMethod(),参数1:指明获取的方法名称,参数2:指明获取的方法的形参列表
200     Method method=clazz.getDeclaredMethod("showNation", String.class);
201     //2:setAccessible可访问修改调用
202     method.setAccessible(true);
203     //3:invoke():参数1:方法调用者,参数2:给方法形参赋值的实参
204     method.invoke(p,"CHN");
205 }
206 
207 
208 }

 

posted @ 2021-12-14 20:12  tiiiiii  阅读(39)  评论(0)    收藏  举报