`
wesker0918
  • 浏览: 42678 次
  • 性别: Icon_minigender_1
  • 来自: 山东->北京
社区版块
存档分类
最新评论

Java学习杂谈(3)

阅读更多

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学习杂谈1-12

    Java学习杂谈系列涵盖了许多关于Java编程的基础概念和机制,以下是对这些知识点的详细解读: 1. **动态加载机制**: 动态加载机制是Java语言的一个关键特性,它使得程序在运行时才能确定哪些类需要加载。当你声明...

    java学习杂谈

    ### Java学习杂谈:深入解析Java的动态加载机制、类搜索原理及JDK与JRE的区别 #### 动态加载机制解析 Java的学习者往往在掌握面向对象编程(OOP)概念时,会遇到“动态加载机制”这一关键点。相较于C++中面向过程...

    主流编程语言的选择和学习杂谈

    "主流编程语言的选择和学习杂谈" 本文主要介绍了当前主流编程语言的特点、发展趋势和学习方法,为新手提供了学习参考。 一、Java 语言 Java 语言是由 Sun 公司开发的,目前由 Java Community Process 控制。Java ...

    2009年Java认证考试重点指导

    [学习资料] 09年Java认证考试:我的Java学习道路 [学习资料] 09年Java认证考试:学好java开发的关键七步 [学习资料] 09年Java认证考试:JAVA求素数算法实现 [学习资料] 09年Java认证考试:java类的构造方法 [学习...

    java杂谈-一个计算机专业学生几年的编程经验汇总谈.pdf

    此外,随着Java版本的更新,一些机制可能会有所变化,例如类加载器的工作方式在JDK 1.4到1.6之间可能有所调整,因此持续学习和跟踪Java的最新发展也是必要的。 总之,Java的动态加载机制、类加载器的工作原理以及...

    程序设计经验杂谈,程序设计,经验杂谈

    例如,Python有PEP 8,Java有Google Java Style Guide,这些都是值得遵循的编码规范。 最后,项目管理在大型项目中扮演着重要角色。了解敏捷开发理念,如Scrum或Kanban,可以帮助团队有效地组织和管理任务。同时,...

    java陈国君(第二版)课件

    总的来说,《Java陈国君(第二版)课件》是一个全面的Java学习资源,无论你是零基础的新手,还是希望进一步提升的开发者,都能从中受益匪浅。通过深入学习和实践,你将能够掌握Java编程的核心技能,为未来的编程生涯...

    java_学习资料

    ### Java框架知识学习 #### Struts 1.x **手写MVC框架** - **概念理解**:在探讨Struts框架之前,先了解MVC(Model-View-Controller)架构模式的基本原理。这是一种广泛应用于软件工程的设计模式,尤其是用于Web...

    臧圩人--JAVA面试题解惑系列合集.pdf

    **1.6 JAVA面试题解惑系列(六)——字符串(String)杂谈** - **知识点**:深入探讨字符串处理技术,包括字符串拼接、比较、格式化等常见操作的内部实现,以及性能优化建议。 **1.7 JAVA面试题解惑系列(七)——...

    组建java团队.pdf

    其中,Java开发人员的需求按照技术级别分为高级1人、中级2人和初级3到4人。根据项目需求,移动端可能需要Android和iOS开发人员,而Web前端需要至少1名专业人员。美工设计人员虽然可以复用,但至少应配置一名。对于...

    JAVA面试题解惑系列

    【JAVA面试题解惑系列】是一系列专门...以上只是《JAVA面试题解惑系列》中部分主题的简要介绍,每篇文章都深入探讨了相关主题,为面试者提供了丰富的学习资料。掌握这些知识点,将有助于在面试中表现出扎实的Java基础。

    程序设计经验杂谈

    3. **算法与数据结构**:程序设计的核心是解决问题,这往往涉及算法的选择和应用。基础算法如排序(冒泡、快速、归并)、查找(线性、二分)以及递归等,是每个程序员必备的技能。数据结构如数组、链表、栈、队列、...

    j2ee杂谈

    在IT行业中,J2EE(Java 2 Platform, Enterprise Edition)是一个广泛使用的开源企业级应用开发平台,由Oracle...通过深入学习和实践这两个技术,开发者可以更好地应对复杂的业务场景,打造健壮、可维护的Java应用。

    Java面试题详解,和一些基础知识的深入剖析,个人认为非常棒

    “JAVA面试题解惑系列(六)——字符串(String)杂谈”可能涉及到String池的概念,即JVM会缓存重复的字符串,以提高性能。此外,String的equals()和==的区别也常常是面试的焦点,前者比较内容,后者比较对象引用。 ...

    android开发杂谈

    这篇"Android开发杂谈"涵盖了从系统组成、启动过程到关键组件的解析,旨在为初学者提供一个全面的理解框架。 Android系统是由多个层次构成的,包括Application、Framework、Native Libraries、Userspace Drivers...

    swing开发杂谈--初版本程序源码

    Swing是Java编程语言中用于构建图形用户界面(GUI)的一个工具包,它是Java Foundation Classes ...通过学习和理解这个初版本的源码,开发者能够更好地掌握Swing的使用,并在此基础上构建更复杂的Java GUI应用程序。

    JAVA数据结构和算法

    深入浅出 例子实用 代码丰富 是java程序人员学习和深入数据结构和算法的实用读物 由于资源过大,分两部分上传 本资源为第二部分

    java俄罗斯方块

    综上所述,“java俄罗斯方块”项目涵盖了Java编程中的许多核心概念和技术,是学习和实践Java GUI编程、多线程、游戏开发和数据处理的绝佳案例。通过这个项目,开发者不仅可以掌握Java编程基础,还能深入理解游戏开发...

Global site tag (gtag.js) - Google Analytics