【问题标题】:Overriding a static<K,V> method覆盖静态<K,V> 方法
【发布时间】:2018-05-09 12:39:42
【问题描述】:

我们有一种方法可以对两个通用对象进行比较:

    public static <K, V> Diff<K, V> check(K key, V act, V exp) {
        Diff<K, V> d = null;
        System.out.println(act.getClass());
        System.out.println(exp.getClass());
        // null checks
        if (exp == null && act == null) {
            // both null, so no difference
        } else if (exp == null) {
            d = new Diff<>(key, null, act);
        } else if (act == null) {
            d = new Diff<>(key, exp, null);
        } else {
            // compare the entries
            if (!exp.equals(act)) {
                d = new Diff<>(key, exp, act);
            }
        }

        return d;
    }

问题是,对于日期(java.sql.Date),有时日期而不仅仅是 MM/dd/yyyy 可能有 MM/dd/yyyy hh:mm 而另一个没有,所以它不处理他们平等。如果日期相同,我希望它们相等(我不关心小时、分钟、秒)。

所以我尝试创建一个新方法:

    public static <K, V> Diff<K, java.sql.Date> check(K key, java.sql.Date act, java.sql.Date exp) {
        Diff<K, java.sql.Date> d = null;

        // null checks
        if (exp == null && act == null) {
            // both null, so no difference
        } else if (exp == null) {
            d = new Diff<>(key, null, act);
        } else if (act == null) {
            d = new Diff<>(key, exp, null);
        } else {
            // compare the entries
            if (!exp.toString().equals(act.toString())) {
                d = new Diff<K, java.sql.Date>(key, exp, act);
            }
        }

        return d;
    }

由于某种原因,它不会让我说公共静态。无论如何,这并没有给出任何编译器错误,但是在程序中,我看到调用了原始方法。您可以在原始方法中看到我正在打印类,它们的值是

class java.sql.Date
class java.sql.Date

那么为什么我的专用方法没有被调用,而通用方法被调用了?

这是类(部分):

public static class Diff<K, V> {
    private K key;
    private V exp, act;
    ...
    ...
}

(我列出了数据,这里还有很多其他方法我展示...)

这里是调用函​​数。地图中有几行。有些很长,有些是字符串,有些是 sql 日期。 Key 始终是 String,但很多其他地方也可能会调用它,这可能具有其他数据类型的 key。

public static <K, V> List<Diff<K, V>> MapComparison(Map<K, V> map1, Map<K, V> map2) {
    List<Diff<K, V>> result = new LinkedList<Diff<K, V>>();

    // null checks
    if (map1 == null) {
        map1 = new HashMap<K, V>();
    }
    if (map2 == null) {
        map2 = new HashMap<K, V>();
    }

    HashSet<K> allKeys = new HashSet<K>();
    allKeys.addAll(map1.keySet());
    allKeys.addAll(map2.keySet());

    for (K key : allKeys) {
        V exp = map1.get(key);
        V act = map2.get(key);
        Diff<K, V> d = Diff.check(key, act, exp);
        if (d != null) {
            result.add(d);
        }
    }

    return result;
}

调用 MapComparison:

public static DiffListMap doComparison(RowList exp, RowList act, String keyName) {
    DiffListMap ret = new DiffListMap();
    DiffList diffs;

    // Loop through each expected row.
    for (Row exp_row : exp) {
        Object key = exp_row.get(keyName);
        diffs = null;
        boolean found = false;
        // Look for the corresponding actual row
        // using the unique key
        for (Row act_row : act) {
            if (act_row.get(keyName).equals(key)) {
                // If the correct one is found, do the comparison
                found = true;
                diffs = new DiffList(MapComparison(exp_row, act_row));
                // remove the row from the actual results.
                act.remove(act_row);
                break;
            }
        }

仅供参考

public static class Row extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;
}

【问题讨论】:

  • 是的,但我不知道如何在回复中正确格式化。这是未格式化的,因为它似乎从未在回复中格式化:太长了。我将不得不在下一条评论中发布
  • 不相关:始终使用有意义的名称。 check() 是什么意思?确切地说:没有。并提示:在第二种情况下,甚至没有定义 V 类型。 V 没有被使用,因此根本不应该出现在那里!
  • public static List> MapComparison(Map map1, Map map2) { List> 结果 = 新的 LinkedList>(); // null 检查 if (map1 == null) { map1 = new HashMap(); } if (map2 == null) { map2 = new HashMap(); } HashSet allKeys = new HashSet(); allKeys.addAll(map1.keySet()); allKeys.addAll(map2.keySet()); for (K key : allKeys) { V exp = map1.get(key); V act = map2.get(key); Diff d = Diff.check(key, act, exp); if (d != null) { result.add(d); } } 返回结果; }
  • 不要将更多信息放入 cmets。编辑您的问题,并在那里格式化代码......就像您格式化问题中的所有其他代码一样!
  • 谈论重写静态方法是没有意义的;只有虚方法可以被覆盖。

标签: java overloading


【解决方案1】:
public static <K, V> List<Diff<K, V>> MapComparison(Map<K, V> map1, Map<K, V> map2) {
    // ...
    V exp = map1.get(key);
    V act = map2.get(key);
    Diff<K, V> d = Diff.check(key, act, exp);
    // ...

调用站点在编译时绑定。编译器永远不会将这个Diff.check 调用绑定到新的重载,因为它不知道也不关心V 可能在运行时绑定到java.sql.Date。它只知道KV 是从Object 派生的一些类型,所以它绑定到它唯一可以绑定的方法:Diff&lt;K, V&gt; check(K, V, V)

【讨论】:

  • 你认为原来的那样,而不是 if (!exp.equals(act)) 我可以把 if !(exp.toString().equals(act.toString())? java.sql.Date 只会打印 yyyy-mm-dd。但它可能会因为其他数据类型而搞砸?
  • 我不会,因为默认的toString() 实现包括身份哈希码。没有规定两个等效对象也必须等于toString()。更重要的是,并没有规定由toString() 相等的对象实际上是等价的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-04
  • 2010-10-27
相关资源
最近更新 更多