- 浏览: 1012708 次
- 性别:
- 来自: 福州
最新评论
-
guanxin2012:
大神,您好。非常感谢您贡献了IKExpression。我们现在 ...
分享开源表达式解析器IK-Expression2.0 -
qqgigas:
LZ,public boolean createUser(LD ...
Sun Directory Server/LDAP学习笔记(二)——API说明及代码样例 -
gao_shengxian:
Hibernate: update T_GX_TEST set ...
优雅Java编程 之 使用Hibernate存储Oracle Spatial对象 -
a78113534:
感谢大神,在安卓里面调用成功了。
发布IK Expression开源表达式解析器 V2.1.0 -
majiedota:
加油
来自开源支持者的第一笔捐赠
代码如下:
上述的 LOC_1 处和 LOC_2 处打印的ID完全相等, LOC_3处输出true(说明对象地址相同),BUT~~ LOC_4处输出是false;
给出FlowToken的equals实现
跟踪发现,实际进入equals的obj参数根本不是外面传入的那个token对象,中间过程被Hinernate的CGLIBLazyInitializer做了代理处理,发生了底层对象的变换。
开始大家都打死不信有这样的BUG,经过对jvm线程和变量编号的反复跟踪,BUG每次都重现。确认CGLIBLazyInitializer确有问题,但目前在国内互联网上没有找到相同的案例。这里提出,供javaeye上的大牛商讨!
如果我们一群人的诊断是对的,hibernate就隐藏了一个相当恐怖的bug咯!!!
我重新整理下, 首先这里有2个 token 和 taskInstance.getFlowToken(), 我把参数传入的token 称为 tokenA, 把 taskInstance.getFlowToken() 称为 tokenB.
楼主说 tokenB 是 hibernate 通过lazyload 产生的代理. 而根据 LOC_3 :token == taskInstance.getFlowToken() 打印的 true 的情况来看. 可以知道 tokenA 和 tokenB 都是hibernate代理的对象. 而且是同一个对象.
Hibernate lazy load的原理是 用cglib 生成当前 model 的子类. 重写他所有(根据hibernate定义)的 getter 和 setter 方法, 注意是getter, setter的,像equals应该不会被重写, 另外model 的所有final方法不会重写(所以个人很讨厌final, spring 框架里就一堆), 当你调用一个 getter 的时候他才从数据库取出真实的对象返回他的值
因为tokenA和tokenB都是被代理的对象, 所以在equals 直接调用 id 属性的话, 必然返回 null. 也有人说 这个时候hibernate 已经知道对象的id 了, 这个没错. 但知道id 也不一定会把他知道的id 放在id属性中吧.
所以equals内, 必须使用 getId() 来访问id. 楼主一开始没有用getter访问出错了, 后来经过大家指正把代码改成了
所以楼主等节后去公司里试验一下用getter来访问id, 我认为就不会有问题了, 最后我想说的是 这贴我也投了新手. 不是因为问题什么, 而是因为这个标题, 你们竟然会怀疑hibernate有bug. hibernate 这么常用的框架, equals这么常用的功能. 是不会有这么这么大的一个bug 的. 如果真的有的话, 也会立刻被修复. 我像表达的意思是 99.99% 的问题都是我们使用不当造成的, 不应该动不动就质疑框架类库, 这样的风气我认为是不应该被提倡的.
set.add(new C());
// true
System.out.println(set.contains(new C()));
这个的输出结果真是true吗
我发贴可不强调你说的,这样的说法容易歪楼哈!!
替换了对象的意思就是:cglib给我new了一个所有属性都=null的FlowToken对象,这个对象是FlowToken的一个proxy没错,但什么属性值都取不到,再次强调所有方法返回null。我不知道为啥发生这样的情况。
就当我故意歪楼好了,别搞半天就是楼上说的原因。
兄弟,你啥时候能把我说的测试代码运行一下,我其实不是很关心other.getClass(),我其实更关心this.getClass()。
没问题,不过代码环境在公司,节后一定运行一下!!
再次说明,希望大家把精力集中的问题本身哈。je上发贴就是为了技术而技术,灌水我上天涯,吹牛会去mopper的。
我发贴可不强调你说的,这样的说法容易歪楼哈!!
替换了对象的意思就是:cglib给我new了一个所有属性都=null的FlowToken对象,这个对象是FlowToken的一个proxy没错,但什么属性值都取不到,再次强调所有方法返回null。我不知道为啥发生这样的情况。
兄弟,你啥时候能把我说的测试代码运行一下,我其实不是很关心other.getClass(),我其实更关心this.getClass()。
这里的
怎么说也应该用 getter来访问把, 也就是
你可以看看我原来写的, 这标题取得, 确实不是 hibernate 的bug 啊
http://dev.sunteya.com/svn/flyer/trunk/core/src/main/java/com/sunteya/flyer/domain/AbstractEntity.java
兄弟,你说法是对的,但你没有解决我遇到的问题。我的问题是,传入equals方法的对象根本是个所有属性都是null的新对象,跟在equals外取到的对象不是一个东西。
非常郁闷啊,我也不希望是hibernate的bug,要知道,第一,我感情上很喜欢Hibernate;第二,我有大量的应用基于hibernate,它要出问题了,我可郁闷大发了!目前这个症状仅在我程序的一个地方出现;大部分情况是很正常的,but~~~谁知道下一次在哪里啊
这里的
怎么说也应该用 getter来访问把, 也就是
你可以看看我原来写的, 这标题取得, 确实不是 hibernate 的bug 啊
http://dev.sunteya.com/svn/flyer/trunk/core/src/main/java/com/sunteya/flyer/domain/AbstractEntity.java
感觉java阿姨已经有点不食人间烟火了,诸如此类的阿姨不知道人间还有我辈这等小老百姓在饱受煎熬,呵呵,牢骚一句。我觉得实践中的问题可能是影响广泛的问题,而非只有理论问题才能入java阿姨的法眼....
你的猜测是对的,在跟踪调试中,可以很明显的看到,调用equals方法时,CGLib接入了其中,这也正是我写这篇blog的原因,我们还请了公司的C++权威来协助跟踪,确定我们不是眼花了,或者代码错误,确实是被代理替换了对象。但我们不知道CGLib在怎样一种情况下,会发生这样的异常。(肯定不是每次都发生的,否则问题早就被发现了,呵呵)
/** * 判断当前流程实例上下文中,是否存在Blocking(阻挡性)的任务 * 规则 * 1.任务未结束 * 2.任务是必办理的 * 3.当前任务实例的token和执行上下文的token一致 * @param token * @return */ public boolean hasBlockingTaskInstances(FlowToken token) { boolean hasBlockingTasks = false; System.out.println("LOC_1 :" + token.getId()); Set<TaskInstance> taskInstances = flowInstance.getTaskInstances(); if (taskInstances!=null) { Iterator<TaskInstance> iter = taskInstances.iterator(); while ( (iter.hasNext()) && (!hasBlockingTasks)) { System.out.println("LOC_2 : " + taskInstance.getFlowToken().getId()); System.out.println("LOC_3 : " + token == taskInstance.getFlowToken()); System.out.println("LOC_4 : " + token.equals(taskInstance.getFlowToken()); TaskInstance taskInstance = (TaskInstance) iter.next(); if ( (! taskInstance.hasEnded()) //任务未结束 && (taskInstance.getIsBlocking()) //任务是必办理的 && (token!=null) && (token.equals(taskInstance.getFlowToken())) ) { hasBlockingTasks = true; } } } return hasBlockingTasks; }
上述的 LOC_1 处和 LOC_2 处打印的ID完全相等, LOC_3处输出true(说明对象地址相同),BUT~~ LOC_4处输出是false;
给出FlowToken的equals实现
/* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof FlowToken)) return false; final FlowToken other = (FlowToken) obj; if (id == null || other.id == null) { return false; } else if (!id.equals(other.id)) return false; return true; }
跟踪发现,实际进入equals的obj参数根本不是外面传入的那个token对象,中间过程被Hinernate的CGLIBLazyInitializer做了代理处理,发生了底层对象的变换。
开始大家都打死不信有这样的BUG,经过对jvm线程和变量编号的反复跟踪,BUG每次都重现。确认CGLIBLazyInitializer确有问题,但目前在国内互联网上没有找到相同的案例。这里提出,供javaeye上的大牛商讨!
如果我们一群人的诊断是对的,hibernate就隐藏了一个相当恐怖的bug咯!!!
评论
56 楼
seemoon
2009-05-28
还行,问题讨论得很清楚,直接obj.id这应该是一种有“隐患”的程序写法,尤其在类增强的情况下,obj.id又属于比较特殊的属性。
被评为新手贴的确有失公允。
被评为新手贴的确有失公允。
55 楼
Sunteya
2009-05-28
linliangyi2007 写道
代码如下:
上述的 LOC_1 处和 LOC_2 处打印的ID完全相等, LOC_3处输出true(说明对象地址相同),BUT~~ LOC_4处输出是false;
给出FlowToken的equals实现
跟踪发现,实际进入equals的obj参数根本不是外面传入的那个token对象,中间过程被Hinernate的CGLIBLazyInitializer做了代理处理,发生了底层对象的变换。
开始大家都打死不信有这样的BUG,经过对jvm线程和变量编号的反复跟踪,BUG每次都重现。确认CGLIBLazyInitializer确有问题,但目前在国内互联网上没有找到相同的案例。这里提出,供javaeye上的大牛商讨!
如果我们一群人的诊断是对的,hibernate就隐藏了一个相当恐怖的bug咯!!!
/** * 判断当前流程实例上下文中,是否存在Blocking(阻挡性)的任务 * 规则 * 1.任务未结束 * 2.任务是必办理的 * 3.当前任务实例的token和执行上下文的token一致 * @param token * @return */ public boolean hasBlockingTaskInstances(FlowToken token) { boolean hasBlockingTasks = false; System.out.println("LOC_1 :" + token.getId()); Set<TaskInstance> taskInstances = flowInstance.getTaskInstances(); if (taskInstances!=null) { Iterator<TaskInstance> iter = taskInstances.iterator(); while ( (iter.hasNext()) && (!hasBlockingTasks)) { System.out.println("LOC_2 : " + taskInstance.getFlowToken().getId()); System.out.println("LOC_3 : " + token == taskInstance.getFlowToken()); System.out.println("LOC_4 : " + token.equals(taskInstance.getFlowToken()); TaskInstance taskInstance = (TaskInstance) iter.next(); if ( (! taskInstance.hasEnded()) //任务未结束 && (taskInstance.getIsBlocking()) //任务是必办理的 && (token!=null) && (token.equals(taskInstance.getFlowToken())) ) { hasBlockingTasks = true; } } } return hasBlockingTasks; }
上述的 LOC_1 处和 LOC_2 处打印的ID完全相等, LOC_3处输出true(说明对象地址相同),BUT~~ LOC_4处输出是false;
给出FlowToken的equals实现
/* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof FlowToken)) return false; final FlowToken other = (FlowToken) obj; if (id == null || other.id == null) { return false; } else if (!id.equals(other.id)) return false; return true; }
跟踪发现,实际进入equals的obj参数根本不是外面传入的那个token对象,中间过程被Hinernate的CGLIBLazyInitializer做了代理处理,发生了底层对象的变换。
开始大家都打死不信有这样的BUG,经过对jvm线程和变量编号的反复跟踪,BUG每次都重现。确认CGLIBLazyInitializer确有问题,但目前在国内互联网上没有找到相同的案例。这里提出,供javaeye上的大牛商讨!
如果我们一群人的诊断是对的,hibernate就隐藏了一个相当恐怖的bug咯!!!
我重新整理下, 首先这里有2个 token 和 taskInstance.getFlowToken(), 我把参数传入的token 称为 tokenA, 把 taskInstance.getFlowToken() 称为 tokenB.
楼主说 tokenB 是 hibernate 通过lazyload 产生的代理. 而根据 LOC_3 :token == taskInstance.getFlowToken() 打印的 true 的情况来看. 可以知道 tokenA 和 tokenB 都是hibernate代理的对象. 而且是同一个对象.
Hibernate lazy load的原理是 用cglib 生成当前 model 的子类. 重写他所有(根据hibernate定义)的 getter 和 setter 方法, 注意是getter, setter的,像equals应该不会被重写, 另外model 的所有final方法不会重写(所以个人很讨厌final, spring 框架里就一堆), 当你调用一个 getter 的时候他才从数据库取出真实的对象返回他的值
因为tokenA和tokenB都是被代理的对象, 所以在equals 直接调用 id 属性的话, 必然返回 null. 也有人说 这个时候hibernate 已经知道对象的id 了, 这个没错. 但知道id 也不一定会把他知道的id 放在id属性中吧.
所以equals内, 必须使用 getId() 来访问id. 楼主一开始没有用getter访问出错了, 后来经过大家指正把代码改成了
13. if (id == null || other.getId() == null) { 14. return false; 15. } else if (!id.equals(other.getId())) 16. return false;可以看到虽然tokenB是通过getter 访问了, 但 tokenA 还是使用id 属性. 这样结果当然还是不对.
所以楼主等节后去公司里试验一下用getter来访问id, 我认为就不会有问题了, 最后我想说的是 这贴我也投了新手. 不是因为问题什么, 而是因为这个标题, 你们竟然会怀疑hibernate有bug. hibernate 这么常用的框架, equals这么常用的功能. 是不会有这么这么大的一个bug 的. 如果真的有的话, 也会立刻被修复. 我像表达的意思是 99.99% 的问题都是我们使用不当造成的, 不应该动不动就质疑框架类库, 这样的风气我认为是不应该被提倡的.
54 楼
linliangyi2007
2009-05-27
歪个楼,既然楼上的说道hashcode和equals,我来说说我的理解。
如果你使用的容器是HashSet,那么当判断contain的时候,首先容器取的是对象的hashCode方法,而后,在相同hashCode的hash桶中使用equals方法比较。
然而如果你使用的是TreeSet那么比较将使用Comparable接口的comparaTo了,comparaTo返回0就是相等,认为集合内已经存在,及时这时的hashcode和equals方法都不等
如果你使用的容器是HashSet,那么当判断contain的时候,首先容器取的是对象的hashCode方法,而后,在相同hashCode的hash桶中使用equals方法比较。
然而如果你使用的是TreeSet那么比较将使用Comparable接口的comparaTo了,comparaTo返回0就是相等,认为集合内已经存在,及时这时的hashcode和equals方法都不等
53 楼
cnheroooooo
2009-05-27
rrsy23 写道
从这个问题看LZ对java的equlas与hashcode没有理解清楚;
这两个方法是留个自己实现的;
我完全可以写个equals永远返回false,hashcode永远返回一样;
说个实际点的吧;
set 放进去的东西能找到吗?
package com.bobo;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class TestMain {
public static void main(String[] args) {
new TestMain().test1();
}
public void test1() {
Set set = new HashSet();
set.add(new A());
// false
System.out.println(set.contains(new A()));
set.add(new B());
// true
System.out.println(set.contains(new B()));
set.add(new C());
// true
System.out.println(set.contains(new C()));
A a = new A();
set.add(a);
// true
System.out.println(set.contains(a));
B b = new B();
set.add(b);
// true
System.out.println(set.contains(b));
C c = new C();
set.add(c);
// 大部分情况下是false
System.out.println(set.contains(c));
}
class A {
}
class B {
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals(Object obj) {
return true;
}
}
class C {
@Override
public int hashCode() {
return new Random().nextInt();
}
@Override
public boolean equals(Object obj) {
return true;
}
}
}
理解哈吧,研究哈吧;其实很多书上也讲了;
关键是你思考没有,研究没有;
这两个方法是留个自己实现的;
我完全可以写个equals永远返回false,hashcode永远返回一样;
说个实际点的吧;
set 放进去的东西能找到吗?
package com.bobo;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class TestMain {
public static void main(String[] args) {
new TestMain().test1();
}
public void test1() {
Set set = new HashSet();
set.add(new A());
// false
System.out.println(set.contains(new A()));
set.add(new B());
// true
System.out.println(set.contains(new B()));
set.add(new C());
// true
System.out.println(set.contains(new C()));
A a = new A();
set.add(a);
// true
System.out.println(set.contains(a));
B b = new B();
set.add(b);
// true
System.out.println(set.contains(b));
C c = new C();
set.add(c);
// 大部分情况下是false
System.out.println(set.contains(c));
}
class A {
}
class B {
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals(Object obj) {
return true;
}
}
class C {
@Override
public int hashCode() {
return new Random().nextInt();
}
@Override
public boolean equals(Object obj) {
return true;
}
}
}
理解哈吧,研究哈吧;其实很多书上也讲了;
关键是你思考没有,研究没有;
set.add(new C());
// true
System.out.println(set.contains(new C()));
这个的输出结果真是true吗
52 楼
jianfeng008cn
2009-05-27
linliangyi2007 写道
jianfeng008cn 写道
cglib 替换对象是很正常的,你能不能明确的说明错在哪了?你的替换了对象是什么意思啊?这帖子看得真冒火。
ps:你一个劲强调自己水平好有意义嘛!
ps:你一个劲强调自己水平好有意义嘛!
我发贴可不强调你说的,这样的说法容易歪楼哈!!
替换了对象的意思就是:cglib给我new了一个所有属性都=null的FlowToken对象,这个对象是FlowToken的一个proxy没错,但什么属性值都取不到,再次强调所有方法返回null。我不知道为啥发生这样的情况。
就当我故意歪楼好了,别搞半天就是楼上说的原因。
51 楼
zhxp791008
2009-05-27
CGLIB产生proxy的原理:是通过动态的生成一个子类去覆盖所要代理类的不是final的方法,并设置好callback,则原有类的每个方法调用就会转变成调用用户定义的拦截方法,在Hibernate中就是调用getter方法时访问数据库进行实际的查询。但是在调用getId时是不会查询数据库的。因为ID已经知道了。
50 楼
linliangyi2007
2009-05-27
icewubin 写道
linliangyi2007 写道
兄弟,你说法是对的,但你没有解决我遇到的问题。我的问题是,传入equals方法的对象根本是个所有属性都是null的新对象,跟在equals外取到的对象不是一个东西。
非常郁闷啊,我也不希望是hibernate的bug,要知道,第一,我感情上很喜欢Hibernate;第二,我有大量的应用基于hibernate,它要出问题了,我可郁闷大发了!目前这个症状仅在我程序的一个地方出现;大部分情况是很正常的,but~~~谁知道下一次在哪里啊
非常郁闷啊,我也不希望是hibernate的bug,要知道,第一,我感情上很喜欢Hibernate;第二,我有大量的应用基于hibernate,它要出问题了,我可郁闷大发了!目前这个症状仅在我程序的一个地方出现;大部分情况是很正常的,but~~~谁知道下一次在哪里啊
兄弟,你啥时候能把我说的测试代码运行一下,我其实不是很关心other.getClass(),我其实更关心this.getClass()。
没问题,不过代码环境在公司,节后一定运行一下!!
再次说明,希望大家把精力集中的问题本身哈。je上发贴就是为了技术而技术,灌水我上天涯,吹牛会去mopper的。
49 楼
linliangyi2007
2009-05-27
jianfeng008cn 写道
cglib 替换对象是很正常的,你能不能明确的说明错在哪了?你的替换了对象是什么意思啊?这帖子看得真冒火。
ps:你一个劲强调自己水平好有意义嘛!
ps:你一个劲强调自己水平好有意义嘛!
我发贴可不强调你说的,这样的说法容易歪楼哈!!
替换了对象的意思就是:cglib给我new了一个所有属性都=null的FlowToken对象,这个对象是FlowToken的一个proxy没错,但什么属性值都取不到,再次强调所有方法返回null。我不知道为啥发生这样的情况。
48 楼
icewubin
2009-05-27
linliangyi2007 写道
兄弟,你说法是对的,但你没有解决我遇到的问题。我的问题是,传入equals方法的对象根本是个所有属性都是null的新对象,跟在equals外取到的对象不是一个东西。
非常郁闷啊,我也不希望是hibernate的bug,要知道,第一,我感情上很喜欢Hibernate;第二,我有大量的应用基于hibernate,它要出问题了,我可郁闷大发了!目前这个症状仅在我程序的一个地方出现;大部分情况是很正常的,but~~~谁知道下一次在哪里啊
非常郁闷啊,我也不希望是hibernate的bug,要知道,第一,我感情上很喜欢Hibernate;第二,我有大量的应用基于hibernate,它要出问题了,我可郁闷大发了!目前这个症状仅在我程序的一个地方出现;大部分情况是很正常的,but~~~谁知道下一次在哪里啊
兄弟,你啥时候能把我说的测试代码运行一下,我其实不是很关心other.getClass(),我其实更关心this.getClass()。
47 楼
linliangyi2007
2009-05-27
Sunteya 写道
linliangyi2007 写道
4. @Override 5. public boolean equals(Object obj) { 6. if (this == obj) 7. return true; 8. if (obj == null) 9. return false; 10. if (!(obj instanceof FlowToken)) 11. return false; 12. final FlowToken other = (FlowToken) obj; 13. if (id == null || other.getId() == null) { 14. return false; 15. } else if (!id.equals(other.getId())) 16. return false; 17. return true; 18. }
这里的
13. if (id == null || other.getId() == null) { 14. return false; 15. } else if (!id.equals(other.getId())) 16. return false;
怎么说也应该用 getter来访问把, 也就是
13. if (getId() == null || other.getId() == null) { 14. return false; 15. } else if (!getId().equals(other.getId())) 16. return false;
你可以看看我原来写的, 这标题取得, 确实不是 hibernate 的bug 啊
http://dev.sunteya.com/svn/flyer/trunk/core/src/main/java/com/sunteya/flyer/domain/AbstractEntity.java
兄弟,你说法是对的,但你没有解决我遇到的问题。我的问题是,传入equals方法的对象根本是个所有属性都是null的新对象,跟在equals外取到的对象不是一个东西。
非常郁闷啊,我也不希望是hibernate的bug,要知道,第一,我感情上很喜欢Hibernate;第二,我有大量的应用基于hibernate,它要出问题了,我可郁闷大发了!目前这个症状仅在我程序的一个地方出现;大部分情况是很正常的,but~~~谁知道下一次在哪里啊
46 楼
linliangyi2007
2009-05-27
楼上几个说我标题有问题的,看到“可能”两个字没!
顶多说我是标题党嘛,嘎嘎,就是想吸引更多的大牛来关注啊
顶多说我是标题党嘛,嘎嘎,就是想吸引更多的大牛来关注啊
45 楼
icewubin
2009-05-27
给所有人建议,hibernate中取ID有更好的通用方法,明天我来贴代码,可以放在BaseModel中的。
44 楼
Sunteya
2009-05-27
linliangyi2007 写道
4. @Override 5. public boolean equals(Object obj) { 6. if (this == obj) 7. return true; 8. if (obj == null) 9. return false; 10. if (!(obj instanceof FlowToken)) 11. return false; 12. final FlowToken other = (FlowToken) obj; 13. if (id == null || other.getId() == null) { 14. return false; 15. } else if (!id.equals(other.getId())) 16. return false; 17. return true; 18. }
这里的
13. if (id == null || other.getId() == null) { 14. return false; 15. } else if (!id.equals(other.getId())) 16. return false;
怎么说也应该用 getter来访问把, 也就是
13. if (getId() == null || other.getId() == null) { 14. return false; 15. } else if (!getId().equals(other.getId())) 16. return false;
你可以看看我原来写的, 这标题取得, 确实不是 hibernate 的bug 啊
http://dev.sunteya.com/svn/flyer/trunk/core/src/main/java/com/sunteya/flyer/domain/AbstractEntity.java
43 楼
kjj
2009-05-27
标题气得也太有噱头了,问题还没弄清楚,就说是hibernat 的bug,不是有点太武断了吗!!!
42 楼
betafox
2009-05-27
linliangyi2007 写道
靠这也叫新手帖!!
javaeye上有几个新手提这样的问题啊!!
提问题也要有层次好啵?动不动就评新手帖,无语!
javaeye上有几个新手提这样的问题啊!!
提问题也要有层次好啵?动不动就评新手帖,无语!
感觉java阿姨已经有点不食人间烟火了,诸如此类的阿姨不知道人间还有我辈这等小老百姓在饱受煎熬,呵呵,牢骚一句。我觉得实践中的问题可能是影响广泛的问题,而非只有理论问题才能入java阿姨的法眼....
41 楼
icewubin
2009-05-27
说句题外话,楼主的这种实现equals的短路方法是有缺陷的。
楼主可以自己在Eclipse中,生成某一个model的equals方法,看看短路方法应该如何实现(不过推荐的实现方法碰到Hibernate代理对象会不好使,需要其他办法解决)。
楼主可以自己在Eclipse中,生成某一个model的equals方法,看看短路方法应该如何实现(不过推荐的实现方法碰到Hibernate代理对象会不好使,需要其他办法解决)。
40 楼
icewubin
2009-05-27
拜托楼主把我说的那两个打印语句的结果贴出来看看:
System.out.println(this.getClass());
System.out.println(other.getClass());
还有就是三个打印都使用这个tokenOther的引用之后,还是返回false么?
System.out.println(this.getClass());
System.out.println(other.getClass());
还有就是三个打印都使用这个tokenOther的引用之后,还是返回false么?
39 楼
jianfeng008cn
2009-05-27
cglib 替换对象是很正常的,你能不能明确的说明错在哪了?你的替换了对象是什么意思啊?这帖子看得真冒火。
ps:你一个劲强调自己水平好有意义嘛!
ps:你一个劲强调自己水平好有意义嘛!
38 楼
linliangyi2007
2009-05-27
icewubin 写道
建议先在equals方法中,加入如下两句话,看看结果:
顺带确认一下你传进来的token参数本身是否是代理对象,是的话,这个equals有可能也被CGLib动了写手脚(我瞎猜的)。
然后主要测试代码如下修改:
然后三个打印都使用这个tokenOther的引用,看看结果。
System.out.println(this.getClass()); System.out.println(other.getClass());
顺带确认一下你传进来的token参数本身是否是代理对象,是的话,这个equals有可能也被CGLib动了写手脚(我瞎猜的)。
然后主要测试代码如下修改:
FlowToken tokenOther = taskInstance.getFlowToken();
然后三个打印都使用这个tokenOther的引用,看看结果。
你的猜测是对的,在跟踪调试中,可以很明显的看到,调用equals方法时,CGLib接入了其中,这也正是我写这篇blog的原因,我们还请了公司的C++权威来协助跟踪,确定我们不是眼花了,或者代码错误,确实是被代理替换了对象。但我们不知道CGLib在怎样一种情况下,会发生这样的异常。(肯定不是每次都发生的,否则问题早就被发现了,呵呵)
37 楼
icewubin
2009-05-27
建议先在equals方法中,加入如下两句话,看看结果:
顺带确认一下你传进来的token参数本身是否是代理对象,是的话,这个equals有可能也被CGLib动了写手脚(我瞎猜的)。
然后主要测试代码如下修改:
然后三个打印都使用这个tokenOther的引用,看看结果。
System.out.println(this.getClass()); System.out.println(other.getClass());
顺带确认一下你传进来的token参数本身是否是代理对象,是的话,这个equals有可能也被CGLib动了写手脚(我瞎猜的)。
然后主要测试代码如下修改:
FlowToken tokenOther = taskInstance.getFlowToken();
然后三个打印都使用这个tokenOther的引用,看看结果。
发表评论
-
来自开源支持者的第一笔捐赠
2013-01-09 21:15 57772013年1月9号,一个平凡而又不平常的日子! IK中文分词 ... -
发布 IK Analyzer 2012 FF 版本
2012-10-23 17:50 25074首先感谢大家对IK分词器的关注。 最近一段时间正式公司事务最 ... -
发布 IK Analyzer 2012 版本
2012-03-08 11:23 36163新版本改进: 支持分词歧义处理 支持数量词合并 词典支持中英 ... -
CSDN发生严重用户账号泄密事件
2011-12-21 19:21 2564之前有在CSDN注册过的兄弟们,注意了。。。 如果你的邮箱, ... -
一个隐形的java int溢出
2011-08-30 09:44 7555故事的背景: 笔者最近在做一个类SNS的项目,其中 ... -
雷军 :互联网创业的葵花宝典
2011-05-04 10:35 3593博主评: 这片博客很短 ... -
Luci-mint站内搜索实测
2011-04-02 16:18 4135关于Luci-mint 服务器硬 ... -
发布 IK Analyzer 3.2.8 for Lucene3.X
2011-03-04 17:49 14251IK Analyzer 3.2.8版本修订 ... -
TIPS - XML CDATA中的非法字符处理
2011-02-17 15:03 3301XML解析过程中,常遇见CDATA中存在非法字符,尤其在火星文 ... -
对Cassandra的初体验
2010-10-13 17:58 9132作为“云计算”时代的架构设计人员而言,不懂K-V库会被 ... -
Spring + iBatis 的多库横向切分简易解决思路
2010-10-11 13:43 93541.引言 笔者最近在做一个互联网的“类SNS”应用,应用 ... -
发布 IK Analyzer 3.2.5 稳定版 for Lucene3.0
2010-09-08 14:43 5822新版本IKAnnlyzer3.2.8已发布! 地址: http ... -
关于Lucene3.0.1 QueryParser的一个错误
2010-05-21 21:33 2128表达式1: 引用 id:"1231231" ... -
发布 IK Analyzer 3.2.3 稳定版 for Lucene3.0
2010-05-15 14:13 6715IK Analyzer 3.2.3版本修订 在3.2.0版 ... -
windows平台上的nginx使用
2010-01-28 17:13 3404转载自:http://nginx.org/en/docs/wi ... -
发布IKAnnlyzer3.2.0稳定版 for Lucene3.0
2009-12-07 09:27 9574最新3.2.5版本已经推出,http://linliangyi ... -
在Tomcat下以JNDI方式发布JbossCache
2009-12-04 10:57 3828前言: 看过JbossCache的开发手册,发现在Jb ... -
Spring AOP小例子
2009-11-16 10:35 3403PS: 要注明一下,这个是转载滴,之前漏了说鸟,汗死 这里给 ... -
ActiveMQ 5.X 与 Tomcat 集成一(JNDI部署)
2009-11-10 15:15 5648原文地址:http://activemq.apache.org ... -
发布IKAnalyzer中文分词器V3.1.6GA
2009-11-08 23:10 11854IKAnalyzer3.2.0稳定版已经发布,支持Lucene ...
相关推荐
重载equals方法示例重载equals方法示例重载equals方法示例重载equals方法示例重载equals方法示例
例如,public boolean equals(Object o) 是一个正确的重写方法,而 public boolean equals(String o) 是一个重载方法,而不是重写方法。 equals 方法的实现 ------------------------- equals 方法的实现需要遵循...
### equals方法重写知识点解析 #### 一、equals方法简介 `equals`方法是Java语言中Object类的一个重要成员方法,其默认实现是比较两个对象的内存地址是否相同(即是否为同一个对象)。为了使对象之间能够基于内容...
### Java中equals方法隐藏的陷阱 在Java编程中,正确实现`equals`方法至关重要,它不仅影响对象的比较逻辑,还直接关系到集合类(如`HashSet`、`HashMap`等)的行为。本文将深入探讨Java中`equals`方法的一些常见...
### set接口中hashCode和equals方法详解 #### 一、引言 在Java编程语言中,`Set`接口作为集合框架的重要组成部分,在实现无重复元素的数据结构方面扮演着关键角色。为了确保元素的唯一性,`Set`接口依赖于对象的`...
equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.
Java 对象的toString和equals方法重写 在 Java 中,每个对象都继承自 Object 类,而 Object 类中定义了两个重要的方法:toString() 和 equals()。这两个方法都是非常重要的,它们分别用于对象的字符串表示和对象...
在JavaScript中,`equals`方法并不像在其他某些编程语言中那样是内置的,例如Java。但是,由于JavaScript的灵活性,我们可以自定义一个`equals`函数来实现对象间的深度比较。这个方法通常用于比较两个对象的属性和值...
5. 设定生成Bean的模板,可以选择是否生成equals()、hashCode()、toString()等方法,以及字段的访问级别等。 6. 完成设置后,点击“Finish”按钮,开发工具将自动生成对应的Java Bean类和Hibernate映射文件(.hbm....
equals方法的四个常见陷阱分别是:定义了错误的equals方法签名,重载了equals的但没有同时重载hashCode的方法,建立在会变化字域上的equals定义,不满足等价关系的equals错误定义。下面将对每个陷阱进行详细的解释...
在Java编程语言中,了解如何正确使用`==`和`equals()`方法是非常关键的,因为它们在比较对象和基本类型时有不同的行为。下面将详细解释这两个方法的工作原理、使用场景以及一些常见误区。 首先,`==`运算符主要用于...
在Java编程语言中,比较运算符`==`和`equals()`方法是用来检查两个对象是否相等的,但它们之间存在显著的区别。理解这些差异对于编写正确的代码至关重要。 首先,我们来看`==`运算符。它主要用于基本数据类型的比较...
- 为了避免哈希冲突带来的性能问题,在覆盖`equals()`方法的同时,通常也需要覆盖`hashCode()`方法。 #### 实现示例 以下是一个简单的类`Person`,展示了如何正确覆盖`equals()`和`hashCode()`方法: ```java ...
2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2....
"关于Object中equals方法和hashCode方法判断的分析" 在 Java 中,Object 类提供了两个重要的方法:equals 方法和 hashCode 方法。这两个方法都是用于比较两个对象是否相等的,但它们的实现机理和作用域却有所不同。...
字符串是一个特殊的引用类型,在C#语言中,重载了字符串对象的很多方法,包括`Equals()`方法,使字符串对象用起来就像是值类型一样。这也是为什么在上面的例子中,`a`和`b`的比较结果都是`true`的原因。 需要注意的...
在Java编程语言中,`==`和`equals()`方法是用来比较对象之间关系的两种常见方式,但它们在使用上有着显著的区别。 首先,`==`运算符主要用于比较基本类型(如int、char、byte等)的值是否相等,或者比较引用类型...
### C# Equals 和 GetHashCode 方法重写 在C#编程中,`Equals` 和 `GetHashCode` 方法是非常重要的成员方法,它们对于确保对象的正确比较以及高效地存储和检索对象至关重要。这两个方法通常需要在自定义类中进行...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中的两个核心方法,所有类都默认继承自Object类。这两个方法在处理对象比较和集合操作时起着至关重要的作用。当我们创建自定义类并需要对对象进行精确...
这里我们将深入探讨`equals()`方法的用法,以及它与`==`的区别,同时解决题目中提出的问题。 **问题一:** 在Java中,`String`类的实例有两种创建方式。一种是直接通过字面量,如`String s1 = "abc";`,这时字符串...