Java基础知识(不断更新)
1.关于基类构造器与导出类构造器的注意事项
public class A { //此处如果没有无参构造方法会报编译错误,因为编译器不知道在导出类中用哪个构造器构造基类 public A() { System.out.println("Constructor A"); } public A(int i) { System.out.println("Constructor A int"); } } public class B { public B() { System.out.println("Constructor B"); } }
2.方法调用绑定
将一个方法调用同一个方法主体联系起来被称作绑定。若在程序执行前进行绑定,叫做前期绑定。如果在运行时根据对象的类型进行绑定就叫后期绑定。
Java中除了static和final方法(private方法属于final方法)之外,其他所有的方法都是后期绑定。
3.为什么在重写equals()方法时,一般都会重写hashCode()方法?
基于散列法的集合需要使用hashCode()方法返回的散列值存储和管理元素,例如Hashtable、HashMap和HashSet等,在使用这些集合时,首先会根据元素对象的散列码值确定其存储位置,然后再根据equals()方法结果判断元素对象是否已经存在,最后根据判断结果进行不同处理。因此,实际应用时如果重写了equals()方法,那么hashCode()方法也应该被重写。
HashMap中put的说明:在此映射中关联指定值与指定键。如果该映射包含了一个该键的映射关系,则旧值被替换。
以下是JDK1.5中HashMap类put方法的源码:
/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
4.如何重写hashCode()方法?
hashCode()方法在重写时通常按照以下设计原则实现。
(1). 把某个非零常数值,例如17,保存在int型变量result中。
(2).对于对象中每一个关键域f(指equals方法中考虑的每一个域)参照以下原则处理
- boolean型,计算(f?0:1)。
- byte、char和short型,计算(int)。
- long型,计算(int)(f^(f>>>32))。
- float型,计算Float.floatToIntBits(afloat)。
- double型,计算Double.doubleToLongBits(adouble)得到一个long,再执行long型的处理。
- 对象引用,递归调用它的hashCode()方法。
- 数组域,对其中每个元素调用它的hashCode()方法。
(3).将上面计算得到的散列码保存到int型变量c,然后执行result = 37 * result + c;
(4).返回result。
为了维护hashCode常规协定,在重写hashCode()方法时需要遵循一定的设计原则,具体如上所述。
public int hashCode() { int hashCode = 7; for (Iterator it = this.genericArgumentValues.iterator(); it.hasNext();) { ValueHolder valueHolder = (ValueHolder) it.next(); hashCode = 31 * hashCode + valueHolder.contentHashCode(); } hashCode = 29 * hashCode; for (Iterator it = this.indexedArgumentValues.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); Integer key = (Integer) entry.getKey(); ValueHolder value = (ValueHolder) entry.getValue(); hashCode = 31 * hashCode + (value.contentHashCode() ^ key.hashCode()); } return hashCode; }
5.什么是clone?
在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B
任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。
解释:
浅复制(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用.
深复制(深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.就是说完全是新对象产生的.
public class B { } public class A { private B b = new B(); public B getB() { return this.b; } }
上面这段代码中A类中的getB()获取的B是浅复制还是深复制呢?
上一篇: 如何使用浏览器解析js代码
下一篇: tomcat编码问题根源-1