-----------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比较两个值是否相同,