反射


反射不是1.5新特性,是从1.2开始就有的,三大框架以及一些小框架都要用到反射技术

         JAVA反射技术,不像我们开始学习那样,编写好一个一个类,如果想要调用别的类方法,直接调用就行(不同包,得加载包,静态属性:  类名.属性,非静态属性:对象.属性)。它是一种动态的机制,主要用在框架中,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。


   我的理解:
         在程序中设置一个变量,这个变量的值在配置文件中赋值,如变量classname, 在程序中我们用到的类名是什么?答案是不知道。我们只能通过反射技术,通过变量classname来找我们用到的类。

          变量classname的值,在配置文件中设置,可以修改。我们配置哪个类,程序中就找哪个类来加载。

 好处:

            这样如果我们对程序进行功能扩展,就不需要修改源代码了。新写出代码后,设置配置文件就行了


          比如在反射中,调用一个未知类的main(),未知类是后来的。这个反射就实现了一个小框架。框架是提前做好的,框架调用用户的类,就像房子是框架,新门是用户类。反射做的框架有个好处:将来的类可以调用以前的类。框架不需要知道将来的类叫么。


以上是我对反射总的理解,下面是反射的知识点


反射的基础:Class类

        Class类:这个类是把我们写的那些普通类当做对象,向上抽取出来的类。

             例如,一个Java类中用一个Class类的对象来表示一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个

Java类来表示。就像汽车是一个类,其中的发动机,变速箱等等也是一个类。

             表示Java类的Class类显然要提供一系列的方法,来获取其中的变量,方法,构造方法,修饰符,包等信息。

些信息就是用相应类的实例对象来表示,他们是Field、Method、Contructor、Package等等。

       Class类的实例对象是字节码文件,什么是字节码?

        一个类被加载器加载到内存中占有一片存储空间,这个空间里面的内容就说字节码;不同类的字节码是不同的,所以它们在内    存中的内容是不同的。我们编译程序后所生成的类.class文件就是字节码文件。


         九个预定义的Class对象:
byte,short,int,long,char,float,double,boolean以及关键字void。




得到Class类的三种方式

1.类名.class 
    如:Person.class;


2.对象.getclass();
       如:得到创建该对象的字节码:new Demo().getClass(); 


3.Class.forName():
     如: Class.forName("Java.util.date");返回字节码。
forName()方法先在内存中判断有没有字节码,有就返回,没有就用类加载器加载一个,然后在返回。


注意:看到上面三个方法,是不是有个疑问,方法1和方法2,用到了类名和对象名,和反射机制不符合啊?

           确实, 方法1和方法2不符合,这里说的是得到Class类的方式。在反射中我们用到的时方法3。



字节码文件就是把所有类的字节码文件抽取出的共性(属性、方法、构造函数)封装为一个统一的Class类,
而每个字节码文件就是这个Class类的一个实例对象。

但是把每个类的字节码文件的属性、方法、构造函数等共性分别抽取成一个个类,分别是Field类(描述属性的共性),

Method类(描述方法的共性),Constructor类(描述构造方法的共性)

可以Class对象可以调用Class类的方法得到这些类的对象:

Field   getField();
Mehod   getMehod();

Constructor getConstructor()等等。

package fs1;  
  
import java.lang.reflect.*;  
import java.util.*;  
  
import java.*;  
class Person{  
    private String name;  
    private int age;  
    public Person(String name, int age) {  
        super();  
        this.name = name;  
        this.age = age;  
    }  
      
      
}  
public class fanshe {  
  
    public static void main(String[] args) throws Exception {  
        // TODO Auto-generated method stub  
        String s1="abc";  
        sop(Person.class);  
        Person p=new Person("lisi",23);  
        //sop(Person.getClass());  
        System.out.println(123);  
          
            //sop(Class.forName("Java.lang.String"));  
        Class c1=String.class;  
        Class c2=s1.getClass();  
        Class c3=Class.forName("java.lang.String");  
        sop(c1==c2);  
        sop(c1==c3);  
        sop(c3==c2);  
          
        sop(new String("abc").getClass().getFields());  
        List l1=new ArrayList();  
        Constructor[] cons=Class.forName("java.lang.String").getConstructors();  
        //获取构造方法。可以通过构造方法构造实例对象,得到方法的时候需要参数列型  
        Constructor cons1=String.class.getConstructor(StringBuffer.class);  
        //用获取的构造方法创建实例对象,调用活动的方法时,也需要有类型  
        String  str2=(String) cons1.newInstance(new StringBuffer("abc"));  
        sop(str2.charAt(2));  
        ReflectPoint pt1=new ReflectPoint(3,5);  
        //该方法只有私有的草可以获得  
        Field fieldY=pt1.getClass().getField("y");  
      
        sop(fieldY.get(pt1));  
        Field fieldX=pt1.getClass().getDeclaredField("x");  
        fieldX.setAccessible(true);  
        sop(fieldX.get(pt1));  
        changeStringValue(pt1);  
        sop(pt1);  
        //Method类,代表某一个类中的成员方法  
        Method methodCharAt=String.class.getMethod("charAt", int.class);  
        sop(methodCharAt.invoke(s1, 1));  
        //获取main方法  
        String startingClassName=args[0];  
        Method mainMethod=Class.forName(startingClassName).getMethod("main", String[].class);  
        //使用一下两种方式调用main方法  
        //把整个数组打包为一个数组,因为为了兼容1.4要对数组进行依次解包  
        mainMethod.invoke(null, new Object[]{new String[]{"11","22","33"}});  
        //生命该数组是一个对象  
        //mainMethod.invoke(null, (Object)new String[]{"11","22","33"});  
        int[] a1=new int[]{1,2,3};  
        int[] a2=new int[4];  
        int[][] a3=new int[2][3];  
        String[] a4=new String[]{"a","b","c"};  
        //对象要得到字节码组要使用方法,不能直接用。class获取  
        sop(a1.getClass()==a2.getClass());  
        sop(a1.getClass()==a3.getClass());  
        sop(a1.getClass()==a4.getClass());  
        sop(a1.getClass().getName());  
        sop(a1.getClass().getSuperclass().getName());  
        Object Obj1=a1;  
        Object Obj2=a4;  
        //基本数据类型的数组是无法装入Object数组中的  
        //Object[] Obj3=a1;  
        Object[] Obj4=a3;  
        Object[] Obj5=a4;  
        sop(a1);  
        sop(a4);  
        //int类型的数组不能传入Object【】中,  
        sop(Arrays.asList(a1));  
        sop(Arrays.asList(a4));  
        Object obj=null;  
        printObject(a1);  
        printObject("abc");  
          
          
    }  
    private static void printObject(Object obj) {  
        Class clazz=obj.getClass();  
        if(clazz.isArray()){  
            int len=Array.getLength(obj);  
            for(int i=0;i<len;i++){  
                sop(Array.get(obj, 1));  
            }  
        }else{  
            sop(obj);  
        }  
          
    }  
    private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {  
        Field[] fields=obj.getClass().getFields();  
        for(Field field: fields){  
            //使用==比较两个字节码,因为两个字节码有可能是同一个  
            if(field.getType()==String.class){  
                String oldValue=(String) field.get(obj);  
                String newValue=oldValue.replace('b', 'a');  
                field.set(obj, newValue);  
            }  
        }  
          
    }  
    public static void sop(Object obj){  
        System.out.println(obj);  
    }  
  
}  
class Test{  
    public static void main(String[] args){  
        System.out.println(123);  
        }  
    }  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值