首页 > 解决方案 > java比较器是类型感知的吗?

问题描述

我想要一种基于任何给定 Comparable 类创建 Comparator 对象的简单方法,因此我编写了 ComparatorCreator 对象,我相信它会查看其泛型的类型并返回我可以用来比较对象的正确 Comparator 对象类型。所以我写了下面的代码来测试我的想法。我的信念是,由于 BackwardsInt 类的 compareto 方法是一个反向比较器,它应该能够以相反的顺序比较任何两个数字。但是在执行语句时,它在比较两个整数时完全忽略了反转,甚至抛出了错误。我想知道为什么会这样。我创建的比较器似乎知道我在其参数中传递的数字的类型。

(不久前我也很喜欢有界通配符,所以如果这导致了问题,那么糟糕)。

import java.util.Comparator;

public class what {
    public static void main(String[] ignoreme)
    {
        Comparator comp = new ComparatorCreator<BackwardsInt>().getComparator();
        //comp should represent a Comparator<Number> which redirects to BackwardsInt.compareTo
        int big=6;
        int small=2;
        BackwardsInt bbig=new BackwardsInt(6);
        BackwardsInt bsmall=new BackwardsInt(2);

        System.out.println(comp.compare(bbig, bsmall));//prints -1 good
        System.out.println(comp.compare(bbig, small));//prints -1 good
        System.out.println(comp.compare(big, small));//prints 1 why?
        System.out.println(comp.compare(big, bsmall));//throws error?!?
    }
    private static class ComparatorCreator<T extends Comparable<? super T>>{
        public Comparator<? extends T> getComparator()
        {
            return T::compareTo;
        }
    }
    private static class BackwardsInt extends Number implements Comparable<Number>{
        private int val;
        public BackwardsInt(int v)
        {
            val=v;
        }
        @Override
        public int compareTo(Number o) {
            double d = o.doubleValue()-val;
            if(d>0)
                return 1;
            if(d<0)
                return -1;
            return 0;
        }

        public int intValue() {
            return val;
        }

        public long longValue() {
            return val;
        }

        public float floatValue() {
            return val;
        }

        public double doubleValue() {
            return val;
        }
    }
}

标签: javatypes

解决方案


让我们看看你的ComponentCreator

private static class ComparatorCreator<T extends Comparable<? super T>>{
    public Comparator<? extends T> getComparator()
    {
        return T::compareTo;
    }
}

如果稍作更改以使您的错误更清楚

private static class ComparatorCreator<T extends Comparable<? super T>>{
    public Comparator<? extends T> getComparator()
    {
        return (o1, o2) -> {
            return o1.compareTo(o2);
        };
    }
}

您使用的方法参考与我拥有的 lambda 相同,但它使错误更加明显。如果我们一一检查您的样品,我们可以看到以下内容:

comp.compare(bbig, bsmall); // calls bbig.compareTo(bsmall)
comp.compare(bbig, small); // calls bbig.compareTo(small)
comp.compare(big, small); // calls big.compareTo(small)
comp.compare(big, bsmall); // calls big.compareTo(bsmal)

您收到的输出是有意义的,因为big.compareTo()将调用该类的compareTo()函数Integer


推荐阅读