当前位置:文档之家› java中hashcode()和equals()的详解

java中hashcode()和equals()的详解

java中hashcode()和equals()的详解
java中hashcode()和equals()的详解

hashcode方法浅析

有许多人学了很长时间的Java,但一直不明白hashCode方法的作用,我来解释一下吧。首先,想要明白hashCode的作用,你必须要先知道Java中的集合。总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。如果详细讲解哈希算法,那需要更多的文章篇幅,我在这里就不介绍了。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不

是)。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode 方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。所以,Java对于eqauls方法和hashCode方法是这样规定的:1、如果两个对象相同,那么它们的hashCode值一定要相同;2、如果两个对象的hashCode相同,它们并不一定相同上面说的对象相同指的是用eqauls方法比较。你当然可以不按要求去做了,但你会发现,相同的对象可以出现在Set集合中。同时,增加新元素的效率会大大下降。

java中hashcode()和equals()的详解

1. 首先equals()和hashcode()这两个方法都是从object类中继承过来的。

equals()方法在object类中定义如下:

public boolean equals(Object obj) {

return (this == obj);

}

很明显是对两个对象的地址值进行的比较(即比较引用是否相同)。但是我们必需清楚,当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法。比如在String类中如下:

public boolean equals(Object anObject) {

if (this == anObject) {

return true;

}

if (anObject instanceof String) {

String anotherString = (String)anObject;

int n = count;

if (n == anotherString.count) {

char v1[] = value;

char v2[] = anotherString.value;

int i = offset;

int j = anotherString.offset;

while (n-- != 0) {

if (v1[i++] != v2[j++])

return false;

}

return true;

}

}

return false;

}

很明显,这是进行的内容比较,而已经不再是地址的比较。依次类推Double、Integer、Math。。。。等等这些类都是重写了equals()方法的,从而进行的是内容的比较。当然了基本类型是进行值的比较,这个没有什么好说的。

我们还应该注意,Java语言对equals()的要求如下,这些要求是必须遵循的:

?对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。

?反射性:x.equals(x)必须返回是“true”。

?类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。

?还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。

?任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。

以上这五点是重写equals()方法时,必须遵守的准则,如果违反会出现意想不到的结果,请大家一定要遵守。

2. 其次是hashcode() 方法,在object类中定义如下:

public native int hashCode();

说明是一个本地方法,它的实现是根据本地机器相关的。当然我们可以在自己写的类中覆盖hashcode()方法,比如String、Integer、Double。。。。等等这些类都是覆盖了hashcode()方法的。例如在String类中定义的hashcode()方法如下:

public int hashCode() {

int h = hash;

if (h == 0) {

int off = offset;

char val[] = value;

int len = count;

for (int i = 0; i < len; i++) {

h = 31*h + val[off++];

}

hash = h;

}

return h;

}

解释一下这个程序(String的API中写到):

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

使用int 算法,这里s[i] 是字符串的第i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希码为0。)

3.这里我们首先要明白一个问题:

equals()相等的两个对象,hashcode()一定相等;

equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。

反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。解释下第3点的使用范围,我的理解是在object、String等类中都能使用。在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了;在String类中,equals()返回的是两个对象内容的比较,当两个对象内容相等时,

Hashcode()方法根据String类的重写(第2点里面已经分析了)代码的分析,也可知道hashcode()返回结果也会相等。以此类推,可以知道Integer、Double等封装类中经过重写的equals()和hashcode()方法也同样适合于这个原则。当然没有经过重写的类,在继承了object 类的equals()和hashcode()方法后,也会遵守这个原则。

4.谈到hashcode()和equals()就不能不说到hashset,hashmap,hashtable中的使用,具体是怎样呢,请看如下分析:

Hashset是继承Set接口,Set接口又实现Collection接口,这是层次关系。那么hashset是根据什么原理来存取对象的呢?

在hashset中不允许出现重复对象,元素的位置也是不确定的。在hashset中又是怎样判定元素是否重复的呢?这就是问题的关键所在,经过一下午的查询求证终于获得了一点启示,和大家分享一下,在java的集合中,判断两个对象是否相等的规则是:

1),判断两个对象的hashCode是否相等

如果不相等,认为两个对象也不相等,完毕

如果相等,转入2)

(这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大大降低,所以我们这里将其做为必需的。后面会重点讲到这个问题。)

2),判断两个对象用equals运算是否相等

如果不相等,认为两个对象也不相等

如果相等,认为两个对象相等(equals()是判断两个对象是否相等的关键)

为什么是两条准则,难道用第一条不行吗?不行,因为前面已经说了,hashcode()相等时,equals()方法也可能不等,所以必须用第2条准则进行限制,才能保证加入的为非重复元素。比如下面的代码:

public static void main(String args[]){

String s1=new String("zhaoxudong");

String s2=new String("zhaoxudong");

System.out.println(s1==s2);//false

System.out.println(s1.equals(s2));//true

System.out.println(s1.hashCode());//s1.hashcode()等于s2.hashcode()

System.out.println(s2.hashCode());

Set hashset=new HashSet();

hashset.add(s1);

hashset.add(s2);

/*实质上在添加s1,s2时,运用上面说到的两点准则,可以知道hashset认为s1和s2是相等的,是在添加重复元素,所以让s2覆盖了s1;*/

Iterator it=hashset.iterator();

while(it.hasNext())

{

System.out.println(it.next());

}

最后在while循环的时候只打印出了一个”zhaoxudong”。

输出结果为:false

true

-967303459

-967303459

这是因为String类已经重写了equals()方法和hashcode()方法,所以在根据上面的第1.2条原则判定时,hashset认为它们是相等的对象,进行了重复添加。

但是看下面的程序:

import java.util.*;

public class HashSetTest

{

public static void main(String[] args)

{

HashSet hs=new HashSet();

hs.add(new Student(1,"zhangsan"));

hs.add(new Student(2,"lisi"));

hs.add(new Student(3,"wangwu"));

hs.add(new Student(1,"zhangsan"));

Iterator it=hs.iterator();

while(it.hasNext())

{

System.out.println(it.next());

}

}

}

class Student

{

int num;

String name;

Student(int num,String name)

{

this.num=num;

https://www.doczj.com/doc/587597601.html,=name;

}

public String toString()

{

return num+":"+name;

}

}

输出结果为:

1:zhangsan

1:zhangsan

3:wangwu

2:lisi

问题出现了,为什么hashset添加了相等的元素呢,这是不是和hashset的原则违背了呢?回答是:没有

因为在根据hashcode()对两次建立的new Student(1,"zhangsan")对象进行比较时,生成的是不同的哈希码值,所以hashset把他当作不同的对象对待了,当然此时的equals()方法返回的值也不等(这个不用解释了吧)。那么为什么会生成不同的哈希码值呢?上面我们在比较s1和s2的时候不是生成了同样的哈希码吗?原因就在于我们自己写的Student类并没有重新自己的hashcode()和equals()方法,所以在比较时,是继承的object类中的hashcode()方法,呵呵,各位还记得object类中的hashcode()方法比较的是什么吧!!

它是一个本地方法,比较的是对象的地址(引用地址),使用new方法创建对象,两次生成的当然是不同的对象了(这个大家都能理解吧。。。),造成的结果就是两个对象的hashcode()返回的值不一样。所以根据第一个准则,hashset会把它们当作不同的对象对待,自然也用不着第二个准则进行判定了。那么怎么解决这个问题呢??

答案是:在Student类中重新hashcode()和equals()方法。

例如:

class Student

{

int num;

String name;

Student(int num,String name)

{

this.num=num;

https://www.doczj.com/doc/587597601.html,=name;

}

public int hashCode()

{

return num*name.hashCode();

}

public boolean equals(Object o)

{

Student s=(Student)o;

return num==s.num && name.equals(https://www.doczj.com/doc/587597601.html,);

}

public String toString()

{

return num+":"+name;

}

}

根据重写的方法,即便两次调用了new Student(1,"zhangsan"),我们在获得对象的哈希码时,根据重写的方法hashcode(),获得的哈希码肯定是一样的(这一点应该没有疑问吧)。

当然根据equals()方法我们也可判断是相同的。所以在向hashset集合中添加时把它们当作重复元素看待了。所以运行修改后的程序时,我们会发现运行结果是:

1:zhangsan

3:wangwu

2:lisi

可以看到重复元素的问题已经消除。

关于在hibernate的pojo类中,重新equals()和hashcode()的问题:

1),重点是equals,重写hashCode只是技术要求(为了提高效率)

2),为什么要重写equals呢,因为在java的集合框架中,是通过equals来判断两个对象是否相等的

3),在hibernate中,经常使用set集合来保存相关对象,而set集合是不允许重复的。我们再来谈谈前面提到在向hashset集合中添加元素时,怎样判断对象是否相同的准则,前面说了两条,其实只要重写equals()这一条也可以。

但当hashset中元素比较多时,或者是重写的equals()方法比较复杂时,我们只用equals()方法进行比较判断,效率也会非常低,所以引入了hashcode()这个方法,只是为了提高效率,但是我觉得这是非常有必要的(所以我们在前面以两条准则来进行hashset的元素是否重复的判断)。

比如可以这样写:

public int hashCode(){

return 1;}//等价于hashcode无效

这样做的效果就是在比较哈希码的时候不能进行判断,因为每个对象返回的哈希码都是1,每次都必须要经过比较equals()方法后才能进行判断是否重复,这当然会引起效率的大大降低。

我有一个问题,如果像前面提到的在hashset中判断元素是否重复的必要方法是equals()方法(根据网上找到的观点),但是这里并没有涉及到关于哈希表的问题,可是这个集合却叫hashset,这是为什么??

我想,在hashmap,hashtable中的存储操作,依然遵守上面的准则。所以这里不再多说。这些是今天看书,网上查询资料,自己总结出来的,部分代码和语言是引述,但是千真万确是自己总结出来的。有错误之处和不详细不清楚的地方还请大家指出,我也是初学者,所以难免会有错误的地方,希望大家共同讨论。

1. '=='是用来比较两个变量(基本类型和对象类型)的值是否相等的,如果两个变量是基本类型的,那很容易,直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用(即地址)。对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals 方法了。

2. Object类中的equals方法就是用'=='来比较的,所以如果没有重写equals 方法,equals和==是等价的。

通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。

3. Object类中的hashCode是返回对象在内存中地址转换成的一个int值(可以就当做地址看)。所以如果没有重写hashCode方法,任何对象的hashCode

都是不相等的。通常在集合类的时候需要重写hashCode方法和equals方法,因为如果需要给集合类(比如:HashSet)添加对象,那么在添加之前需要查看给集合里是否已经有了该对象,比较好的方式就是用hashCode。

4. 注意的是String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。

5. equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。

以下是测试代码。

Java代码

1.public class Equals_HashCode {

2.public static void main(String[] args) {

3.String a = new String("str");

4.String b = new String("str");

5.System.out.println(a==b);

6.System.out.println(a.equals(b));

7.System.out.println(a.hashCode());

8.System.out.println(b.hashCode());

9.// 输出false true 114225 114225

10. class A{

11. String str;

12. int i;

13. public A(String str, int i) {

14. super();

15. this.str = str;

16. this.i = i;

17. }

18. }

19. A aA = new A("str",1);

20. A bA = new A("str",1);

21. System.out.println(aA==bA);

22. System.out.println(aA.equals(bA));

23. System.out.println(aA.hashCode());

24. System.out.println(bA.hashCode());

25. // 输

出false false 6413875 21174459

26. class B{

27. String str;

28. public B(String str){

29. this.str = str;

30. }

31. }

32. B aB = new B("str");

33. B bB = new B("str");

34. System.out.println(aB==bB);

35. System.out.println(aB.equals(bB));

36. System.out.println(aB.hashCode());

37. System.out.println(bB.hashCode());

38. // 输出false false 827574 17510567

39. class C{

40. int i;

41. public C(int i){

42. this.i = i;

43. }

44. }

45. C aC = new C(1);

46. C bC = new C(1);

47. System.out.println(aC==bC);

48. System.out.println(aC.equals(bC));

49. System.out.println(aC.hashCode());

50. System.out.println(bC.hashCode());

51. //输

出false false 27744459 28737396

52. }

53.

54.}

55.

java中equal和==的比较

java中equals方法和“==”的区别:

equals 方法是 https://www.doczj.com/doc/587597601.html,ng.Object 类的方法。

有两种用法说明:

(1)对于字符串变量来说,使用“==”和“equals()”方法比较字符串时,其比较方法不同。

“==”比较两个变量本身的值,即两个对象在内存中的首地址。

“equals()”比较字符串中所包含的内容是否相同。

比如:

String s1,s2,s3 = "abc", s4 ="abc" ;

s1 = new String("abc");

s2 = new String("abc");

那么:

s1==s2 是 false //两个变量的内存地址不一样,也就是说它们指向的对象不一样,

故不相等。

s1.equals(s2) 是 true //两个变量的所包含的内容是abc,故相等。

注意(1):

如果: StringBuffer s1 = new StringBuffer("a");

StringBuffer s2 = new StringBuffer("a");

结果: s1.equals(s2) //是false

解释:StringBuffer类中没有重新定义equals这个方法,因此这个方法就来自Object类,

而Object类中的equals方法是用来比较“地址”的,所以等于false.

注意(2):

对于s3和s4来说,有一点不一样要引起注意,由于s3和s4是两个字符

串常量所生成的变量,其中所存放的内存地址是相等的,

所以s3==s4是true(即使没有s3=s4这样一个赋值语句)

(2)对于非字符串变量来说,"=="和"equals"方法的作用是相同的都是用来比较其

对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象。

比如:

class A

{

A obj1 = new A();

A obj2 = new A();

}

那么:obj1==obj2是false

obj1.equals(obj2)是false

但是如加上这样一句:obj1=obj2;

那么 obj1==obj2 是true

obj1.equals(obj2) 是true

总之:equals方法对于字符串来说是比较内容的,而对于非字符串来说是比较

其指向的对象是否相同的。

== 比较符也是比较指向的对象是否相同的也就是对象在对内存中的的首地址。

String类中重新定义了equals这个方法,而且比较的是值,而不是地址。所以是true。

关于equals与==的区别从以下几个方面来说:

(1)如果是基本类型比较,那么只能用==来比较,不能用equals

比如:

public class TestEquals {

public static void main(String[] args)

{

int a = 3;

int b = 4;

int c = 3;

System.out.println(a == b);//结果是false

System.out.println(a == c);//结果是true

System.out.println(a.equals(c));//错误,编译不能通过,equals方法

//不能运用与基本类型的比较

}

}

(2)对于基本类型的包装类型,比如Boolean、Character、Byte、Shot、Integer、Long、Float、Double等的引用变量,==是比较地址的,而equals是比较内容的。比如:

public class TestEquals {

public static void main(String[] args)

{ Integer n1 = new Integer(30);

Integer n2 = new Integer(30);

Integer n3 = new Integer(31);

System.out.println(n1 == n2);//结果是false 两个不同的Integer对象,故其地址不同,

System.out.println(n1 == n3);//那么不管是new Integer(30)还是new Integer(31) 结果都显示false

System.out.println(n1.equals(n2));//结果是true 根据jdk文档中的说明,n1与n2指向的对象中的内容是相等的,都是30,故equals比较后结果是true

System.out.println(n1.equals(n3));//结果是false 因对象内容不一样,一个是30一个是31

}

}

这是Integer的实例,如果是其他的比如Double、Character、Float等也一样。

(3)注意:对于String(字符串)、StringBuffer(线程安全的可变字符序列)、StringBuilder(可变字符序列)这三个类作进一步的说明。

(a)首先,介绍String的用法,请看下面的实例:

public class TestEquals {

public static void main(String[] args) {

String s1 = "123";

String s2 = "123";

String s3 = "abc";

String s4 = new String("123");

String s5 = new String("123");

String s6 = new String("abc");

System.out.println(s1 == s2);//(1)true

System.out.println(s1.equals(s2));//(2)true

System.out.println(s1 == s3);//(3)flase

System.out.println(s1.equals(s3));//(4)flase

System.out.println(s4 == s5);//(5)flase

System.out.println(s4.equals(s5));//(6)true

System.out.println(s4 == s6);//(7)flase

System.out.println(s4.equals(s6));//(8)flase

System.out.println(s1 == s4);//(9)false

System.out.println(s1.equals(s4));//(10)true

}

}

答案解释:s1与s2分别指向由字符串常量”123” 创建的对象,在常量池中,只有一个对象,内容为123,有两个引用s1和s2指向这个对象,故这两个引用变量所指向的地址是相同的,因而(1)处的运行结果为true,又因为

s1.equals(s2)是比较s1和s2所指向的对象的内容是否相等,而我们知道这两个对象的内容都是字符串常量”123”,故标记(2)处的运行结果是true。

用同样的方法分析,s1和s3所指向的对象不一样,内容也不一样,故标记(3)和(4)处运行结果是false。

再看看s4和s5,这两个引用变量所指向的对象的内容都是一样的(内容都是123),但是这两个对象是用new操作符创建处类的,是在内存中分配两块空间给这两个对象的,因而这两个对象的内存地址不一样,故事两个不同的对象,标记(5)处的s4 == s5 运行结果为false,但是内容一样,故标记(6)处的

s4.equals(s5)运行结果为true。同理,s4和s6所指向的对象地址不同,内容也不相同。故标记(7)(8)处运行结果为false。

s1和s4分别指向两个不同的对象(之所以这样称呼,是因为这两个对象在内存中的地址不相同,故而对象不相同),故标记为(9)处的s1 == s4运行结果为false,而标记为(10)处的s1.equals(s4)运行结果疑问:乍一看结果,有点惊讶,为什么不是true呢,不是说 equals方法是比较内容的吗?

解释:不错,如果在新类中被覆盖了equals方法,就可以用来比较内容的。但是在上面的例子中类Value并没有覆盖Object中的equals方法,而是继承了该方法,因此它就是被用来比较地址的,又v1和v2的所指向的对象不相同,故标记(1)处的v1.equals(v2)运行结果为false,标记为(2)处的v1 == v2运行结果也为false。

JAVA反射机制(内含大量实例)

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ 、OpenC++ 、MetaXa和OpenJava等就是基于反射机制的语言。最近,反射机制也被应用到了视窗系统、操作系统和文件系统中。 反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。可以看出,同一般的反射概念相比,计算机科学领域的反射不单单指反射本身,还包括对反射结果所采取的措施。所有采用反射机制的系统(即反射系统)都希望使系统的实现更开放。可以说,实现了反射机制的系统都具有开放性,但具有开放性的系统并不一定采用了反射机制,开放性是反射系统的必要条件。一般来说,反射系统除了满足开放性条件外还必须满足原因连接(Causally-connected)。所谓原因连接是指对反射系统自描述的改变能够立即反映到系统底层的实

际状态和行为上的情况,反之亦然。开放性和原因连接是反射系统的两大基本要素。 Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。 二、Java中的类反射: Reflection 是 Java 程序开发语言的特征之一,它允许运行中的Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。 1.检测类: 1.1 reflection的工作机制 考虑下面这个简单的例子,让我们看看 reflection 是如何工作的。

一个例子让你了解Java反射机制

一个例子让你了解Java反射机制 JAVA反射机制: 通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没用,下面我们看看实践 Demo ~ Demo: 1.package cn.lee.demo; 2. 3.import https://www.doczj.com/doc/587597601.html,ng.reflect.Constructor; 4.import https://www.doczj.com/doc/587597601.html,ng.reflect.Field; 5.import https://www.doczj.com/doc/587597601.html,ng.reflect.InvocationTargetException; 6.import https://www.doczj.com/doc/587597601.html,ng.reflect.Method; 7.import https://www.doczj.com/doc/587597601.html,ng.reflect.Modifier; 8.import https://www.doczj.com/doc/587597601.html,ng.reflect.TypeVariable; 9. 10.public class Main { 11. /** 12. * 为了看清楚Java反射部分代码,所有异常我都最后抛出来给虚拟机处 理! 13. * @param args 14. * @throws ClassNotFoundException 15. * @throws InstantiationException 16. * @throws IllegalAccessException 17. * @throws InvocationTargetException 18. * @throws IllegalArgumentException 19. * @throws NoSuchFieldException 20. * @throws SecurityException 21. * @throws NoSuchMethodException 22. */

深入理解Java反射机制汇总

深入理解Java反射机制 本文较为详细的分析了Java反射机制。分享给大家供大家参考,具体如下: 一、预先需要掌握的知识(java虚拟机) java虚拟机的方法区: java虚拟机有一个运行时数据区,这个数据区又被分为方法区,堆区和栈区,我们这里需要了解的主要是方法区。方法区的主要作用是存储被装载的类的类型信息,当java虚拟机装载某个类型的时候,需要类装载器定位相应的class文件,然后将其读入到java虚拟机中,紧接着虚拟机提取class 中的类型信息,将这些信息存储到方法区中。这些信息主要包括: 1、这个类型的全限定名 2、这个类型的直接超类的全限定名 3、这个类型是类类型还是接口类型 4、这个类型的访问修饰符 5、任何直接超接口的全限定名的有序列表 6、该类型的常量池 7、字段信息 8、方法信息 9、除了常量以外的所有类变量 10、一个到class类的引用 等等(读者可以参考《深入java虚拟机》这本书的叙述) Class类: Class类是一个非常重要的java基础类,每当装载一个新的类型的时候,java虚拟机都会在java堆中创建一个对应于新类型的Class实例,该实例就代表此类型,通过该Class实例我们就可以访问该类型的基本信息。上面说到在方法区中会存储某个被装载类的类型信息,我们就可以通过Class实例来访问这些信息。比如,对于上面说到的信息Class中都有对应的方法,如下:

1、getName();这个类型的全限定名 2、getSuperClass();这个类型的直接超类的全限定名 3、isInterface();这个类型是类类型还是接口类型 4、getTypeParamters();这个类型的访问修饰符 5、getInterfaces();任何直接超接口的全限定名的有序列表 6、getFields();字段信息 7、getMethods();方法信息 等等(读者可以自己参看jdk帮助文档,得到更多的信息) 二、java反射详解 反射的概念:所谓的反射就是java语言在运行时拥有一项自观的能力,反射使您的程序代码能够得到装载到JVM中的类的内部信息,允许您执行程序时才得到需要类的内部信息,而不是在编写代码的时候就必须要知道所需类的内部信息,这使反射成为构建灵活的应用的主要工具。 反射的常用类和函数:Java反射机制的实现要借助于4个类:Class,Constructor,Field,Method;其中class代表的是类对象,Constructor-类的构造器对象,Field-类的属性对象,Method -类的方法对象,通过这四个对象我们可以粗略的看到一个类的各个组成部分。其中最核心的就是Class类,它是实现反射的基础,它包含的方法我们在第一部分已经进行了基本的阐述。应用反射时我们最关心的一般是一个类的构造器、属性和方法,下面我们主要介绍Class 类中针对这三个元素的方法: 1、得到构造器的方法 Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,Constructor[] getConstructors() -- 获得类的所有公共构造函数 Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关) Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关) 2、获得字段信息的方法

Java中类反射机制基本原理

Java中的类反射机制 一、反射的概念 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ 、Open C++ 、Meta Xa和Open Java等就是基于反射机制的语言。最近,反射机制也被应用到了视窗系统、操作系统和文件系统中。 反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。可以看出,同一般的反射概念相比,计算机科学领域的反射不单单指反射本身,还包括对反射结果所采取的措施。所有采用反射机制的系统(即反射系统)都希望使系统的实现更开放。可以说,实现了反射机制的系统都具有开放性,但具有开放性的系统并不一定采用了反射机制,开放性是反射系统的必要条件。一般来说,反射系统除了满足开放性条件外还必须满足原因连接(Causally-connected)。所谓原因连接是指对反射系统自描述的改变能够立即反映到系统底层的实际状态和行为上的情况,反之亦然。开放性和原因连接是反射系统的两大基本要素。 Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。 二、Java类反射 Reflection 是Java 程序开发语言的特征之一,它允许运行中的Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者C++ 中就没有办法在程序中获得函数定义相关的信息。 1.检测类 1.1 reflection的工作机制 考虑下面这个简单的例子,让我们看看reflection 是如何工作的。 import https://www.doczj.com/doc/587597601.html,ng.reflect.*; public class DumpMethods { public static void main(String args[]) { try { Class c = Class.forName(args[0]); Method m[] = c.getDeclaredMethods(); for (int i = 0; i < m.length; i++) System.out.println(m[i].toString()); } catch (Throwable e) { System.err.println(e); }

java反射机制详解与应用

java有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods1。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。 这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces (例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。 目前好多框架都会用到java的反射机制。比如struts2,sping,hibernate。 如果我们不用struts2,自己写一个类似的功能也是可以实现的,比如浏览器通过HTTP发送数据,而这些数据都是字符串,我们接受到这些字符串时,可以通过反射去构造一个对象(通过拦截器做成框架的功能),这样就可以用对象的get和set方法了,而不用原始的getPeremter 方法。事实上,在struts2出来之前,我们又不想用struts1的ActionForm就做过这样项目。 一、Class object 的产生方式有以下几种。 1、运用getClass() 注:每个class 都有此函数 String str = "abc"; Class c1 = str.getClass(); 2、运用static method Class.forName()(最常被使用) Class c1 = Class.forName ("https://www.doczj.com/doc/587597601.html,ng.String"); Class c2 = Class.forName ("java.awt.Button"); 3、运用.class 语法 Class c1 = String.class; Class c2 = java.awt.Button.class; 4、运用primitive wrapper classes的TYPE 语法 Class c1 = Integer.TYPE; Class c2 = Long.TYPE; 二、Java类反射中的主要方法 对于以下三类组件中的任何一类来说-- 构造函数、字段和方法-- https://www.doczj.com/doc/587597601.html,ng.Class 提供四种

Java反射访问私有变量和私有方法

Java反射访问私有变量和私有方法 引言 对于软件开发人员来说,单元测试是一项必不可少的工作。它既可以验证程序的有效性,又可以在程序出现BUG 的时候,帮助开发人员快速的定位问题所在。但是,在写单元测试的过程中,开发人员经常要访问类的一些非公有的成员变量或方法,这给测试工作带来了很大的困扰。本文总结了访问类的非公有成员变量或方法的四种途径,以方便测试人员在需要访问类非公有成员变量或方法时进行选择。 尽管有很多经验丰富的程序员认为不应该提倡访问类的私有成员变量或方法,因为这样做违反了Java 语言封装性的基本规则。然而,在实际测试中被测试的对象千奇百怪,为了有效快速的进行单元测试,有时我们不得不违反一些这样或那样的规则。本文只讨论如何访问类的非公有成员变量或方法,至于是否应该在开发测试中这样做,则留给读者自己根据实际情况去判断和选择。 方法一:修改访问权限修饰符 先介绍最简单也是最直接的方法,就是利用Java 语言自身的特性,达到访问非公有成员的目的。说白了就是直接将private 和protected 关键字改为public 或者直接删除。我们建议直接删除,因为在Java 语言定义中,缺省访问修饰符是包可见的。这样做之后,我们可以另建一个源码目录——test 目录(多数IDE 支持这么做,如Eclipse 和JBuilder),然后将测试类放到test 目录相同包下,从而达到访问待测类的成员变量和方法的目的。此时,在其它包的代码依然不能访问这些变量或方法,在一定程度上保障了程序的封装性。 下面的代码示例展示了这一方法。 清单1. 原始待测类 A 代码 public class A { private String name = null; private void calculate() { } }

java 6个机制

*克隆机制 克隆就是在内存中复制对象,Java克隆(Clone)是Java语言的特性之一,但在实际中应用比较少见。但有时候用克隆会更方便更有效率。(缺点应该是多分配了一块空间,占内存吧,如果数据量大,内存占用的就大) 对于克隆(Clone),Java有一些限制: 1、被克隆的类必须自己实现Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。Cloneable 接口实际上是个标识接口,没有任何接口方法。 2、实现Cloneable接口的类应该使用公共方法重写 Object.clone(它是受保护的)。某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。 3、在https://www.doczj.com/doc/587597601.html,ng.Object类中克隆方法是这么定义的: protected Object clone()throws CloneNotSupportedException{ } 创建并返回此对象的一个副本。表明是一个受保护的方法,同一个包中可见。 按照惯例,返回的对象应该通过调用 super.clone 获得。 克隆分为深克隆和浅克隆 浅度克隆:浅度克隆对于要克隆的对象,对于其基本数据类型的属性,复制一份给新产生的对象,对于非基本数据类型的属性,仅仅复制一份引用给新产生的对象,即新产生的对象和原始对象中的非基本数据类型的属性都指向的是同一个对象; 深度克隆:在浅度克隆的基础上,对于要克隆的对象非基本数据类型的属性对应的类,也实现克隆,这样对于非基本数据类型的属性,复制的不是同一份引用,即新产生的对象和原始对象中的非基本数据类型的属性指向的不是同一个对象。 *序列化机制 序列化也叫串行化,试讲对象转换成紧凑的二进制域的形式,使该对象具备可以被持久化即永久保存的特性。 序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。 这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。 如何序列化一个对象

java反射原理

Java反射机制 一、什么是反射机制 简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。 二、哪里用到反射机制 有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行代码, Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成驱动对象实例,并不知道它的具体含义。听了反射机制这节课后,才知道,原来这就是反射,现在很多开框架都用到反射机制,hibernate、struts都是用反射机制实现的。 三、反射机制的优点与缺点 为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,静态编译:在编译时确定类型,绑定对象,即通过。 动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多 态的应用,有以降低类之间的藕合性。 一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中 它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。

它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。 四、利用反射机制能获得什么信息 一句话,类中有什么信息,它就可以获得什么信息,不过前提是得知道类的名字,要不就没有后文了首先得根据传入的类的全名来创建Class对象。 Class c=Class.forName("className");注明:className必须为全名,也就是得包含包名,比如, https://www.doczj.com/doc/587597601.html,erInfo; Object obj=c.newInstance();//创建对象的实例 OK,有了对象就什么都好办了,想要什么信息就有什么信息了。 获得构造函数的方法 Constructor getConstructor(Class[] params)//根据指定参数获得public构造器 Constructor[] getConstructors()//获得public的所有构造器 Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器 Constructor[] getDeclaredConstructors()//获得public的所有构造器 获得类方法的方法 Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法 Method[] getMethods()//获得所有的public方法 Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public 的方法

JAVA反射

java 中的反射总结 刚开始学习java的时候真的很难理解反射到底是个什么东西 一些书籍,哪怕是很经典的书籍都解释的让人感觉懵懵的,或许的确是我太笨 况且,网上说在将来学习框架的时候需要经常应用到反射机制,这样一来总让人心里有些不安就方才偶然又把讲解反射的章节和视频看了一点,觉得能理解一些了 现在决定一鼓作气,边看边写,顺便把一些主要的内容和操作都记载到这里 我想,对于我这么一个笨笨的人来说,学习的最好方法也许就是不断重复 遇到不懂的知识就停下来把以往的重新学一遍,虽然浪费了很多时间,但对我也有些效果 我的理解是:所谓反射,就是根据一个已经实例化了的对象来还原类的完整信息 至少对我而言,我认为它带给我的好处是,让我从下往上的又了解了一遍面向对象 x_x 在此又痛恨一边那些厚部头们,把我的脑细胞搞死一片 Class类 如果要完成反射,那么必须了解Class类 实例1:通过对象取得包名和类名 1 2 3 4 5 6 7 8 9 10 11 12 13 package org.siu; class Test { } public class Demo { public static void main(String[] args) { Test t = new Test(); System.out.println(t.getClass()); System.out.println(t.getClass().getName()); } } 编译结果如下,注意包的编译方式即可 此处的getClass()方法是默认继承自Object类的

在java中,Object类是所有类的父类,同样,所有类的实例化对象也都是Class类的实例因此,这样一来就会牵扯到向上转型和向下转型的概念 由于向下转型的不安全因素,在这里泛型也会接踵而来 (不过我想说的是,此处的泛型设计很刺眼!尼玛,整个java的语法设计同样刺眼,超恶心!!!) 实例2:Class类的实例化 由于Class类没有构造方法,所以实例化Class类的方式有点特殊,有三种方式: ?对象.getClass( ) ?类.Class ?forName( )

java反射机制详解 及 Method.invoke解释

java反射机制详解及Method.invoke解释 JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够 知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。 1. 得到某个对象的属性 Java代码public Object getProperty(Object owner, String fieldName) throws Exception { Class ownerClass = owner.getClass(); Field field = ownerClass.getField(fieldName); Object property = field.get(owner); return property; } Class ownerClass = owner.getClass():得到该对象的Class。Field field = ownerClass.getField(fieldName):通过Class 得到类声明的属性。Object property = field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里

会报IllegalAccessException。2. 得到某个类的静态属性Java代码public Object getStaticProperty(String className, String fieldName) throws Exception { Class ownerClass = Class.forName(className); Field field = ownerClass.getField(fieldName); Object property = field.get(ownerClass); return property; } Class ownerClass = Class.forName(className) :首先得到这个类的Class。Field field = ownerClass.getField(fieldName):和上面一样,通过Class 得到类声明的属性。Object property = field.get(ownerClass) :这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取。3. 执行某对象的方法 Java代码public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception { Class ownerClass = owner.getClass(); Class[] argsClass = new Class[args.length]; for (int i = 0, j = args.length; i < j; i++) { argsClass[i] = args[i].getClass(); } Method method =

java反射机制的原理

Java反射机制的原理 在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,可以调用它的任意一个方法。 这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。 Java反射机制主要提供了以下功能 在运行时判断任意一个对象所属的类。 在运行时构造任意一个类的对象。 在运行时判断任意一个类所具有的成员变量和方法。 在运行时调用任意一个对象的方法 关于JA V A更多反射机制的资料以及跟高手学习机会,可以加到群422,然后就是912,加上最后的489,感觉还不错。现在才开始学反射机制没多久,差不多已经把这一块搞清楚了 反射的常用类和函数:Java反射机制的实现要借助于4个类:Class,Constructor,Field,Method;其中class代表的是类对象,Constructor -类的构造器对象,Field-类的属性对象,Method-类的方法对象,通过这四个对象我们可以粗略的看到一个类的各个组成部分。其中最核心的就是Class类,它是实现反射的基础,它包含的方法我们在第一部分已经进行了基本的阐述。应用反射时我们最关心的一般是一个类的构造器、属性和方法,下面我们主要介绍Class类中针对这三个元素的方法: 1、得到构造器的方法 Constructor getConstructor(Class[]params)--获得使用特殊的参数类型的公共构造函数, Constructor[]getConstructors()--获得类的所有公共构造函数

Constructor getDeclaredConstructor(Class[]params)--获得使用特定参数类型的构造函数(与接入级别无关) Constructor[]getDeclaredConstructors()--获得类的所有构造函数(与接入级别无关) 2、获得字段信息的方法 Field getField(String name)--获得命名的公共字段 Field[]getFields()--获得类的所有公共字段 Field getDeclaredField(String name)--获得类声明的命名的字段Field[]getDeclaredFields()--获得类声明的所有字段 3、获得方法信息的方法 Method getMethod(String name,Class[]params)--使用特定的参数类型,获得命名的公共方法 Method[]getMethods()--获得类的所有公共方法 Method getDeclaredMethod(String name,Class[]params)--使用特写的参数类型,获得类声明的命名的方法 Method[]getDeclaredMethods()--获得类声明的所有方法 在程序开发中使用反射并结合属性文件,可以达到程序代码与配置文件相分离的目的 如果我们想要得到对象的信息,一般需要“引入需要的‘包.类’的名称——通过new实例化——取得实例化对象”这样的过程。使用反射就可以变成“实例化对象——getClass()方法——得到完整的‘包.类’名称”这样的过程。

实验10Java反射技术

(1)利用反射机制编写一个程序,这个程序能把类中所有的成员变量赋值,并把操作信息输出到控制台。 package ex101; import https://www.doczj.com/doc/587597601.html,ng.reflect.Field; public class Demo { public static void main(String[] args) throws Exception{ Class c=null; Object obj=null; try { ////获取操作类Person所对应的Class对象 c=Class.forName("ex101.Person"); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } try { //使用Person类的class对象生成实例 obj=c.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } Field nameField=null; Field ageField=null; //获取Person类的name属性 nameField=c.getDeclaredField("name"); //获取Person类的age属性 ageField=c.getDeclaredField("age"); nameField.setAccessible(true); nameField.set(obj,"计算机科学与技术"); ageField.setAccessible(true); ageField.set(obj, 20); System.out.println("姓名:"+nameField.get(obj)); System.out.println("年龄:"+ageField.get(obj)); } } package ex101; public class Person { private String name; private int age; public Person(){ } } (2)利用反射机制编写一个程序,这个程序能指定调用类的某个方法及构

Java反射机制的工作原理详解

Java反射机制的工作原理详解 JAVA反射机制工作原理: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。 1. 得到某个对象的属性 1 public Object getProperty(Object owner, String fieldName) throws Exception { 2 Class ownerClass = owner.getClass(); 3 4 Field field = ownerClass.getField(fieldName); 5 6 Object property = field.get(owner); 7 8 return property; 9 } Class ownerClass = owner.getClass():得到该对象的Class。 Field field = ownerClass.getField(fieldName):通过Class得到类声明的属性。 Object property = field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。 2. 得到某个类的静态属性

1 public Object getStaticProperty(String className, String fieldName) 2 throws Exception { 3 Class ownerClass = Class.forName(className); 4 5 Field field = ownerClass.getField(fieldName); 6 7 Object property = field.get(ownerClass); 8 9 return property; 10 } Class ownerClass = Class.forName(className) :首先得到这个类的Class。 Field field = ownerClass.getField(fieldName):和上面一样,通过Class得到类声明的属性。 Object property = field.get(ownerClass) :这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取。 3. 执行某对象的方法 1 public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception { 2 3 Class ownerClass = owner.getClass(); 4 5 Class[] argsClass = new Class[args.length]; 6 7 for (int i = 0, j = args.length; i < j; i++) {

JAVA反射机制

Java反射机制 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ 、OpenC++ 、MetaXa和OpenJava等就是基于反射机制的语言。最近,反射机制也被应用到了视窗系统、操作系统和文件系统中。 反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。可以看出,同一般的反射概念相比,计算机科学领域的反射不单单指反射本身,还包括对反射结果所采取的措施。所有采用反射机制的系统(即反射系统)都希望使系统的实现更开放。可以说,实现了反射机制的系统都具有开放性,但具有开放性的系统并不一定采用了反射机制,开放性是反射系统的必要条件。一般来说,反射系统除了满足开放性条件外还必须满足原因连接(Causally-connected)。所谓原因连接是指对反射系统自描述的改变能够立即反映到系统底层的实际状态和行为上的情况,反之亦然。开放性和原因连接是反射系统的两大基本要素。 Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。 二、Java中的类反射: Reflection 是Java 程序开发语言的特征之一,它允许运行中的Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者C++ 中就没有办法在程序中获得函数定义相关的信息。 1.检测类: 1.1 reflection的工作机制 考虑下面这个简单的例子,让我们看看reflection 是如何工作的。 import https://www.doczj.com/doc/587597601.html,ng.reflect.*; public class DumpMethods { public static void main(String args[]) { try { Class c = Class.forName(args[0]); Method m[] = c.getDeclaredMethods(); for (int i = 0; i < m.length; i++) System.out.println(m[i].toString()); } catch (Throwable e) {

JAVA的内省机制(introspector)与反射机制(reflection)

JAVA的内省机制(introspector)与反射机制(reflection) 2010-05-05 20:49 相对而言,反射比内省更容易理解一点。用一句比较白的话来概括,反射就是让你可以通过名称来得到对象 ( 类,属性,方法 ) 的技术,这种技术比内省机制使用范围更广泛。例如我们可以通过类名来生成一个类的实例;知道了方法名,就可以调用这个方法;知道了属性名就可以访问这个属性的值。内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 API 存放于包 java.beans 中。一般的做法是通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。下面我们来看一个例子,这个例子把某个对象的所有属性名称和值都打印出来: Java代码 1.package MyTest; 2.public class bean { 3.private String id = null ; 4.private String name = null ; 5. 6.public String getId() { 7.return id; 8. } 9.public void setId(String id) { 10. this.id = id; 11. } 12. 13. public String getName() { 14. return name; 15. } 16. public void setName(String name) { 17. https://www.doczj.com/doc/587597601.html, = name; 18. } 19.} 20. 21.package MyTest; 22.import java.beans.BeanInfo; 23.import java.beans.EventSetDescriptor; 24.import java.beans.Introspector;

Java Filter过滤机制详解

Java Filter过滤机制详解 以前以为Filter只是一个特殊点的Servlet,用进只需在web.xml中配置一下拦截路径就可以了,可经过这两天的深入学习,才知道以前对Filter类的了解和使用都太过浅薄了。 在网上看了很多篇相关的技术文章,现提取它们中的精髓(我认为能说明问题的东西)及我个人的一些学习经验作如下总结,希望能帮助大家更好地理解Filter 的过滤机制。 要学习Filter,就必须先理解和掌握servlet的调用机制和流程。关于servlet,网上也有很多相关文章,大家若有不明白的可以到百度中搜一下,我这里为了突出重点就不多说了。好,下面进入正题。 一、什么是Filter Filter 技术是servlet 2.3 新增加的功能.servlet2.3是sun公司与2000年10月发布的,它的开发者包括许多个人和公司团体,充分体现了sun公司所倡导的代码开放性原则.由于众多的参与者的共同努力,servlet2.3比以往功能都强大了许多,而且性能也有了大幅提高. 它新增加的功能包括: 1. 应用程序生命周期事件控制; 2. 新的国际化; 3. 澄清了类的装载规则; 4. 新的错误及安全属性; 5. 不赞成使用HttpUtils 类; 6. 各种有用的方法; 7. 阐明并扩展了几个servlet DTD; 8. filter功能. 其中最重要的就是filter功能.它使用户可以改变一个request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开servlet时处理response.换种说法,filter其实是一个”servlet chaining”(servlet 链).一个filter 包括: 1. 在servlet被调用之前截获; 2. 在servlet被调用之前检查servlet request;

相关主题
文本预览
相关文档 最新文档