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是浅复制还是深复制呢?