关于Class类的成员函数与Java反射机制,坦言Synchronize的本质

转载 2012年03月21日 16:22:06
    1.   关于Object类理解

        大家都知道Object是所有Java类的基类,   意味着所有的Java类都会继承了Object的11个方法。建议大家去看看Object的   11个成员函数的源代码,就会知道默认的实现方式。比如equals方法,默认实现就是用”==”来比较,即直接比较内存地址,返回true   或者   false。而toString()方法,返回的串组成方式是??

        ”getClass().getName()   +   ”@”   +   Integer.toHexString(hashCode())”

        其实不用我过多的解释,大家都能看懂这个串的组成。接下来再看看hashCode():

        public   native   int   hashCode();

        由于是native方法,跟OS的处理方式相关,源代码里仅仅有一个声明罢了。我们有兴趣的话完全可以去深究它的hashCode 到底是由OS怎么样产生的呢?但笔者建议最重要的还是先记住使用它的几条原则吧!首先如果equals()方法相同的对象具有相通的hashCode,但 equals   ()对象不相通的时候并不保证hashCode()方法返回不同的整数。而且下一次运行同一个程序,同一个对象未必还是当初的那个 hashCode()   哦。

        其余的方法呢?nofigy()、notifyAll()、clone()、wait()都是native方法的,说明依赖于操作系统的实现。最后一个有趣的方法是finalize(),类似C++的析构函数,签名是protected,证明只有继承扩展了才能使用,方法体是空的,默示什么也不做。它的作用据笔者的了解仅仅是通知JVM此对象不再使用,随时可以被销毁,而实际的销毁权还是在于虚拟机手上。那么它真的什么也不做麽?未必,实际上如果是线程对象它会导致在一定范围内该线程的优先级别提高,导致更快的被销毁来节约内存提高性能。其实从常理来说,我们也可以大概这样猜测出 jvm做法的目的。

        2.   关于重载hashCode()与Collection框架的关系

笔者曾经听一位搞Java培训多年的前辈说在他看来hashCode方法没有任何意义,仅仅是为了配合证明具有同样的hashCode会导致 equals   方法相等而存在的。连有的前辈都犯这样的错误,其实说明它还是满容易被忽略的。那么hashCode()方法到底做什么用?

        学过数据结构的课程大家都会知道有一种结构叫hash   table,目的是通过给每个对象分配一个唯一的索引来提高查询的效率。那么Java也不会肆意扭曲改变这个概念,所以hashCode唯一的作用就是为支持数据结构中的哈希表结构而存在的,换句话说,也就是只有用到集合框架的   Hashtable、HashMap、HashSet的时候,才需要重载hashCode()方法,

这样才能使得我们能人为的去控制在哈希结构中索引是否相等。笔者举一个例子:

        曾经为了写一个求解类程序,需要随机列出1,2,3,4组成的不同排列组合,所以笔者写了一个数组类用int[]来存组合结果,然后把随机产生的组合加入一个HashSet中,就是想利用HashSet不包括重复元素的特点。可是HashSet怎么判断是不是重复的元素呢?当然是通过   hashCode()返回的结果是否相等来判断啦,可做一下这个实验:

        int[]   A   =   {1,2,3,4};

        int[]   B   =   {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()却是可以的,因为并没有在同一对象上加两把锁的行为产生。

        这样大家能理解了麽?明白它的原理能更好的帮助大家设计同步机制,不要滥用加锁。

对于JAVA反射机制和CLASS类的个人理解

上周上课老师点我起来回答问题,问了一下JAVA反射机制,我本来对JAVA用得不多,加上有一段时间没有看过了,所以并没有能够答出来,之后就想要好好理解理解,加上老师布置作业让弄懂JAVA反射和Class...
  • qq_32377239
  • qq_32377239
  • 2016年10月16日 19:41
  • 327

java反射,获取类对象所有成员变量,从字符串调用函数

java反射,获取类对象所有成员变量,从字符串调用函数
  • scimence
  • scimence
  • 2015年06月19日 09:32
  • 9497

《Java反射的应用》

《Java反射的应用》最近在研究Java并发相关的类库,看到了AtomicIntegerFieldUpdater,这个类就是利用反射来完成原子更新字段的值。由于自己对反射相关的操作都忘记了,今天刚好借...
  • u010412719
  • u010412719
  • 2016年07月29日 21:40
  • 450

Java利用反射机制遍历成员变量

package reportcustomize; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetE...
  • WSKinght
  • WSKinght
  • 2015年01月23日 13:20
  • 2450

Java笔记——利用反射机制获取成员变量及成员方法

package tmp; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; im...
  • pat_datamine
  • pat_datamine
  • 2015年01月09日 14:19
  • 1472

java反射机制 以及通过反射获得类的变量字段,方法,构造函数

反射机制 首先获得类模板的方式有三种: 1. Class cls=对象名.getClass();//使用这种方式获取类模板有局限性:必须现有对象才能得到类模板对象 2.Class cls=C...
  • AlwaysDebug
  • AlwaysDebug
  • 2015年09月08日 21:07
  • 3736

Java反射机制获取/调用类的属性和方法

Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。 ...
  • YagamiMisaMisa
  • YagamiMisaMisa
  • 2017年04月05日 16:32
  • 627

利用Java反射机制获得私有成员

1.Java对于一些类的封装使得私有属性无法在类外获得,但是java可以于运行时加载、探知、使用编译期间完全未知的classes,利用安全管理器及反射,可以在不修改源码 的基础上访问私有成员。 举例:...
  • apxar
  • apxar
  • 2013年09月26日 22:49
  • 4915

Java反射 类类型就是可以操作的类本身 如何通过反射得到函数 函数返回值 函数参数

Java反射的个人理解:反射就是一种 了解类并使用类 的一套方法; 学过Java基础的都知道如何进行类的实例化,也知道通过实例调用变量或者方法; 但很多时候类不是我们自己写的,所以我们对类不是很了解...
  • evanxuhe
  • evanxuhe
  • 2017年07月19日 17:08
  • 481

通过反射机制调用某个类的方法

要通过反射机制调用某个类的方法,主要用到了下面这个方法: public Object invoke(Object obj,Object... args) 这个方法对带有指定参数的指定对象调用由此 ...
  • Handsome_fan
  • Handsome_fan
  • 2017年02月04日 14:27
  • 2907
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于Class类的成员函数与Java反射机制,坦言Synchronize的本质
举报原因:
原因补充:

(最多只允许输入30个字)