例如
Class MyClass
{
String name;
public void setName(String s)
{
this.name=s;
}
public String getName()
{
return this.s;
}
}
public class TMain
{
public static void main(String args[])
{
MyClass myclass=new MyClass();
myclass.setName("Terry");
System.out.println("hashcode:"+myclass.hashcode());
MyClass myclass1=getClassFromHashCode(myclass.hascode()); //通过hashcode重新得到这个对象
System.out.println("name:"+myclass1.getName());//这里应该显示出Terry
}
public static Object getClassFromHashCode(int hascode)
{
//就是这个方法不知怎么写
}
}
能解决的,我加分再结贴。谢谢
28 个解决方案
#1
你真的搞了多年的开发吗??
汗!狂汗!
汗!狂汗!
#2
mark!
---------------------
代表城管来接分。
不给就抢,一天一次...
---------------------
代表城管来接分。
不给就抢,一天一次...
#3
你这个理论上是行不通的
#4
这个倒不是没有办法,不过需要修改一下代码
#5
class XObject{
private final static Map<Integer,XObject> map=Collections.synchronizedMap(new HashMap<Integer,XObject>());
public static XObject getObjectByRawHashCode(Integer hashCode){
return map.get(hashCode);
}
XObject(){
map.put(System.identityHashCode(this),this);
}
}
class MyClass extends XObject
{
String name;
public void setName(String s)
{
this.name=s;
}
public String getName()
{
return this.name;
}
}
main:
MyClass myclass=new MyClass();
myclass.setName("Terry");
System.out.println("hashcode:"+myclass.hashCode());
MyClass myclass1=(MyClass) XObject.getObjectByRawHashCode(myclass.hashCode()); //通过hashcode重新得到这个对象
System.out.println("name:"+myclass1.getName());//这里应该显示出Terry
private final static Map<Integer,XObject> map=Collections.synchronizedMap(new HashMap<Integer,XObject>());
public static XObject getObjectByRawHashCode(Integer hashCode){
return map.get(hashCode);
}
XObject(){
map.put(System.identityHashCode(this),this);
}
}
class MyClass extends XObject
{
String name;
public void setName(String s)
{
this.name=s;
}
public String getName()
{
return this.name;
}
}
main:
MyClass myclass=new MyClass();
myclass.setName("Terry");
System.out.println("hashcode:"+myclass.hashCode());
MyClass myclass1=(MyClass) XObject.getObjectByRawHashCode(myclass.hashCode()); //通过hashcode重新得到这个对象
System.out.println("name:"+myclass1.getName());//这里应该显示出Terry
#6
TO hbwhwang: J2EE方面的开放经验绝对比你这个开班授课的江湖游医要丰富. 想做老师, 就多回答问题,不会回答别混分.把等级搞上去了才有说服力.
#7
treeroot(旗鲁特) ( )
你的这个方法是要预先定义好才能得到的,如果里面数据有变化,那么hashcode肯定会变化,这个时候你又取不出来了
所以,应该不能用你的那种方法来从 hashcode取出对象
你的这个方法是要预先定义好才能得到的,如果里面数据有变化,那么hashcode肯定会变化,这个时候你又取不出来了
所以,应该不能用你的那种方法来从 hashcode取出对象
#8
terry_yip(搞了几年开发,现在才来恶补基础,请别见笑!):
没想到那句“汗,狂汗”伤害了你的自尊~
抱歉了,兄弟!
=======
你的问题在JAVA DOC中有答案,Object类的hashCode()方法里面有这个方法的详细说明。
我英文不好,就不给你翻译了,你自己看看吧。
没想到那句“汗,狂汗”伤害了你的自尊~
抱歉了,兄弟!
=======
你的问题在JAVA DOC中有答案,Object类的hashCode()方法里面有这个方法的详细说明。
我英文不好,就不给你翻译了,你自己看看吧。
#9
谢谢treeroot的详尽代码,不过以那种原理来看,应该要改Object类的代码,才能使所有的对象都能通过hashcode取到吧?
#10
TO hbwhwang:从你说推荐我看Java Doc中的Object类的hashCode方法,我就觉得你都没看清我的这个问题问什么,这个问题是问从hashcode取得Object的问题,而不是问hashcode用来做什么的,如果是google一下或查看JDK文档就找到答案的,我也不会发贴问.你有可能是说hashcode不是唯一的这个问题, 这个可能性我考虑过,得到了Object后,用getClass()方法就可以知道是不是我想要的Object了. 总之,用"你真的搞了多年的开发吗??汗!狂汗!"来回答一个你没看清楚的问题,是"针对人而不是针对技术问题 ", 有点不合适的,是吧?
#11
算啦, 说明了问题就OK了,我的水平也不是好到哪儿去. 别跑题了, 大家继续讨论主题上的问题吧.贴子先加十分.
#12
terry_yip(搞了几年开发,现在才来恶补基础,请别见笑!) :
你错了,我看清楚了你的问题才说那句话的。
你题目中的类MyClass没有继承,那么就是继承自JAVA的Object。因此你所说的hashCode就是Object的hashCode。
关于Object的hashCode,在JAVA DOC中,有这段话:
* As much as is reasonably practical, the hashCode method defined by
* class <tt>Object</tt> does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer, but this implementation
* technique is not required by the
* Java<font size="-2"><sup>TM</sup></font> programming language.)
也就是说:Object的hashCode,(一般)是根据对象的内部地址(internal address)转化(计算)而来的。
从理论上(我说的是理论上,而实际上除非你非常深入了解JVM),如果我们如果找到了这个内部地址,那么我们还是有办法取回对象的。可是这个算法可能(我是说可能,我也没看过源码)是不可逆的,也就是说,你不一定能通过hashCode反算出internal address。
当然现在唯一的一条路就显示出来了:
1、java的hashCode算法必须可逆
2、有办法把变量myclass1刷成你得到的internal address
=============
我说的“汗,狂汗”没有别的意思,也不是为了捞分!(没见过接分的这么说话的吧)
我只是感叹于你写的“搞了几年开发”
我个人认为“搞了几年开发”的技术人员不可能不知道上面的内容。
你错了,我看清楚了你的问题才说那句话的。
你题目中的类MyClass没有继承,那么就是继承自JAVA的Object。因此你所说的hashCode就是Object的hashCode。
关于Object的hashCode,在JAVA DOC中,有这段话:
* As much as is reasonably practical, the hashCode method defined by
* class <tt>Object</tt> does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer, but this implementation
* technique is not required by the
* Java<font size="-2"><sup>TM</sup></font> programming language.)
也就是说:Object的hashCode,(一般)是根据对象的内部地址(internal address)转化(计算)而来的。
从理论上(我说的是理论上,而实际上除非你非常深入了解JVM),如果我们如果找到了这个内部地址,那么我们还是有办法取回对象的。可是这个算法可能(我是说可能,我也没看过源码)是不可逆的,也就是说,你不一定能通过hashCode反算出internal address。
当然现在唯一的一条路就显示出来了:
1、java的hashCode算法必须可逆
2、有办法把变量myclass1刷成你得到的internal address
=============
我说的“汗,狂汗”没有别的意思,也不是为了捞分!(没见过接分的这么说话的吧)
我只是感叹于你写的“搞了几年开发”
我个人认为“搞了几年开发”的技术人员不可能不知道上面的内容。
#13
我还是觉得从hashcode转化成对象不太可能
#14
解决方案还是有的吧,例如添加一个实时map,记录hashcode和对象引用
直接似乎是不行的
直接似乎是不行的
#15
TO hbwhwang:你说对了,搞了几年开发的人,不可道不知道上面内容,我六年前就知道Object类是所有类的超类,所有的对象中都默认继承Object类的方法. 我不知道我说过的内容中,你从哪里看出来我是不知道上面这个知识点的.你的JavaDoc的内容,在Eclipse上,随便Ctrl+点击"Object"这个单词都可以看到,至于hashCode()是一个native方法,我也知道,但不代表native方法中实现的东西,就不能提取出来,万一sun另外做了另一个native方法,可以让你提取,而我们平时少用不知道呢? 又或者sun没有提供,但有人可以通过别的算法实现呢? 我就是因为有这个猜测所以才发贴问.
就像前面treeroot所说的,他讲的也是一个解决办法,不过他要继承一个自定义的类,如果要把JVM中所有的类都找得到,就得改变所有类的超类----Object类的源代码,上面我都讲过了这个问题了,证明我是很清楚Object是所有类的超类这个知识点的.我很谢谢他的回贴,虽然不是最好的,但起码他是提供了一个可行的解决方法.
我可以这样讲,通过hashcode返过来找到hashcode对应对象,是可以实现的,Spring中已经有相似的这个功能, 我没空研究它的源码,所以才想请教一下大家.
就像前面treeroot所说的,他讲的也是一个解决办法,不过他要继承一个自定义的类,如果要把JVM中所有的类都找得到,就得改变所有类的超类----Object类的源代码,上面我都讲过了这个问题了,证明我是很清楚Object是所有类的超类这个知识点的.我很谢谢他的回贴,虽然不是最好的,但起码他是提供了一个可行的解决方法.
我可以这样讲,通过hashcode返过来找到hashcode对应对象,是可以实现的,Spring中已经有相似的这个功能, 我没空研究它的源码,所以才想请教一下大家.
#16
了解,算了不吵了,如果我言语不慎伤害了你,再次跟你说声抱歉~
既然你认可treeroot(旗鲁特) 的办法,那我也可以给你一种办法,不用继承,但是得用工厂。
public MyClassFactory{
static Map<Integer,MyClass> map=new HashMap<Integer,MyClass>();
private MyClassFactory(){}
public synchronized static MyClass getInstance(){
MyClass m=new MyClass();
map.put(m.hashCode(),m);
return m;
}
public synchronized static Object getClassFromHashCode(int hascode){
return map.get(new Integer(hashCode));
}
}
在你每次需要MyClass对象的时候,不要new,而是这样:
MyClass myclass=MyClassFactory.getInstance();
然后你就可以:
MyClass myclass2=MyClassFactory.getClassFromHashCode(myclass.hashCode());
既然你认可treeroot(旗鲁特) 的办法,那我也可以给你一种办法,不用继承,但是得用工厂。
public MyClassFactory{
static Map<Integer,MyClass> map=new HashMap<Integer,MyClass>();
private MyClassFactory(){}
public synchronized static MyClass getInstance(){
MyClass m=new MyClass();
map.put(m.hashCode(),m);
return m;
}
public synchronized static Object getClassFromHashCode(int hascode){
return map.get(new Integer(hashCode));
}
}
在你每次需要MyClass对象的时候,不要new,而是这样:
MyClass myclass=MyClassFactory.getInstance();
然后你就可以:
MyClass myclass2=MyClassFactory.getClassFromHashCode(myclass.hashCode());
#17
OK,我的言论也有点过激,我也say sorry.
在这里,其实我说明一下我的设想,我们做项目做多了,就会发现,很多时候,出现的错误都是很隐蔽的,有时客户对你说:"我好像先按这里,再按那里,然后输入什么什么,再进去, 就报错了",但你到现场时,却怎么也发现不了错误,你要客户方的人再模拟一次,好像又没错,这个问题真的很烦,最后我们最终解决问题时发现,多数都是对象中的某些变量值不规范造成的,程序员的水平也有高有低,同一个人的精神状态也有好有差,你不可能要求程序一做出来,就有足够的健壮性去处理各种不规范的变量值的,所以我就设想出这样一种模式来处理-----当JVM抛出不能处理的Exception时, 马上得到抛出Exception的对象, 并把这个对象用ObjectOutPutStream记录在文本或者数据库中, 于是, 我们通过log4j的报错时间,就可以定位到记录这个错误对象的媒介,并把它还原, 从而就跟踪到这个对象里面的所有变量的值, 那么查起错来就容易多了.
我之所以问本贴的这个问题,其实就是发现Exception中,可以得到抛出错误的对象的hashcode, (用Thowable里面的getStackTrace()得到StackTraceElement,然后调用StackTraceElement.hashcode()得到抛出错误的对象的hashcode),然后我就想把Exception的构造方法改一下,进一步通过hashcode来得到发生错误的对象,然后再把这个对象持久化了,当然,这个对象要实现Serialisable接口, 这就是我的想法. TreeRoot的方法可以实现,但需要再把Object类的代码改一下.hbwhwang的方法其实和treeroot的原理是一样的,都是先把对象和hashcode存在一个静态的Map里面, 只不过换成了工厂模式.
我两个月前已经发贴问过这个问题,结果用Plain Java的API得不到实现方法, 后来用Spring的ExceptionInterceptor来实现了, 但是我不满足于功能的实现,我还想知道实现的原理.
在这里,其实我说明一下我的设想,我们做项目做多了,就会发现,很多时候,出现的错误都是很隐蔽的,有时客户对你说:"我好像先按这里,再按那里,然后输入什么什么,再进去, 就报错了",但你到现场时,却怎么也发现不了错误,你要客户方的人再模拟一次,好像又没错,这个问题真的很烦,最后我们最终解决问题时发现,多数都是对象中的某些变量值不规范造成的,程序员的水平也有高有低,同一个人的精神状态也有好有差,你不可能要求程序一做出来,就有足够的健壮性去处理各种不规范的变量值的,所以我就设想出这样一种模式来处理-----当JVM抛出不能处理的Exception时, 马上得到抛出Exception的对象, 并把这个对象用ObjectOutPutStream记录在文本或者数据库中, 于是, 我们通过log4j的报错时间,就可以定位到记录这个错误对象的媒介,并把它还原, 从而就跟踪到这个对象里面的所有变量的值, 那么查起错来就容易多了.
我之所以问本贴的这个问题,其实就是发现Exception中,可以得到抛出错误的对象的hashcode, (用Thowable里面的getStackTrace()得到StackTraceElement,然后调用StackTraceElement.hashcode()得到抛出错误的对象的hashcode),然后我就想把Exception的构造方法改一下,进一步通过hashcode来得到发生错误的对象,然后再把这个对象持久化了,当然,这个对象要实现Serialisable接口, 这就是我的想法. TreeRoot的方法可以实现,但需要再把Object类的代码改一下.hbwhwang的方法其实和treeroot的原理是一样的,都是先把对象和hashcode存在一个静态的Map里面, 只不过换成了工厂模式.
我两个月前已经发贴问过这个问题,结果用Plain Java的API得不到实现方法, 后来用Spring的ExceptionInterceptor来实现了, 但是我不满足于功能的实现,我还想知道实现的原理.
#18
如果用Map来分别存放hashcode ,Object的这种方法,是可行,但会有一个问题,随着系统的运行,Map中的Object越来越多,而不释放,这就有危险了。
#19
起始修改java.lang.Object源码是行的通的,但是绝对不推荐
只要自己写一个java.lang.Object.java,重新定义一些方法,要么重新打包rt.jar里面
要么启动的时候放到bootclasspath前面,这样引导类加载器就会加载你实现的Object,
儿忽略掉rt.jar中的Object(不过这个参数不是标准参数)
java -Xboolclasspath/p myobject.jar
只要自己写一个java.lang.Object.java,重新定义一些方法,要么重新打包rt.jar里面
要么启动的时候放到bootclasspath前面,这样引导类加载器就会加载你实现的Object,
儿忽略掉rt.jar中的Object(不过这个参数不是标准参数)
java -Xboolclasspath/p myobject.jar
#20
haha, 大师们都跑这开会来啦?兄弟搬个板凳来学习学习 ^_^
楼主提出这个问题的初衷实在让兄弟感到钦佩,难能可贵!
如果楼主能在一开始就把背景交待一下就更好了。现在经常看到一些帖子,上来就问一个看似比较离奇的问题,等纠缠到最后发现他遇到的问题根本就不应该用他想的思路去解决。我当然不是说本帖,只是说如果一开始就交待清楚的话,能避免不少误会。
楼主说的“项目中纠错”的问题,的确是个问题。以前我没想到还可以用这种手段处理,以后得多想想了 *_*
楼主提出这个问题的初衷实在让兄弟感到钦佩,难能可贵!
如果楼主能在一开始就把背景交待一下就更好了。现在经常看到一些帖子,上来就问一个看似比较离奇的问题,等纠缠到最后发现他遇到的问题根本就不应该用他想的思路去解决。我当然不是说本帖,只是说如果一开始就交待清楚的话,能避免不少误会。
楼主说的“项目中纠错”的问题,的确是个问题。以前我没想到还可以用这种手段处理,以后得多想想了 *_*
#21
maquan('ma:kju) :
别太当回事~~
你去研究一下,就不会滔滔江水了~~
别太当回事~~
你去研究一下,就不会滔滔江水了~~
#22
呵呵,如果我一开始就说得那么详细,恐惊很多人一看就觉得太复杂,没人回贴,贴子很快就沉下去了。
#23
使用AspectJ,例:
public interface HashCode
{
public int hashCode();
}
@Aspect
public class HashCodeImpl implements HashCode
{
public int hashCode()
{
//...在这里将对象和它的hasCode值进行缓存
}
@DeclareParents ( value = "foo.MyClass1" , defaultImpl = HashCodeImpl.class )
//这时的foo.MyClass是需要通过hasCode来获取原对象的类
private HashCode h1 ;
//如果有多个类需要处理,如下添加
@DeclareParents ( value = "foo.MyClass2" , defaultImpl = HashCodeImpl.class )
private HashCode h2 ;
....
}
使用AspectJ编译(可以是jar或java文件)后就可以只对需要的类进行这样的处理,
此方法对原代码没有任何改变
public interface HashCode
{
public int hashCode();
}
@Aspect
public class HashCodeImpl implements HashCode
{
public int hashCode()
{
//...在这里将对象和它的hasCode值进行缓存
}
@DeclareParents ( value = "foo.MyClass1" , defaultImpl = HashCodeImpl.class )
//这时的foo.MyClass是需要通过hasCode来获取原对象的类
private HashCode h1 ;
//如果有多个类需要处理,如下添加
@DeclareParents ( value = "foo.MyClass2" , defaultImpl = HashCodeImpl.class )
private HashCode h2 ;
....
}
使用AspectJ编译(可以是jar或java文件)后就可以只对需要的类进行这样的处理,
此方法对原代码没有任何改变
#24
AspectJ编译后的字节码实际上给所有经过处理的类加上了接口HashCode,接口的方法实现是HashCodeImpl中的实现
#25
mark!
#26
原来AspactJ是这样用的,谢谢flyxxxx让我们长了见识~~!!!^-^
TO treeroot:你说“要么启动的时候放到bootclasspath前面,这样引导类加载器就会加载你实现的Object,”
能不能具体讲一下,怎么把myobject.jar 启动的时候放到bootclasspath前面?你的那句命令不能运行,我在google粗略地找了一下,也没有相关的资料。谢谢了。
贴子再加10分。
TO treeroot:你说“要么启动的时候放到bootclasspath前面,这样引导类加载器就会加载你实现的Object,”
能不能具体讲一下,怎么把myobject.jar 启动的时候放到bootclasspath前面?你的那句命令不能运行,我在google粗略地找了一下,也没有相关的资料。谢谢了。
贴子再加10分。
#27
http://blog.csdn.net/treeroot/archive/2006/07/22/960778.aspx
#28
先收藏再研究
#1
你真的搞了多年的开发吗??
汗!狂汗!
汗!狂汗!
#2
mark!
---------------------
代表城管来接分。
不给就抢,一天一次...
---------------------
代表城管来接分。
不给就抢,一天一次...
#3
你这个理论上是行不通的
#4
这个倒不是没有办法,不过需要修改一下代码
#5
class XObject{
private final static Map<Integer,XObject> map=Collections.synchronizedMap(new HashMap<Integer,XObject>());
public static XObject getObjectByRawHashCode(Integer hashCode){
return map.get(hashCode);
}
XObject(){
map.put(System.identityHashCode(this),this);
}
}
class MyClass extends XObject
{
String name;
public void setName(String s)
{
this.name=s;
}
public String getName()
{
return this.name;
}
}
main:
MyClass myclass=new MyClass();
myclass.setName("Terry");
System.out.println("hashcode:"+myclass.hashCode());
MyClass myclass1=(MyClass) XObject.getObjectByRawHashCode(myclass.hashCode()); //通过hashcode重新得到这个对象
System.out.println("name:"+myclass1.getName());//这里应该显示出Terry
private final static Map<Integer,XObject> map=Collections.synchronizedMap(new HashMap<Integer,XObject>());
public static XObject getObjectByRawHashCode(Integer hashCode){
return map.get(hashCode);
}
XObject(){
map.put(System.identityHashCode(this),this);
}
}
class MyClass extends XObject
{
String name;
public void setName(String s)
{
this.name=s;
}
public String getName()
{
return this.name;
}
}
main:
MyClass myclass=new MyClass();
myclass.setName("Terry");
System.out.println("hashcode:"+myclass.hashCode());
MyClass myclass1=(MyClass) XObject.getObjectByRawHashCode(myclass.hashCode()); //通过hashcode重新得到这个对象
System.out.println("name:"+myclass1.getName());//这里应该显示出Terry
#6
TO hbwhwang: J2EE方面的开放经验绝对比你这个开班授课的江湖游医要丰富. 想做老师, 就多回答问题,不会回答别混分.把等级搞上去了才有说服力.
#7
treeroot(旗鲁特) ( )
你的这个方法是要预先定义好才能得到的,如果里面数据有变化,那么hashcode肯定会变化,这个时候你又取不出来了
所以,应该不能用你的那种方法来从 hashcode取出对象
你的这个方法是要预先定义好才能得到的,如果里面数据有变化,那么hashcode肯定会变化,这个时候你又取不出来了
所以,应该不能用你的那种方法来从 hashcode取出对象
#8
terry_yip(搞了几年开发,现在才来恶补基础,请别见笑!):
没想到那句“汗,狂汗”伤害了你的自尊~
抱歉了,兄弟!
=======
你的问题在JAVA DOC中有答案,Object类的hashCode()方法里面有这个方法的详细说明。
我英文不好,就不给你翻译了,你自己看看吧。
没想到那句“汗,狂汗”伤害了你的自尊~
抱歉了,兄弟!
=======
你的问题在JAVA DOC中有答案,Object类的hashCode()方法里面有这个方法的详细说明。
我英文不好,就不给你翻译了,你自己看看吧。
#9
谢谢treeroot的详尽代码,不过以那种原理来看,应该要改Object类的代码,才能使所有的对象都能通过hashcode取到吧?
#10
TO hbwhwang:从你说推荐我看Java Doc中的Object类的hashCode方法,我就觉得你都没看清我的这个问题问什么,这个问题是问从hashcode取得Object的问题,而不是问hashcode用来做什么的,如果是google一下或查看JDK文档就找到答案的,我也不会发贴问.你有可能是说hashcode不是唯一的这个问题, 这个可能性我考虑过,得到了Object后,用getClass()方法就可以知道是不是我想要的Object了. 总之,用"你真的搞了多年的开发吗??汗!狂汗!"来回答一个你没看清楚的问题,是"针对人而不是针对技术问题 ", 有点不合适的,是吧?
#11
算啦, 说明了问题就OK了,我的水平也不是好到哪儿去. 别跑题了, 大家继续讨论主题上的问题吧.贴子先加十分.
#12
terry_yip(搞了几年开发,现在才来恶补基础,请别见笑!) :
你错了,我看清楚了你的问题才说那句话的。
你题目中的类MyClass没有继承,那么就是继承自JAVA的Object。因此你所说的hashCode就是Object的hashCode。
关于Object的hashCode,在JAVA DOC中,有这段话:
* As much as is reasonably practical, the hashCode method defined by
* class <tt>Object</tt> does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer, but this implementation
* technique is not required by the
* Java<font size="-2"><sup>TM</sup></font> programming language.)
也就是说:Object的hashCode,(一般)是根据对象的内部地址(internal address)转化(计算)而来的。
从理论上(我说的是理论上,而实际上除非你非常深入了解JVM),如果我们如果找到了这个内部地址,那么我们还是有办法取回对象的。可是这个算法可能(我是说可能,我也没看过源码)是不可逆的,也就是说,你不一定能通过hashCode反算出internal address。
当然现在唯一的一条路就显示出来了:
1、java的hashCode算法必须可逆
2、有办法把变量myclass1刷成你得到的internal address
=============
我说的“汗,狂汗”没有别的意思,也不是为了捞分!(没见过接分的这么说话的吧)
我只是感叹于你写的“搞了几年开发”
我个人认为“搞了几年开发”的技术人员不可能不知道上面的内容。
你错了,我看清楚了你的问题才说那句话的。
你题目中的类MyClass没有继承,那么就是继承自JAVA的Object。因此你所说的hashCode就是Object的hashCode。
关于Object的hashCode,在JAVA DOC中,有这段话:
* As much as is reasonably practical, the hashCode method defined by
* class <tt>Object</tt> does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer, but this implementation
* technique is not required by the
* Java<font size="-2"><sup>TM</sup></font> programming language.)
也就是说:Object的hashCode,(一般)是根据对象的内部地址(internal address)转化(计算)而来的。
从理论上(我说的是理论上,而实际上除非你非常深入了解JVM),如果我们如果找到了这个内部地址,那么我们还是有办法取回对象的。可是这个算法可能(我是说可能,我也没看过源码)是不可逆的,也就是说,你不一定能通过hashCode反算出internal address。
当然现在唯一的一条路就显示出来了:
1、java的hashCode算法必须可逆
2、有办法把变量myclass1刷成你得到的internal address
=============
我说的“汗,狂汗”没有别的意思,也不是为了捞分!(没见过接分的这么说话的吧)
我只是感叹于你写的“搞了几年开发”
我个人认为“搞了几年开发”的技术人员不可能不知道上面的内容。
#13
我还是觉得从hashcode转化成对象不太可能
#14
解决方案还是有的吧,例如添加一个实时map,记录hashcode和对象引用
直接似乎是不行的
直接似乎是不行的
#15
TO hbwhwang:你说对了,搞了几年开发的人,不可道不知道上面内容,我六年前就知道Object类是所有类的超类,所有的对象中都默认继承Object类的方法. 我不知道我说过的内容中,你从哪里看出来我是不知道上面这个知识点的.你的JavaDoc的内容,在Eclipse上,随便Ctrl+点击"Object"这个单词都可以看到,至于hashCode()是一个native方法,我也知道,但不代表native方法中实现的东西,就不能提取出来,万一sun另外做了另一个native方法,可以让你提取,而我们平时少用不知道呢? 又或者sun没有提供,但有人可以通过别的算法实现呢? 我就是因为有这个猜测所以才发贴问.
就像前面treeroot所说的,他讲的也是一个解决办法,不过他要继承一个自定义的类,如果要把JVM中所有的类都找得到,就得改变所有类的超类----Object类的源代码,上面我都讲过了这个问题了,证明我是很清楚Object是所有类的超类这个知识点的.我很谢谢他的回贴,虽然不是最好的,但起码他是提供了一个可行的解决方法.
我可以这样讲,通过hashcode返过来找到hashcode对应对象,是可以实现的,Spring中已经有相似的这个功能, 我没空研究它的源码,所以才想请教一下大家.
就像前面treeroot所说的,他讲的也是一个解决办法,不过他要继承一个自定义的类,如果要把JVM中所有的类都找得到,就得改变所有类的超类----Object类的源代码,上面我都讲过了这个问题了,证明我是很清楚Object是所有类的超类这个知识点的.我很谢谢他的回贴,虽然不是最好的,但起码他是提供了一个可行的解决方法.
我可以这样讲,通过hashcode返过来找到hashcode对应对象,是可以实现的,Spring中已经有相似的这个功能, 我没空研究它的源码,所以才想请教一下大家.
#16
了解,算了不吵了,如果我言语不慎伤害了你,再次跟你说声抱歉~
既然你认可treeroot(旗鲁特) 的办法,那我也可以给你一种办法,不用继承,但是得用工厂。
public MyClassFactory{
static Map<Integer,MyClass> map=new HashMap<Integer,MyClass>();
private MyClassFactory(){}
public synchronized static MyClass getInstance(){
MyClass m=new MyClass();
map.put(m.hashCode(),m);
return m;
}
public synchronized static Object getClassFromHashCode(int hascode){
return map.get(new Integer(hashCode));
}
}
在你每次需要MyClass对象的时候,不要new,而是这样:
MyClass myclass=MyClassFactory.getInstance();
然后你就可以:
MyClass myclass2=MyClassFactory.getClassFromHashCode(myclass.hashCode());
既然你认可treeroot(旗鲁特) 的办法,那我也可以给你一种办法,不用继承,但是得用工厂。
public MyClassFactory{
static Map<Integer,MyClass> map=new HashMap<Integer,MyClass>();
private MyClassFactory(){}
public synchronized static MyClass getInstance(){
MyClass m=new MyClass();
map.put(m.hashCode(),m);
return m;
}
public synchronized static Object getClassFromHashCode(int hascode){
return map.get(new Integer(hashCode));
}
}
在你每次需要MyClass对象的时候,不要new,而是这样:
MyClass myclass=MyClassFactory.getInstance();
然后你就可以:
MyClass myclass2=MyClassFactory.getClassFromHashCode(myclass.hashCode());
#17
OK,我的言论也有点过激,我也say sorry.
在这里,其实我说明一下我的设想,我们做项目做多了,就会发现,很多时候,出现的错误都是很隐蔽的,有时客户对你说:"我好像先按这里,再按那里,然后输入什么什么,再进去, 就报错了",但你到现场时,却怎么也发现不了错误,你要客户方的人再模拟一次,好像又没错,这个问题真的很烦,最后我们最终解决问题时发现,多数都是对象中的某些变量值不规范造成的,程序员的水平也有高有低,同一个人的精神状态也有好有差,你不可能要求程序一做出来,就有足够的健壮性去处理各种不规范的变量值的,所以我就设想出这样一种模式来处理-----当JVM抛出不能处理的Exception时, 马上得到抛出Exception的对象, 并把这个对象用ObjectOutPutStream记录在文本或者数据库中, 于是, 我们通过log4j的报错时间,就可以定位到记录这个错误对象的媒介,并把它还原, 从而就跟踪到这个对象里面的所有变量的值, 那么查起错来就容易多了.
我之所以问本贴的这个问题,其实就是发现Exception中,可以得到抛出错误的对象的hashcode, (用Thowable里面的getStackTrace()得到StackTraceElement,然后调用StackTraceElement.hashcode()得到抛出错误的对象的hashcode),然后我就想把Exception的构造方法改一下,进一步通过hashcode来得到发生错误的对象,然后再把这个对象持久化了,当然,这个对象要实现Serialisable接口, 这就是我的想法. TreeRoot的方法可以实现,但需要再把Object类的代码改一下.hbwhwang的方法其实和treeroot的原理是一样的,都是先把对象和hashcode存在一个静态的Map里面, 只不过换成了工厂模式.
我两个月前已经发贴问过这个问题,结果用Plain Java的API得不到实现方法, 后来用Spring的ExceptionInterceptor来实现了, 但是我不满足于功能的实现,我还想知道实现的原理.
在这里,其实我说明一下我的设想,我们做项目做多了,就会发现,很多时候,出现的错误都是很隐蔽的,有时客户对你说:"我好像先按这里,再按那里,然后输入什么什么,再进去, 就报错了",但你到现场时,却怎么也发现不了错误,你要客户方的人再模拟一次,好像又没错,这个问题真的很烦,最后我们最终解决问题时发现,多数都是对象中的某些变量值不规范造成的,程序员的水平也有高有低,同一个人的精神状态也有好有差,你不可能要求程序一做出来,就有足够的健壮性去处理各种不规范的变量值的,所以我就设想出这样一种模式来处理-----当JVM抛出不能处理的Exception时, 马上得到抛出Exception的对象, 并把这个对象用ObjectOutPutStream记录在文本或者数据库中, 于是, 我们通过log4j的报错时间,就可以定位到记录这个错误对象的媒介,并把它还原, 从而就跟踪到这个对象里面的所有变量的值, 那么查起错来就容易多了.
我之所以问本贴的这个问题,其实就是发现Exception中,可以得到抛出错误的对象的hashcode, (用Thowable里面的getStackTrace()得到StackTraceElement,然后调用StackTraceElement.hashcode()得到抛出错误的对象的hashcode),然后我就想把Exception的构造方法改一下,进一步通过hashcode来得到发生错误的对象,然后再把这个对象持久化了,当然,这个对象要实现Serialisable接口, 这就是我的想法. TreeRoot的方法可以实现,但需要再把Object类的代码改一下.hbwhwang的方法其实和treeroot的原理是一样的,都是先把对象和hashcode存在一个静态的Map里面, 只不过换成了工厂模式.
我两个月前已经发贴问过这个问题,结果用Plain Java的API得不到实现方法, 后来用Spring的ExceptionInterceptor来实现了, 但是我不满足于功能的实现,我还想知道实现的原理.
#18
如果用Map来分别存放hashcode ,Object的这种方法,是可行,但会有一个问题,随着系统的运行,Map中的Object越来越多,而不释放,这就有危险了。
#19
起始修改java.lang.Object源码是行的通的,但是绝对不推荐
只要自己写一个java.lang.Object.java,重新定义一些方法,要么重新打包rt.jar里面
要么启动的时候放到bootclasspath前面,这样引导类加载器就会加载你实现的Object,
儿忽略掉rt.jar中的Object(不过这个参数不是标准参数)
java -Xboolclasspath/p myobject.jar
只要自己写一个java.lang.Object.java,重新定义一些方法,要么重新打包rt.jar里面
要么启动的时候放到bootclasspath前面,这样引导类加载器就会加载你实现的Object,
儿忽略掉rt.jar中的Object(不过这个参数不是标准参数)
java -Xboolclasspath/p myobject.jar
#20
haha, 大师们都跑这开会来啦?兄弟搬个板凳来学习学习 ^_^
楼主提出这个问题的初衷实在让兄弟感到钦佩,难能可贵!
如果楼主能在一开始就把背景交待一下就更好了。现在经常看到一些帖子,上来就问一个看似比较离奇的问题,等纠缠到最后发现他遇到的问题根本就不应该用他想的思路去解决。我当然不是说本帖,只是说如果一开始就交待清楚的话,能避免不少误会。
楼主说的“项目中纠错”的问题,的确是个问题。以前我没想到还可以用这种手段处理,以后得多想想了 *_*
楼主提出这个问题的初衷实在让兄弟感到钦佩,难能可贵!
如果楼主能在一开始就把背景交待一下就更好了。现在经常看到一些帖子,上来就问一个看似比较离奇的问题,等纠缠到最后发现他遇到的问题根本就不应该用他想的思路去解决。我当然不是说本帖,只是说如果一开始就交待清楚的话,能避免不少误会。
楼主说的“项目中纠错”的问题,的确是个问题。以前我没想到还可以用这种手段处理,以后得多想想了 *_*
#21
maquan('ma:kju) :
别太当回事~~
你去研究一下,就不会滔滔江水了~~
别太当回事~~
你去研究一下,就不会滔滔江水了~~
#22
呵呵,如果我一开始就说得那么详细,恐惊很多人一看就觉得太复杂,没人回贴,贴子很快就沉下去了。
#23
使用AspectJ,例:
public interface HashCode
{
public int hashCode();
}
@Aspect
public class HashCodeImpl implements HashCode
{
public int hashCode()
{
//...在这里将对象和它的hasCode值进行缓存
}
@DeclareParents ( value = "foo.MyClass1" , defaultImpl = HashCodeImpl.class )
//这时的foo.MyClass是需要通过hasCode来获取原对象的类
private HashCode h1 ;
//如果有多个类需要处理,如下添加
@DeclareParents ( value = "foo.MyClass2" , defaultImpl = HashCodeImpl.class )
private HashCode h2 ;
....
}
使用AspectJ编译(可以是jar或java文件)后就可以只对需要的类进行这样的处理,
此方法对原代码没有任何改变
public interface HashCode
{
public int hashCode();
}
@Aspect
public class HashCodeImpl implements HashCode
{
public int hashCode()
{
//...在这里将对象和它的hasCode值进行缓存
}
@DeclareParents ( value = "foo.MyClass1" , defaultImpl = HashCodeImpl.class )
//这时的foo.MyClass是需要通过hasCode来获取原对象的类
private HashCode h1 ;
//如果有多个类需要处理,如下添加
@DeclareParents ( value = "foo.MyClass2" , defaultImpl = HashCodeImpl.class )
private HashCode h2 ;
....
}
使用AspectJ编译(可以是jar或java文件)后就可以只对需要的类进行这样的处理,
此方法对原代码没有任何改变
#24
AspectJ编译后的字节码实际上给所有经过处理的类加上了接口HashCode,接口的方法实现是HashCodeImpl中的实现
#25
mark!
#26
原来AspactJ是这样用的,谢谢flyxxxx让我们长了见识~~!!!^-^
TO treeroot:你说“要么启动的时候放到bootclasspath前面,这样引导类加载器就会加载你实现的Object,”
能不能具体讲一下,怎么把myobject.jar 启动的时候放到bootclasspath前面?你的那句命令不能运行,我在google粗略地找了一下,也没有相关的资料。谢谢了。
贴子再加10分。
TO treeroot:你说“要么启动的时候放到bootclasspath前面,这样引导类加载器就会加载你实现的Object,”
能不能具体讲一下,怎么把myobject.jar 启动的时候放到bootclasspath前面?你的那句命令不能运行,我在google粗略地找了一下,也没有相关的资料。谢谢了。
贴子再加10分。
#27
http://blog.csdn.net/treeroot/archive/2006/07/22/960778.aspx
#28
先收藏再研究