当前位置: 代码迷 >> J2SE >> 关于HashSet的一个奇葩有关问题
  详细解决方案

关于HashSet的一个奇葩有关问题

热度:100   发布时间:2016-04-23 20:43:23.0
关于HashSet的一个奇葩问题
本帖最后由 li385805776 于 2014-05-18 09:49:56 编辑
看HashSet源码时遇到的一个问题
/**
     * Returns a shallow copy of this <tt>HashSet</tt> instance: the elements
     * themselves are not cloned.
     *
     * @return a shallow copy of this set
     */
    public Object clone() {
        try {
            HashSet<E> newSet = (HashSet<E>) super.clone();
            newSet.map = (HashMap<E, Object>) map.clone();
            return newSet;
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }


为什么newSet.map = (HashMap<E, Object>) map.clone();中可以访问到newSet的map。如果没看过HashSet源码的,可以针对下面代码理解。
public class Test {
public static void main(String[] args) {
System.out.println(new Test().visitNewA());
}

Test(){}

Test(int a){
this.a=a;
}
private int a = 10;

public int visitNewA(){
int s = new Test(11).a;
return s;
}
}


代码没有任何错误,结果为11。问题是,在visitNewA()方法中,为什么可以用new Test(11).a 来访问a
------解决方案--------------------
我觉得这是一个关于JAVA深拷贝和浅拷贝的问题。
public Object clone() {
        try {
            HashSet<E> newSet = (HashSet<E>) super.clone();  //(1)
            newSet.map = (HashMap<E, Object>) map.clone();   //   (2)
            return newSet;
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }
其中(1)处是产生一个和当前HashSet对象一样的对象newSet,但是这个newSet对象里面的map引用指向的仍然是当前对象的map。所以需要(2)这行代码重新拷贝一个HashMap<E,Object>对象。这才算拷贝完成!
至于你说的测试代码,我说一下程序执行流程,你可以设置断点跟一下!
new Test().visitNewA()
等价于:
创建一个Test对象,其中a=10。
然后这个对象调用visitNewA()方法——new   Test(11).a
方法内部创建一个Test局部对象,按照JAVA对象的初始化流程,a先等于10,然后等于11。然后这个局部对象访问它的成员属性a即为11.

------解决方案--------------------
这是Java语言的规定,就是这样的
详见Java Language Specification
http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6
其中说明了
引用
A private class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor. It is not inherited by subclasses.

明确了在包括这个private成员的最顶级Class里都是可以访问这个private成员的
  相关解决方案