在形式参数类型中未声明的实际参数上调用方法

时间:2014-04-05 00:26:36

标签: java

我是一名经验丰富的程序员,但他是一名Java初学者。我有一个基准测试方法,它接受Map类型的参数并对其执行一些测试。它可以在HashMap,Hashtable,IdentityHashMap,TreeMap等上调用,因为它们都实现了Map。它们也都实现了Cloneable,但Eclipse告诉我不允许调用clone()方法。

private static double[] timeMapRemoves(Map<String,Integer>  map, 
                                       Collection<String> data, 
                                       int reps) {
  Map<String,Integer> map_clone = map.clone(); // OOPS -- "clone not accessible"

所以我深入研究了Oracle网站,并提出了各种解决方案

Map<String,Integer> map_clone = null;
Method clone = null;
try {
    clone = map.getClass().getMethod("clone", null);
    map_clone = (Map<String,Integer>)clone.invoke(map, null);
} catch (NoSuchMethodException | SecurityException 
         | IllegalAccessException | IllegalArgumentException
     | InvocationTargetException e) {
    e.printStackTrace();
}

我觉得我可能像Drool Rockworm一样深入研究并错过了规范的解决方案。

1 个答案:

答案 0 :(得分:1)

clone()protected,这意味着它只能从子类或同一个包中访问。

重申评论:

这一切都取决于调用它的上下文,如果该上下文是相同的类型,则可以调用protected方法。这里的上下文是一个不同的类型,因此无法调用它。

例如,当您将参数更改为HashMap<K, V>时,您可以调用它,因为HashMap会使用公共修饰符覆盖clone()方法。简而言之:您不能通过简单的Map<K, V>声明来做到这一点。

这意味着这样的情况会起作用:

class X {
    public X(){
        X newX = new X().clone();
    }
}

但这不会:

class X {
    public X(){
        String newString = "hello".clone();
    }
}

但话又说回来:

class X implements Map<String, String>{
    public X(){
        Map<String, String> map = new HashMap<>().clone();
    }
}

这样:

private static double[] timeMapRemoves(HashMap<String,Integer>  map, 
                                   Collection<String> data, 
                                   int reps) {

    Map<String, String> someMap = (Map<String, String>) map.clone();
}

注意我是如何将参数更改为HashMap<String,Integer>

为什么这样做的原因非常简单:HashMap定义了自己的clone()方法。

public Object clone() {
    HashMap<K,V> result = null;
    try {
        result = (HashMap<K,V>)super.clone();
    } catch (CloneNotSupportedException e) {
        // assert false;
    }
    result.table = new Entry[table.length];
    result.entrySet = null;
    result.modCount = 0;
    result.size = 0;
    result.init();
    result.putAllForCreate(this);

    return result;
}