最近发四重新学习java的基础,从基本类型以及里面的各种方法开始看起,看的一本书《JAVA核心技术卷1,基础知识》,这是第十版,讲的JDK8的一些特性。 我在想我们创建对象的时候都是这样进行创建的
People p = new People(); Integer i = new Integer();但是String 和基本类型可以这么写
int i = 1; String s = "ssss";//这种写法,不是新创建的对象是在常量池中存放了一个ssss的字符串,在栈里面,如果没有引用则消失String 还可以这么写
String s = new String();//新建了一个String的对象,这个是创建了一个新的String的对象,在堆里面,不用的时候由垃圾回收器进行回收这里需要注意堆和栈的区别
看到String源码里面有了个这个方法:
public String(String original) { this.value = original.value; this.hash = original.hash; }这个构造方法作用是什么?构造方法传进来的参数的类型是他自己? 发现String这个类中有两个成员变量
private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0其中第二个hash他描述的是hash值,表示的是什么意思? 下面是相应的方法
/** * Returns a hash code for this string. The hash code for a * <code>String</code> object is computed as * <blockquote><pre> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * </pre></blockquote> * using <code>int</code> arithmetic, where <code>s[i]</code> is the * <i>i</i>th character of the string, <code>n</code> is the length of * the string, and <code>^</code> indicates exponentiation. * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }方法好像是返回一个hase值,具体是什么意思还是不太明白 然后我们深入的看了一下,发现Object类里面也有一个方法
/** * Returns a hash code value for the object. This method is * supported for the benefit of hash tables such as those provided by * {@link java.util.HashMap}. * <p> * The general contract of {@code hashCode} is: * <ul> * <li>Whenever it is invoked on the same object more than once during * an execution of a Java application, the {@code hashCode} method * must consistently return the same integer, provided no information * used in {@code equals} comparisons on the object is modified. * This integer need not remain consistent from one execution of an * application to another execution of the same application. * <li>If two objects are equal according to the {@code equals(Object)} * method, then calling the {@code hashCode} method on each of * the two objects must produce the same integer result. * <li>It is <em>not</em> required that if two objects are unequal * according to the {@link java.lang.Object#equals(java.lang.Object)} * method, then calling the {@code hashCode} method on each of the * two objects must produce distinct integer results. However, the * programmer should be aware that producing distinct integer results * for unequal objects may improve the performance of hash tables. * </ul> * <p> * As much as is reasonably practical, the hashCode method defined by * class {@code Object} does return distinct integers for distinct * objects. (This is typically implemented by converting the internal * address of the object into an integer, but this implementation * technique is not required by the * Java<font size="-2"><sup>TM</sup></font> programming language.) * * @return a hash code value for this object. * @see java.lang.Object#equals(java.lang.Object) * @see java.lang.System#identityHashCode */ public native int hashCode();里面对于这个方法的描述我也贴出来了,自己的英文不太好,看着百度翻译看的,对于里面的东西还是不太理解 Object是所有类的父类,所以String类里面重写了这个方法。 下面我们进行实验会发现一个有趣的现象
String string1 = "aaa"; String string2 = new String(string1); String string3 = new String("aaa"); System.out.println(string1==string2);//false 这个肯定是false,因为使用new时候是新建了一个String的对象,而string1是指向放在常量池中的一个地址(string2也是指向对象的一个地址) 但是他们的haseCode是一致的 System.out.println(string1.hashCode()); System.out.println(string2.hashCode()); System.out.println(string3.hashCode());//这三个个值是一样的 /** 但是如果是我们自己新建的实体类的话 **/ People p1 = new People(); People p2 = new People(); People p3 = p2; System.out.println(p1.hashCode()); System.out.println(p2.hashCode());//这里的值是不一样的,为什么? System.out.println(p3.hashCode());//这里p3和p2的值是一样的看一个文章说hashCode表示的是返回对象的地址值(不完全正确) 但是看Object这个类中的equals里面就是直接比较的地址的啊 我知道为啥String 的hashCode返回的是一样的了,因为他重写了hashCode这个方法(开始自己竟然没注意到。。)
public boolean equals(Object obj) { return (this == obj); }hashCode不一样肯定不是同一个对象,但是hashCode一样的不一定是同一个对象
补充个意外的 JAVA创建对象的时候如果是基本的或者String数据类型需要放到常量池中,就会使用常量池中的属性而不是在堆中新开辟一个空间。 比如说People这个类中有int eye;那么如果people1 的eye=1;people2的eye =1;那么这两个都是使用栈中的一个地址的引用