黑马程序员-------反射

来源:互联网 发布:米维斯s和卡马d1c知乎 编辑:程序博客网 时间:2024/06/07 13:24

                                       黑马程序员-------反射

             ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------



反射:
 
 反射就是把Java类中的各种成分映射成相应的java类,例如,一个java
 类中用一个Class类的对象来表示,一个类中的组成部分: 成员变量 ,方法
 构造方法,包等等信息也用一个个的java类来表示,就像汽车是一个类,汽车中的发动机
 变速箱等等也是一个个的类,表示java类的Class类显然要提供一系列的方法来获得
 其中的变量,方法,构造方法,修饰符,包等信息,这些星系就是用相应的类的实例对象来表示,
 他们是Field,Method,Contructor,Package等等.





java程序中的各个java类属于同一类事物,描述这类食物的java类名就是Class


众多的人用一个类表示就是  人类-->person
众多的类用一个类表示就是  class类--->Class


 反射的基石-> Class类--->代表一类什么事物?
java中的类用于描述一类食物的共性,该类失误有什么特性,没有什么特性,至于这个特性值是什么
则是由这个类的实例对象来确定,不同的实例对象有不用的属性值,java程序中的各个java类他们是否
属于这一类事物,是不是可以用一个类来描述这类事物呢?类的名字,累的访问属性,类所属的包名,字段名称
列表,方法名称的列表,等等.学习反射首先要明白Class这个类


Person p1 = new Person();
Person p2 = new Person();


Date 


Math
 
Class cla1 = Date.class//字节码1;
Clsaa cla2 = Person.class//字节码2;


p1.getClass();获得属于p1 的字节码


Class.forName("java.lang.String")//获得这个类的字节码
返回方式有两种:
   1.这段字节码曾经被加载过已经在java虚拟机中 直接返回
   2.java虚拟机中还没有这段字节码,则用类加载器去加载,把加载进来的字节码缓存到java虚拟机中
   以后需要这段字节码就不用再加载了


 获得各个字节码对应的实力对象(Class类型)


   1.类名.class 例如System.class
   2.对象.getClass(),例如,new Date().getClass()
   3.Class.forName("类名"),例如Class.forName("java.util.Date");


九个预定义Class实例对象:


  八个基本数据类型
  以及一个 void
 
  数组类型的Class实例对象是
   Class.isArray();
   总之只要是在源程序中出现的类型,都有各自的Class实例对象 例如 int[]  void...






 一个类中的每个成员都可以用相应的反射API类的一个实力对象来表示,通过调用Class类的方法
 可以得到这些实例对象
  得到这些实例对象之后有什么用,怎么用?
  这正是放射的要点.


    Constructor类  //构造方法类
 代表字节码中的构造方法
  例子: 
   Constructor[] constructor = Class.forName("java.lang.String").getConstructor();
   获得String类中的所有构造方法
   
   Constructor constructor =
           Class.forName("java.lang.String").getConstructor(StringBuffer.class);
            //获得方法时要用到类型


创建实例对象:


   

//new String(new StringBuffer("abc"))   Constructor constructor1 = String.class.getConstructor(StringBuffer.class);  String str2 =(String)constructor1.newInstance(new StringBuffer("abc"));  //并不知道是String类型  所以需要类型转换      //调用获得的方法时要用到上面相同类型的对象




 class--->constructor--->new Object


   Class.newInstance()方法:
   例子:
     String obj = (String)Class.forName("java.lang.String").newInstance();


Fidle类 // 成员变量类
 
 1.Field类带包某个类中的一个成员变量
 2.演示用eclipse自动生成java类的构造方法
 3.问题:
     得到Field对象是应用到类上面的成员变量,还是应用到对象上面的成员变量?

类只有一个,而该类的实力对象有多少个,如果是与对象关联,那关联的是那个对象?
所以字段FieldX代表的是X的定义,而不是具体的变量



  实例代码:

      

package day1;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;public class ReflectTest {   public static void main(String[] args) throws Exception   {   String str1 = "abc";   Class cls1 = str1.getClass();   Class cls2 = String.class;   Class cls3 = Class.forName("java.lang.String");   System.out.println(cls1 ==cls2);   System.out.println(cls1 ==cls3);      System.out.println(cls1.isPrimitive());   System.out.println(int.class.isPrimitive());//是否是原始类型   System.out.println(int.class ==Integer.class);//false   System.out.println(int.class == Integer.TYPE);   System.out.println(int[].class.isPrimitive());   System.out.println(int[].class.isArray());//是否是数组类型      //new String(new StringBuffer("abc"))   Constructor constructor1 = String.class.getConstructor(StringBuffer.class);  String str2 =(String)constructor1.newInstance(new StringBuffer("abc"));   System.out.println(str2.charAt(2));     ReflectPoint  pt1 = new ReflectPoint(3,5);  Field fieldY = pt1.getClass().getField("y");    //fieldY的值是多少? 5?????  错  field 不是对象上的变量,而是类上,要用它去取某个对象上对应的值  System.out.println( fieldY.get(pt1));    Field fieldX = pt1.getClass().getDeclaredField("x");  fieldX.setAccessible(true);  System.out.println(fieldX.get(pt1));        }}

 Method类代表某个类中的一个成员方法
得到类中某一个方法的例子:
Mehtod methodCharAt = Class.forName("java.lang.String").getMethod("charAt",int.class);


调用方法 
  通常方法:System.out.println(str.charAt(1));
  反射方法:System.out.println(methodCharAt.invoke(str,1));
     如果传递给Method对象的invoke()方法的一个参数为null,这意味着Method对象对应的是一个静态方法


JDK1.4和JDK1.5的invoke()方法的区别:
  JDK1.5:public Object invoke(Object,Object...args);
  JDK1.4:public Object invoke(Object,Object[] args); 即按1.4的语法,需要将一个数组
  作为参数传递给invoke()方法时,数组中的每一个元素分别对应被调用方法中的一个参数,所以调用
  CharAt()方法的代码也可以用JDK1.4改写为charAt.invoke("str",new Object[]{1});的形式   


数组反射:
 具有相同位数和元素类型的数组属于同一个类型,
 即具有相同的Class实例对象.


 代表数组的Class实例对象的getSuperClass()方法放回的父类Object类对应的Class


 基本类型的一维数组可以被当作Object类型使用,不能当作Object[] 类型使用
 给基本类型的一维数组

             代码:

               

   int[] a = new int[3];    int[] a1= new int[4];int[][] a3= new int[3][4];    String[] a4 = new String[3];    System.out.println(a.getClass() == a1.getClass());       //不想等的数组类型字节码    // System.out.println(a.getClass() == a4.getClass());   System.out.println(a1.getClass().getName()+","+a3.getClass().getName()+","+a4.getClass().getName());   System.out.println(a1.getClass().getSuperclass().getName());   System.out.println(a4.getClass().getSuperclass().getName());   //     Object aObj1 = a1;     Object aObj2 =a4;     //Object[] aObj3 = a1;  //int[] 类型数组不是Object类     Object[] aObj4 = a3;     Object[] aObj5 = a4;Arrays.asList()方法处理 int[] 和String[]时的差异. System.out.println(a1);     System.out.println(a4);     System.out.println(Arrays.asList(aObj1));//[[I@1034bb5]因为在jDK1.4中传入的是一个Object[] 数组,所以走1.5版本 闯入的是一个对象而不是一个数组          System.out.println(Arrays.asList(a4));  //[a, b, c, d]  

反射的作用------>>>实现框架功能
  框架与框架要解决的核心问题
   我做房子卖给用户主,由用户自己安装门窗和空调,我做的就是房子的框架,用户需要使用我的框架
   把门窗插进我提供的框架中,框架与工具类有区别,工具类呗用户的类调用,而框架则是调用用户提供的类


 框架要解决的核心问题
   我在写框架(房子)时,你这个用户可能孩子啊上小学,还不会写程序,我写的框架程序怎样能调用你以后
   的类(门窗)呢?
   因为在写程序时无法知道要调用的类名,所以在程序无法直接new某个类的实例对象了,而要用反射方式来做

   

              ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


0 0