代码之家  ›  专栏  ›  技术社区  ›  Julien Chastang

为什么java.lang.Number不能实现可比性?[副本]

  •  128
  • Julien Chastang  · 技术社区  · 17 年前

    java.lang.Number 不执行 Comparable ? 这意味着您无法排序 Number 和 Collections.sort 我觉得这有点奇怪。

    讨论后更新:

    谢谢你所有有用的回复。我最后做了一件事 some more research about this topic .

    对于java.lang.Number为什么不实现Compariable,最简单的解释是基于可变性的考虑。

    回顾一下, java.lang.Number 是抽象的超类型 AtomicInteger AtomicLong , BigDecimal , BigInteger , Byte Double , Float , Integer , Long Short . 在名单上, 原子整数 和 原子长 可比较的 .

    仔细研究后,我发现这不是一个好的实践 可比较的 原子长 和 原子整数 使生效 可比较的 因为它会限制未来子类型的实现。的确 原子长 和 原子整数 在Java 1.5中添加了 java.lang.Number 最初是实施的。

    除了可变性,这里可能还有其他考虑因素。A. compareTo 实施 数字 大十进制 因为它能够容纳所有的 数字 子类型。这一提升在数学和表现方面的含义对我来说有点不清楚,但我的直觉发现这个解决方案很难理解。

    12 回复  |  直到 16 年前
        1
  •  75
  •   cletus    17 年前

    值得一提的是,以下表达式:

    new Long(10).equals(new Integer(10))
    

    总是 false ,这往往会在某个时刻绊倒每个人。所以你不仅不能随意比较 Number 但是你甚至不能确定它们是否相等。

    而且,对于真正的基元类型( float , double ),确定两个值是否相等是一件棘手的事情,必须在可接受的误差范围内完成。尝试以下代码:

    double d1 = 1.0d;
    double d2 = 0.0d;
    for (int i=0; i<10; i++) {
      d2 += 0.1d;
    }
    System.out.println(d2 - d1);
    

    你会有一些小小的不同。

    那么回到制造问题上来 数字 Comparable doubleValue() 数字

    • Byte ;
    • Short ;
    • Integer ;
    • Long
    • AtomicInteger ;
    • AtomicLong ;
    • Float ;
    • Double
    • BigInteger ; 和
    • BigDecimal .

    compareTo() 方法,该方法不会退化为一系列if instanceof语句? 数字 实例只有六种方法可用:

    • byteValue() ;
    • shortValue() ;
    • intValue()
    • longValue() ;
    • floatValue()
    • doubleValue() .

    所以我猜孙做出了(合理的)决定 数字 可比较的 他们自己的例子。

        2
  •  46
  •   Andrew Case    11 年前

    有关答案,请参阅Java BugTrade bug 4414323 comp.lang.java.programmer

    引用Sun对2001年错误报告的回应:

    所有“数字”都不可比; 数字是可能的。这是不公平的 浮点数为true;楠 (非数字)不小于, 大于或等于任何 浮点值,甚至是它本身。 {Float,Double}。比较总数 订购与订购不同 浮点“<”和“=”的 仅可与其他实例进行比较 同级的。还有其他的 案例,比如复数,没有 存在标准总订单, 简称,不论是否为 可比较的数字应保留为 对该子类的决定。

        3
  •  5
  •   z -    17 年前

        4
  •  5
  •   Jaime Saiz    14 年前

    要尝试解决原始问题(对数字列表进行排序),一个选项是声明泛型类型的列表,扩展数字并实现可比较。

    比如:

    <N extends Number & Comparable<N>> void processNumbers(List<N> numbers) {
        System.out.println("Unsorted: " + numbers);
        Collections.sort(numbers);
        System.out.println("  Sorted: " + numbers);
        // ...
    }
    
    void processIntegers() {
        processNumbers(Arrays.asList(7, 2, 5));
    }
    
    void processDoubles() {
        processNumbers(Arrays.asList(7.1, 2.4, 5.2));
    }
    
        5
  •  3
  •   Pete Kirkham    17 年前

    相反,Number的非原子子类实现了compariable本身。

        6
  •  3
  •   cchabanois    16 年前

    你可以用 Transmorph 使用其NumberComparator类比较数字。

    NumberComparator numberComparator = new NumberComparator();
    assertTrue(numberComparator.compare(12, 24) < 0);
    assertTrue(numberComparator.compare((byte) 12, (long) 24) < 0);
    assertTrue(numberComparator.compare((byte) 12, 24.0) < 0);
    assertTrue(numberComparator.compare(25.0, 24.0) > 0);
    assertTrue(numberComparator.compare((double) 25.0, (float) 24.0) > 0);
    assertTrue(numberComparator.compare(new BigDecimal(25.0), (float) 24.0) > 0);
    
        7
  •  2
  •   Hilmar    16 年前

    编写自己的比较器

    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.atomic.AtomicLong;
    
    public class NumberComparator implements Comparator {
        @SuppressWarnings("unchecked")
        @Override
        public int compare(Number number1, Number number2) {
     if (((Object) number2).getClass().equals(((Object) number1).getClass())) {
         // both numbers are instances of the same type!
         if (number1 instanceof Comparable) {
      // and they implement the Comparable interface
      return ((Comparable) number1).compareTo(number2);
         }
     }
     // for all different Number types, let's check there double values
     if (number1.doubleValue() < number2.doubleValue())
         return -1;
     if (number1.doubleValue() > number2.doubleValue())
         return 1;
     return 0;
        }
    
        /**
         * DEMO: How to compare apples and oranges.
         */
        public static void main(String[] args) {
     ArrayList listToSort = new ArrayList();
     listToSort.add(new Long(10));
     listToSort.add(new Integer(1));
     listToSort.add(new Short((short) 14));
     listToSort.add(new Byte((byte) 10));
     listToSort.add(new Long(9));
     listToSort.add(new AtomicLong(2));
     listToSort.add(new Double(9.5));
     listToSort.add(new Double(9.0));
     listToSort.add(new Double(8.5));
     listToSort.add(new AtomicInteger(2));
     listToSort.add(new Long(11));
     listToSort.add(new Float(9));
     listToSort.add(new BigDecimal(3));
     listToSort.add(new BigInteger("12"));
     listToSort.add(new Long(8));
     System.out.println("unsorted: " + listToSort);
     Collections.sort(listToSort, new NumberComparator());
     System.out.println("sorted:   " + listToSort);
     System.out.print("Classes:  ");
     for (Number number : listToSort) {
         System.out.print(number.getClass().getSimpleName() + ", ");
     }
        }
    }
    
        8
  •  1
  •   Peter Lawrey    17 年前

    但是,您可以编写自己的比较器,并使用它创建树映射<编号,对象>,TreeSet<数量>或集合。排序(List<Number>,Comparator)或数组。排序(Number[],Comparator);

        9
  •  1
  •   Nat    9 年前

    为什么这会是个坏主意? :

    abstract class ImmutableNumber extends Number implements Comparable {
        // do NOT implement compareTo method; allowed because class is abstract
    }
    class Integer extends ImmutableNumber {
        // implement compareTo here
    }
    class Long extends ImmutableNumber {
        // implement compareTo here
    }
    

    另一个选项可能是声明类编号实现Comparable,省略compareTo实现,并在某些类(如Integer)中实现它,而在其他类(如AtomicInteger)中抛出UnsupportedException。

        10
  •  0
  •   Steve Kuo    17 年前

        11
  •  0
  •   airportyh    17 年前

    查看类层次结构。像Long、Integer等包装类实现了Comparable,即整数与整数可比,Long与Long可比,但不能混合使用。至少在这个泛型范例中是这样。我想这回答了你的问题“为什么”。

        12
  •  0
  •   Alexey Ivanov    14 年前

    byte (原始)是一个 int

    int i = 255
    
    // down cast primitive
    (byte) i == -1
    

    A. Byte Integer . 字节 是一个 Number 和 整数 . 数字

    Integer iObject = new Integer(255);
    System.out.println(iObject.intValue());   // 255
    System.out.println(iObject.byteValue());  // -1
    

    字节 是一个 整数 是一个 ,您将在中使用哪一个值 compareTo(Number number1, Number number2) 方法

    推荐文章