由于第一段视频学习效果不理想,希望重新看一遍反射视频,并多方面寻找资料,重新写一遍总结,以期java能力早日提高。
Java——反射
一、Class类
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。所以,Class可以提供方法获得动态的java类中的各个属性;
(由定义可以知道Class创建的思路就是获得某一个特定java类的信息然后传给Class的对象,那么具体怎么做呢?)
这里说得java类的信息指的就是该java类的计算机的字节码:传给 Class cls1:
所以有三种方向得到
1.从类名得到:类名.class;
2.从具体的对象得到:Person p1=new Person();那么字节码:p1.getClass();
3.Class类它自身的静态方法,能指定得到某个类的字节码:Class.forName("java.Lang.String");
做反射的时候一般用第三种:因为写原程序的时候,我的类可能还没过创建;
注:八种数据类型和void,预定义的类名,直接类名.class就能创建Class。
1 String strl="abc"; 2 Class cls1=String.class; 3 Class cls2=strl.getClass(); 4 Class cls3=Class.forName("java.lang.String");//最后这钟有ClassNotFoundException 5 // 判断三者是否相同,因为多少取同一个类的字节码当然相同啦 6 System.out.println(cls1==cls2); 7 System.out.println(cls1==cls3); 8 9 // Class.isPrimitive()方法是判断是否是基本数据类型对应的Class 10 System.out.println(cls1.isPrimitive());//肯定是false 11 System.out.println(int.class.isPrimitive());//肯定是true 12 System.out.println(int.class==Integer.class);//Integer是类啊,大哥 13 System.out.println(int.class==Integer.TYPE);//不过这些保证类提供了一个方法.TYPE返回指定类型 14 System.out.println(int[].class.isPrimitive());//数组当然不是啦 15 System.out.println(int[].class.isArray());//但是Class.isArray可以判断是否数组
二、反射定义与意义:
反射就是把Java类中的各个成分映射成相应的Java类中(即是Class类),这个Class类提供一系列的方法,来获取其中的变量、方法、构造方法
修饰符、包等信息,这些信息用相应的实例对象来表示,他们就是Field、Method、Contructor、Package等;
既然一个类中的每个成员都能使用反射的方式来表示,那么怎么得到这些Class类的实例对象,这些实例对象怎么用,用在哪里,就是反射的要点:
三、Constructor(获得构造方法的类)
(1)获得途径:Class类中提供了一个方法:getConstructors()(注意:有s,代表获得这个Class类中所以的构造方法)
例如:Constructor[] constructor=Class.forName("java.lang.String").getConstructors;
getConstructor(参数)得到某个参数对应的特点的构造方法:
例如:
(2)可以调用Class类中getConstructor(String.class,int.class)方法获取指定的构造函数,
在使用newInstance(”zahns“,23)来获取具体的对象;
1 // 关于Constructor类,关于new String(new StirngBuilffer("abc")) 2 Constructor constructor1=String.class.getConstructor(StringBuffer.class);//得到这个特定参数对应的构造方法 3 String str= 4 (String) constructor1.newInstance(new StringBuffer("abc")); 5 //和new String(new StirngBuilffer("abc"))一个意思了,注意强转 6 System.out.println(str.charAt(2));//答案是c
(我的理解:getConstructor和newInstance这连个步骤分别可以说是声明传入特定类型的,然后就是具体传入什么类型的)
(3)Class.newInstance()方法:
String obj=(String)Class.forName("java..lang.String").newsInstance();
该方法内部先得到默认的构造方法,然后用构造方法创建对象;
Class类中的newinstance()方法是使用无参的构造函数创建对象,如果一个类没有参的构造函数,就不能这样创建了。
四、Field类(字段,变量)
*CLass.getFidle("变量名")方法可以获得类中指定的字段,然后用Field中get(类名对象)获得实际值;
*而如果字段是私有的时候使用暴力反射,用人getDeclaredField("变量名")获取,通过get(obj,"")
ReflecPoint 是自定义的类,x私有,y公用
1 ReflecPoint pt1=new ReflecPoint(3,5); 2 Field fielY=pt1.getClass().getField("y"); 3 // 这样依然不能获得y的值 4 System.out.println(fielY.get(pt1));//为5 5 // 那么私有的需要使用暴力反射 6 Field fielX=pt1.getClass().getDeclaredField("x"); 7 fielX.setAccessible(true);//这部是必须的 8 System.out.println(fielX.get(pt1));//为3
1 public class ReflecPoint { 2 private int x; 3 public int y; 4 5 String pp1="asfsdfsdg"; 6 String pp2="asfsasddg"; 7 String pp3="asfsdfaddg"; 8 public ReflecPoint(int x, int y) { 9 // super();默认的 10 this.x = x; 11 this.y = y; 12 } 13 public String toString(){ 14 return pp1+":"+pp2+":"+pp3; 15 } 16 }
1 ReflecPoint pt1=new ReflecPoint(3,5); 2 changeStringValue(pt1); 3 System.out.println(pt1); 4 } 5 //将变量中的String中的b改成a 6 private static void changeStringValue(Object obj) throws Exception { 7 Field[] fields=obj.getClass().getFields(); 8 for(Field field : fields){ 9 if(field.getType()==String.class){//比较的是字节码是否相同 10 String old=(String)field.get(obj); 11 String news=old.replace(‘b‘, ‘a‘); 12 field.set(obj, news); 13 } 14 }
五、Method类