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

时间:2023-02-19 16:46:00

      -----------android培训java培训、java学习型技术博客、期待与您交流!-----------

反射的基石--->Class类
java程序中的各个java类属于同一类事物。描述这类事物的java类名就是class。
对比提问:众多人用一个什么类表示?众多的java类用一个什么类表示?
 人-》Person
 java类-》Class
 对比提问:Person类代表人,它的实例对象就张三,李四这样一个个具体的人,
 class类代表java类,它的各个实例对象又分别对应什么呢?
    对应各个类在内存中的字节码,列如,Person类的字节码,ArrayList类的字节码,等等。
    一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,
    不同类的字节码是不同的,所以他们在内存中的内容是不同的,这一个个的内存空间分别用一个个的对象
  表示,这些对象显然具有相同的类型,这个类是什么呢?
 class 
 Class--->代表一类什么样的事物?
 Person p1=new Person();
 Person p2=new Person();
 Date
 Math
 Class cls1=Date.Class//字节码1;
 Class ClS2=Person.Class//字节码2;
 p1.getClass();
 Class.forName("java.lang.String");
 两种方法:作用:返回字节码
 第一种方法作用表示:曾经加载过字节码已经呆在java界面直接返回。
第二种方法的作用表示:java虚拟机里面还没有这份字节码,则用类加载器去加载,
把加载进来的字节码直接缓冲到虚拟机了面。以后要得到这份字节码就不用加载了
如何等到各个字节码对象的 实例对象(Class类型)
类名.class,例如:Ssytem.class
对象。getClass(),例如:class.forName("java.util.Date").
九个预定义Class实例对象:
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)
和关键字 void 也表示为 Class 对象。 
  参看 Class.isPrimitive方法帮助
  Int,class==Integer.TYPE
数组类型的Class实例对象
   Class.isArray()
   总之,只要在源程序中出现的类型,都有各自的Class实例对象。例如:int[],void 
 反射
  反射就是吧java类中的各种成分映射成相应的java类。例如,一个java类中用一个Class类的对象来表示。
  一个类中的组成部分,成员变量,方法,构造方法,包等等信息也用一个个的java类来表示,就像汽车是一个类,
  汽车中的发动机, 变速箱等等也是一个个的类。表示java类的class类显然要提供一个系列的方法,
  来获得其中的变量,方法构造方法,修饰符,包等信息,这些信息就用相应类的实例对象来表示。
  他们是Filed、Method、Contructor、Package等等 
 一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,
 通过调用Class类的方法可以得到这些实例对象后,
 得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。
 反射就是把java类中的各种成分映射成相应的java类
 method类代表:字节码中的一个方法。
 Constructor类代表某一个类中的一个构造方法。构造方法没有顺序。
 得到某一个类所有的构造方法:
 例如:Constructor[] constructor=
              啃死拽可特 Class.forName("java.lang.String").getConstructors();
 得到某个构造方法:
 例如:Constructor constructor=
 Class.forName("java.lang.String").getConstructor(StringBuffer.class);
 获得方法是要用到类型
 创建实例对象;
    通常方式:String str=new String(new StringBuffer("abc"));
   反射方式;String str=(String)Constructor.newInstance(new StringBuffer("abc")); 
   //调用获得的方法是要到上面相同类型的实例对象。
   Class.neInstance()方法。
   例如:String obj=(String)Class.forName("java.lang.String").newInstance();
   该方法内部想得到默认的构造方法,然后用该构造方法创建实例对象。
   该方法内部的具体代码是怎样写的呢?拥戴缓存机制来保存默认构造方法的实例对象。
 Field类
 Field类代表某一类中的成员变量。
 演示用elipse自动生成java类的构造方法。
 问题;得到的Field对象是对应到类上面的成员变量。还是对应到对象上的成员变量?类只有一个,而该类的实例对象
 有多个,如果是对象关联,那关联的是哪个对象呢》所以字段FieldX代表的是x的定义,而不是具体的x变量。
 Method类
 Method类代表某一个类的一个成员方法。
 得到类中的某个方法:
 例如:   Method charAt=
            Class.forName("java.lang.String").getMethod("charAt".int.class);
 调用方法:
 通常方法;System.out.println(str.charAt(1));
 反射方法:Ssytem.out.println(charAt.intVoke(Str,1));
    如果传递给Mehtod对象的invoke()方法的第一个参数为null,这有着什么样的意义
 呢?说明Mehtod对象对应的是一个静态的方法。
 jdk1.4和jdk1.5的invoke方法的区别:
 jdk1.5:public Object invoke(Object obj,Object...args)
 jdk1.4:public Object invoke(Object obj,Object[] args),即按jdk1.4的语法。
 需要将一个数组作为参数传递给invoke方法时,数组中国的每个元素分别对应被调用方法中的一个参数,所以,
 调用charAt方法的代码也可以用jdk1.4改写为charAt.invoke("str",new Object[]{})的形式
用反射方式执行某一个类中的main方法。
目标:
           写一个程序,这个程序能够根据用户提供的类名,区执行该类中的main方法。
  问题:
    启动java程序的main方法的参数是一个字符串数字。即public static void main(String[] args),
    通过反射方式来调用这个main方法。如何为invoke方法传递给参数呢?按jdk1.5的语法,整个数字是一个参数,
    而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数船队给,invoke方法时,
java会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按1.4的孕妇进行处理,即把数组打散
成若干个单独的参数,所以,在给main方法船队参数方式,不能使用代码
mainMethod.invoke(null,new String[]{"*****"}),javac只把他当做jdk1.4的语法进行理解,
而不把他当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
解决方案:
mainMethod.invoke(null,new Object[]{"***"});
mainMethod.invoke(null,(Object)new String[]{"***"}),编译器会作特殊处理,
编译时不把参数当作数组编译时不把参数当作数组看待,也就不会数组打散成若干个参数。
 
 数组的反射
  具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
  具有相同的Class实例对象。
  代表数组的class实例镀锡的getSuperClass()方法返回的父类为Object类对象的Class.
  基本类型的一维数组可以被当作Ojbect类型使用,不能当作Object类型使用,非基本类型的一维数组,    
 黑马程序员-----------反射
 
黑马程序员-----------反射

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

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

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

反射了面的配置文件。

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

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

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

HashCode的和equals的区别

equals:比较equal是判断两个对值是否相同。

HashSet就是采用哈希表存取对象的集合,它内部采用某个数字,n进行区域的港式对哈希表进行肥皂盒划分对象的存储区域。
    hashCode把集合分成若干区域,当从hashSet集合中查找某个对象是,java系统首先调用对象的hashCode()方法,获取该对象的哈希码。然后根据哈希码。
    找对应的存储区域,最后驱车该存储区域类的每个元素给对象进行equals方法比较 。这样不用变了集合中的所有元素就可以得到结果,相同不存储,不同才存储。
    防止内存溢出。储存好了,
    当对象被存进HashSet集合中后,就不能修改这个对象中的那些参与技术哈希值字段,否则,对象修改后的哈希值与最长存入的HashSet集合的哈希值就不同了。这种情况下,即使contians
    方法使用该对象的当前引用作为参数去hashset集合中检索对象,也将返回找不到对象结果。这样当值无法从HashSet结合汇总单独删除当前对象,从而造成内存泄露。
   

hashCode和equals方法相结合。

用hashCode想算出在哈希表所对应的位置,然后在用equals比较两个值是否相同,