记JAVA的二三事(2)——JVM存储区+hashCode()和equals()的隐式约定

来源:互联网 发布:实战最强的武术知乎 编辑:程序博客网 时间:2024/06/05 11:08

1.JAVA虚拟机存储空间分布图:

      

常量池是一个与Heap和Stack并列的存储区,存在于Method Area中。常量池存放字符串常量和基本数据类型常量。如果一个字符串在编译期已经创建好("")则存储在常量池中,如果是运行期(new)才能确定的则存储在堆中。

堆中存放运行时的对象。

栈中存放对象的引用、基本数据类型的变量以及运行时的方法。

2.hashCode()和equals()的隐式调用约定:

如果两个对象相等(equal),那么他们一定有相同的哈希值。

如果两个对象有相同的哈希值,他们未必相等(equal)。

一般来说Object类默认的equals()同于==,即比较堆内存中的存放地址。但是在String,Integer,Date等类中覆写了这个方法,有了其自身的实现。比如在String中的equals就是比较字符串的内容是否相等。

这条约定可以应用于Map<Key,Value>的存取当中。下面给出一个例子:

import java.util.HashMap;public class Ball {// this表示对当前对象的引用private String color;public Ball(String color) {this.color = color;}public static void main(String[] args) {Ball b1 = new Ball("red");Ball b2 = new Ball("green");HashMap<Ball, String> map = new HashMap<Ball, String>();map.put(b1, "10");map.put(b2, "20");System.out.println("从map中取出key为<颜色是green的Ball>的String值>" +map.get(new Ball("red")));}}
首先介绍一下Map的存取机制:Map内部有一个顶层数组,首先通过Key对象的hashCode()计算出顶层数组通往第二层数组的索引,通过这个索引找到第二层数组,在第二层数组中使用equals()判断是否存在key键对应的value值。

Object类中默认的hashCode()是让每个对象都返回一个不用的int值,所以上述代码一定会返回null。那么如何通过上述代码获取Map中以颜色是red的Ball对象为key的Value值(在获取时不要求key键的对象与存储时的对象是同一个对象,只要求对象中的颜色字段相等)?我们要覆写一下hashCode()和equals()方法。

首先是equals():当对象引用指向的是Ball的对象并且该对象的color字段相等时,我们就判定为true。

@Overridepublic boolean equals(Object obj) {if (!(obj instanceof Ball)) {return false;}return this.color == ((Ball) obj).color;}
其次是hashCode():返回Ball类对象的color字段字符串的长度。
@Overridepublic int hashCode() {return this.color.length();}
看下这样是否符合开始说的约定:equals返回true时hashCode一定相等,hashCode相等时equals不一定返回true。很明显这符合约定。再次运行一下程序,发现果然成功取出了value值("10")。下面给出我理解中的Map查询机制图:

3.如何在HTTP客户端和服务器之间保持状态:Cookie、Session、ViewState、Application

4.OO的概念和设计原则(面向对象):使用类和继承的构造机制,拥有继承、封装、多态等几大特性。

5.this的用法:

表示对当前对象的引用。

区分类的成员变量和函数的参数(本质上同上一点)。

在构造方法中引用自身满足参数类型的构造器。



3 0