- 浏览: 1253558 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (461)
- 心得体会 (166)
- Hibernate (9)
- Spring (12)
- Struts1 (3)
- Ajax (4)
- Java (54)
- 其他技术 (21)
- 数据库 (29)
- EXT (0)
- Struts2 (7)
- Xml (3)
- HTML (5)
- JavaScript (12)
- 面试相关 (3)
- BLOG (11)
- 计算机 (11)
- PMP (0)
- OGNL (1)
- LINUX (79)
- AIX (1)
- Ubuntu (14)
- Android (1)
- hadoop (3)
- LINUX debian (3)
- 心得体会 eclipse (2)
- JSTL (1)
- 心得体会 hadoop cdh3u5 (2)
- maven (5)
- Hive (1)
- 心得体会 工具使用 (3)
- spring data jpa Query By Example(QBE) (1)
- nginx (2)
- Apache (1)
- mysql (6)
- LINUX mysql (2)
- freemaker (1)
- 心得体会 FastDFS Nginx 断点续传 (1)
- LINUX FastDFS Nginx 断点续传 (1)
- 心得体会 Mybatis (2)
- 心得体会 mysql (4)
- php (1)
- logback 简介 (5)
- EL (1)
- Tomcat (2)
- win7 (1)
- LINUX maven (1)
- scrumworks (1)
- linux nginx (6)
- svn linux (1)
- mac (3)
- mac git (1)
- git (1)
- nexus (2)
- golang (1)
- LINUX Redis (1)
- mac oracle (1)
最新评论
-
a785975139:
有用
MySQL Error :SHOW PROFILES -
yijiulove:
弄了半天,参照你的方法解决了.特来感谢,知道可能是先加载,但是 ...
Spring和Mybatis整合时无法读取properties的处理方案 -
chenjinqi1987:
Missing com.sun.jdmk:jmxtools:jar:1.2.1 -
leifeng2:
请问怎么使用,运行之后d盘符没有生产音频文件呢?
java录音程序 -
sundful:
chenghong726 写道你好,我也遇到你这样的问题,按照 ...
Spring和Mybatis整合时无法读取properties的处理方案
这已经笔者写的第三篇Java杂记了,庆幸前两篇一直得到论坛朋友们的支持鼓励,还望大家继续指正不足之处。笔者也一直渴望通过这样方式清醒的自审,来寻找自己技术上的不足之处,希望和共同爱好Java的同仁们一起提高。
前两次分别讲述了关于jvm、jdk、jre、collection、classLoader和一些Design Pattern的自我理解。这次仍然不准备开始过渡到j2ee中,因为觉得还有一些琐碎的j2se的问题没有总结完毕。
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()却是可以的,因为并没有在同一对象上加两把锁的行为产生。
这样大家能理解了麽?明白它的原理能更好的帮助大家设计同步机制,不要滥用加锁。
前两次分别讲述了关于jvm、jdk、jre、collection、classLoader和一些Design Pattern的自我理解。这次仍然不准备开始过渡到j2ee中,因为觉得还有一些琐碎的j2se的问题没有总结完毕。
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数字、货币值和百分数等的格式化处理
2016-09-13 18:36 981如果我们用下列语句输出一个数 System.out.pri ... -
jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令
2016-08-17 09:01 1167公司内部同事分享的一篇文章 周末看到一个用jstack查看死锁 ... -
jstat查看jvm的GC情况[转]
2016-08-17 08:58 799jps(Java Virtual Machine Proce ... -
Java 7, Ubuntu 12.10 64bit issues
2015-04-13 11:57 1379At first Maven failed with the ... -
Map遍历的两种方式
2014-10-20 11:09 924第一种: Map map = new HashMap() ... -
对Map按key和value分别排序
2014-10-20 11:01 962一.理论准备 Map是键值对的集合接口, ... -
【转】程序包com.sun.image.codec.jpeg不存在 问题的完美解决
2014-10-09 13:43 1291maven下面编译失败,失败提示信息为:程序包com.sun ... -
关于系统读取properties配置文件的路径问题,包括打成jar包的运行文件
2014-10-08 18:05 1837在当前的一个项目中, ... -
java中的equals和hashCode(转载)
2014-01-15 14:01 882在某些时候,我们需要判断两个对象是否相等。Java的每个类都继 ... -
关于java中BufferedReader的read()及readLine()方法的使用注意
2013-06-05 16:08 2646以前学习的时候也没有太在意,在项目中使用到了才发现呵呵 1 ... -
java -cp
2013-04-19 12:03 1474java -cp classpath Specify a ... -
maven 打包可执行jar的方法
2013-04-19 12:02 48931.修改pom.xml增加如下内容 [html] ... -
Java 反射测试
2010-08-10 16:54 1310import java.lang.reflect.Invoca ... -
Creating Dynamic Web Project using Maven in Eclipse
2010-08-10 13:10 2873While using Maven as build tool ... -
建立你自己的本地仓库(Maven仓库管理-Nexus)
2010-07-02 13:34 4106这一个章节,我分两部分来介绍,首先介绍一下Maven的仓库,然 ... -
Java枚举类
2010-04-13 11:30 68191.创建一个最简单的枚 ... -
Java堆.栈和常量池 笔记
2010-04-07 09:26 12331.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程 ... -
探讨代理模式与Java反射机制的应用
2010-04-01 09:53 1096代理模式,相信大多数人都非常熟悉,常见的实现方式是通过公共接 ... -
Java的代理模式(通过公共接口实现)
2010-04-01 09:51 1241代理模式的一种常见的实现方案是,定义一个接口或抽象类,并派生出 ... -
Java多线程编程要点
2010-03-31 09:30 11201、 认识Thread和Runnable Java中实现 ...
相关推荐
Java学习杂谈系列涵盖了许多关于Java编程的基础概念和机制,以下是对这些知识点的详细解读: 1. **动态加载机制**: 动态加载机制是Java语言的一个关键特性,它使得程序在运行时才能确定哪些类需要加载。当你声明...
### Java学习杂谈:深入解析Java的动态加载机制、类搜索原理及JDK与JRE的区别 #### 动态加载机制解析 Java的学习者往往在掌握面向对象编程(OOP)概念时,会遇到“动态加载机制”这一关键点。相较于C++中面向过程...
"主流编程语言的选择和学习杂谈" 本文主要介绍了当前主流编程语言的特点、发展趋势和学习方法,为新手提供了学习参考。 一、Java 语言 Java 语言是由 Sun 公司开发的,目前由 Java Community Process 控制。Java ...
[学习资料] 09年Java认证考试:我的Java学习道路 [学习资料] 09年Java认证考试:学好java开发的关键七步 [学习资料] 09年Java认证考试:JAVA求素数算法实现 [学习资料] 09年Java认证考试:java类的构造方法 [学习...
Java的类加载器(Classloader)分为三个层次:Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader。Bootstrap ClassLoader负责加载JRE的核心类库,位于`jre/classes`路径下;Extension ...
总的来说,《Java陈国君(第二版)课件》是一个全面的Java学习资源,无论你是零基础的新手,还是希望进一步提升的开发者,都能从中受益匪浅。通过深入学习和实践,你将能够掌握Java编程的核心技能,为未来的编程生涯...
例如,Python有PEP 8,Java有Google Java Style Guide,这些都是值得遵循的编码规范。 最后,项目管理在大型项目中扮演着重要角色。了解敏捷开发理念,如Scrum或Kanban,可以帮助团队有效地组织和管理任务。同时,...
### Java框架知识学习 #### Struts 1.x **手写MVC框架** - **概念理解**:在探讨Struts框架之前,先了解MVC(Model-View-Controller)架构模式的基本原理。这是一种广泛应用于软件工程的设计模式,尤其是用于Web...
**1.6 JAVA面试题解惑系列(六)——字符串(String)杂谈** - **知识点**:深入探讨字符串处理技术,包括字符串拼接、比较、格式化等常见操作的内部实现,以及性能优化建议。 **1.7 JAVA面试题解惑系列(七)——...
- 发布工具:Jenkins是自动发布工具的首选,它既关乎管理人员的经验,也关系到开发人员的学习与适应能力。Jenkins能够在持续集成中发挥关键作用,提高软件交付的速度和质量。 - Bug管理:合理的Bug管理能够确保软件...
【JAVA面试题解惑系列】是一系列专门...以上只是《JAVA面试题解惑系列》中部分主题的简要介绍,每篇文章都深入探讨了相关主题,为面试者提供了丰富的学习资料。掌握这些知识点,将有助于在面试中表现出扎实的Java基础。
在IT行业中,J2EE(Java 2 Platform, Enterprise Edition)是一个广泛使用的开源企业级应用开发平台,由Oracle...通过深入学习和实践这两个技术,开发者可以更好地应对复杂的业务场景,打造健壮、可维护的Java应用。
“JAVA面试题解惑系列(六)——字符串(String)杂谈”可能涉及到String池的概念,即JVM会缓存重复的字符串,以提高性能。此外,String的equals()和==的区别也常常是面试的焦点,前者比较内容,后者比较对象引用。 ...
C++或Java则适合深入理解面向对象编程。 3. **算法与数据结构**:程序设计的核心是解决问题,这往往涉及算法的选择和应用。基础算法如排序(冒泡、快速、归并)、查找(线性、二分)以及递归等,是每个程序员必备的...
首先,编程语言的学习与实践部分可能会对编程新手非常友好,这里可以介绍一些当前市场上流行的语言,比如Python、Java、JavaScript等,并且给出学习这些语言的步骤、技巧和最佳实践。同时,对于经验丰富的开发者来说...
这篇"Android开发杂谈"涵盖了从系统组成、启动过程到关键组件的解析,旨在为初学者提供一个全面的理解框架。 Android系统是由多个层次构成的,包括Application、Framework、Native Libraries、Userspace Drivers...
Swing是Java编程语言中用于构建图形用户界面(GUI)的一个工具包,它是Java Foundation Classes ...通过学习和理解这个初版本的源码,开发者能够更好地掌握Swing的使用,并在此基础上构建更复杂的Java GUI应用程序。
深入浅出 例子实用 代码丰富 是java程序人员学习和深入数据结构和算法的实用读物 由于资源过大,分两部分上传 本资源为第二部分