查看文章 |
java学习杂谈(三)
2008-07-11 00:24
{1,2,3,4}; System.out.println(A.hashCode()); System.out.println(B.hashCode()); 这明明是同一种组合,却是不同的hashCode,加入Set的时候会被当成不同的对象。这个时 候我们就需要自己来重写hashCode()方法了,如何写呢?其实也是基于原始的hashCode(), 毕竟那是操作系统的实现, 找到相通对象唯一的标识,实现方式很多,笔者的实现方式是 : 首先重写了toString()方法: return A[0]“ ” A[1]“ ” A[2]“ ” A[3]; //显示上比较直观 然后利用toString()来计算hashCode(): return this.toString().hashCode(); 这样上述A和B返回的就都是”1234”,在测试toString().hashCode(),由于String在内存中的副本 是一样的,”1234”.hashCode()返回的一定是相同的结果。 说到这,相信大家能理解得比我更好,今后千万不要再误解hashCode()方法的作用。 3. 关于Class类的成员函数与Java反射机制 很早刚接触Java就听很多老师说过Java的动态运行时机制、反射机制等。确实它们都是 Java的显著特点,运行时加载笔者在第一篇介绍过了,现在想讲讲反射机制。在Java中, 主要是通过java.lang包中的Class类和Method类来实现内存反射机制的。 熟悉C 的人一定知道下面这样在C 中是做不到的: 运行时以字符串参数传递一个类名, 就可以得到这个类的所有信息,包括它所有的方法,和方法的详细信息。还可以实例化一 个对象,并通过查到的方法名来调用该对象的任何方法。这是因为Java的类在内存中除了 C 中也有的静态动态数据区之外,还包括一份对类自身的描述,也正是通过这描述中的信 息,才能帮助我们才运行时读取里面的内容,得到需要加载目标类的所有信息,从而实现 反射机制。大家有没有想过当我们需要得到一个JavaBean的实例的时候,怎么知道它有哪 些属性呢?再明显简单不过的例子就是自己写一个JavaBean的解析器: a. 通过Class.forName(“Bean的类名”)得到Class对象,例如叫ABeanClass b. 通过ABeanClass的getMethods()方法,得到Method[]对象 c. 按照规范所有get方法名后的单词就代表着该Bean的一个属性 d. 当已经知道一个方法名,可以调用newInstance()得到一个实例,然后通过invoke()方法将 方法的名字和方法需要用的参数传递进去,就可以动态调用此方法。 当然还有更复杂的应用,这里就不赘述,大家可以参考Class类和Method类的方法。 4. 坦言Synchronize的本质 Synchronize大家都知道是同步、加锁的意思,其实它的本质远没有大家想得那么复杂。声 明Synchronize的方法被调用的时候,锁其实是加载对象上,当然如果是静态类则是加在类 上的锁,调用结束锁被解除。它的实现原理很简单,仅仅是不让第二把锁再次被加在同一 个对象或类上,仅此而已。一个简单的例子足以说明问题: class A{ synchronized void f(){} void g(){} } 当A的一个对象a被第一个线程调用其f()方法的时候,第二个线程不能调用a的synchronized方 法例如f(),因为那是在试图在对象上加第二把锁。但调用g()却是可以的,因为并没有在同 一对象上加两把锁的行为产生。 这样大家能理解了麽?明白它的原理能更好的帮助大家设计同步机制,不要滥用加锁 |