如何在不知道类型的情况下比较两个对象
How to compare two objects without knowing their type
我正在实现一个排序列表 class,在这个 class 中,我将对任何类型的对象进行排序,所以现在我想测试该对象是否具有可比性,
我用这段代码覆盖了 compareTo() 方法:-
class MyObject implements Comparable {
Object ob;
MyObject(){
this.ob=new Object();
}
public int compareTo(Object current){
if((ob.toString().compareTo(current.toString()))>1)
return 1;
else if((ob.toString().compareTo(current.toString()))<1)
return -1;
else
return 0;
}
public String toString(){
return (String)ob;
}
}
所以现在我需要像这样为这些对象分配编号
class SortedListTest{
public static void main (String arg[]){
MyObject b1= new MyObject();
MyObject b2= new MyObject();
b1.ob=6;
b2.ob=3;
System.out.println(b2.compareTo(b1));
}
}
但它一直给我这个例外:-
Exception in thread "main" java.lang.ClassCastException:
java.lang.Integer cannot be cast to java.lang.String
从概念上讲,这根本没有意义!
要点是:当您允许在列表中使用任意类型的对象时,"sorting" 的概念在这里 而不是 有意义。
因此简短的回答是:算了吧。
从技术上讲,您的问题在这里:
return (String)ob;
该代码假定obj 是一个字符串。但是当你允许 any 类型的对象时,这不一定是正确的。所以 obj.toString()
可以防止运行时问题,但是;如前所述:解决该技术问题并不是真正的答案。
让我们回到现实世界的例子:假设您被要求对 table 上的东西进行分类:勺子、刀、杯子、香蕉、苹果。你打算怎么做?
如果有的话,您可以撤回一些共同点;例如 "weight"。所以你把所有的东西都放在一个秤上;并将其用于 "sort" 他们。
从 Java 的角度来看,对象的 唯一 的共同点是字符串表示(在对它们调用 toString()
时)或数值(调用 hashCode()
时)。因此,您可以 "sort" 在这些属性上。哪个可行,但不会产生任何有用的东西。
换句话说:当您打算 排序 列表的内容时,除了允许列表中的 "same kind of objects" 之外别无他法。这就是 java 集合以这种方式工作的原因。在某种意义上:一个人使用泛型来表达 List<T>
包含具有某些 common 类型的对象。从概念的角度来看,这只是意味着:不是允许 任何东西 进入特定列表,而是只允许 "have something in common" 的对象。
您报告的问题是
return (String)ob;
应该是
return ob.toString();
如果 ob
永远不会为空;或
return Objects.toString(ob);
如果可能的话。
但请注意,将对象包装在对象中以比较其 toString()
并不是必需的。你可以简单地使用一个 Comparator<Object>
,就像 Guava 的 Ordering.usingToString()
:
int order = Ordering.usingToString().compare(someObject, someOtherObject);
或 Java 8 等价物。我想应该是这样的:
Comparator<Object> usingToString = (a, b) -> a.toString().compareTo(b.toString());
int order = usingToString(someObject, someOtherObject);
在Java中,int是原始类型。原始类型没有方法。所以当你这样做的时候。
b1.ob = 6;
b2.ob = 3;
您正在将一个整数放入 MyObject
class 的 ob
变量中。在 compareTo(Object current)
方法中,您调用 ob
上的 toString()
方法。因为你给了 ob
一个整数,你不能调用它的任何方法;
在不知道对象类型的情况下对对象进行排序在许多情况下没有意义。但是,在某些情况下,您可能希望按类型等对对象进行分组(尽管像地图等不同类型的存储可能更适合这种情况)。
问题在于,如果不知道对象的类型,您的操作就会受到限制。您的比较器可以执行以下操作:
- 检查正在比较的对象是否实现
Comparable
并调用其中一个的 compareTo()
方法。
- 如果它们相同 type/class 那么它们可能相等也可能不相等(取决于您的要求)。如何比较取决于你。
- 如果类型不同,您可以尝试通过 class 名称等进行比较。
也就是说你应该真的想想你是否真的需要它,因为你可以依赖的信息很少上。
我正在实现一个排序列表 class,在这个 class 中,我将对任何类型的对象进行排序,所以现在我想测试该对象是否具有可比性,
我用这段代码覆盖了 compareTo() 方法:-
class MyObject implements Comparable {
Object ob;
MyObject(){
this.ob=new Object();
}
public int compareTo(Object current){
if((ob.toString().compareTo(current.toString()))>1)
return 1;
else if((ob.toString().compareTo(current.toString()))<1)
return -1;
else
return 0;
}
public String toString(){
return (String)ob;
}
}
所以现在我需要像这样为这些对象分配编号
class SortedListTest{
public static void main (String arg[]){
MyObject b1= new MyObject();
MyObject b2= new MyObject();
b1.ob=6;
b2.ob=3;
System.out.println(b2.compareTo(b1));
}
}
但它一直给我这个例外:-
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
从概念上讲,这根本没有意义!
要点是:当您允许在列表中使用任意类型的对象时,"sorting" 的概念在这里 而不是 有意义。
因此简短的回答是:算了吧。
从技术上讲,您的问题在这里:
return (String)ob;
该代码假定obj 是一个字符串。但是当你允许 any 类型的对象时,这不一定是正确的。所以 obj.toString()
可以防止运行时问题,但是;如前所述:解决该技术问题并不是真正的答案。
让我们回到现实世界的例子:假设您被要求对 table 上的东西进行分类:勺子、刀、杯子、香蕉、苹果。你打算怎么做?
如果有的话,您可以撤回一些共同点;例如 "weight"。所以你把所有的东西都放在一个秤上;并将其用于 "sort" 他们。
从 Java 的角度来看,对象的 唯一 的共同点是字符串表示(在对它们调用 toString()
时)或数值(调用 hashCode()
时)。因此,您可以 "sort" 在这些属性上。哪个可行,但不会产生任何有用的东西。
换句话说:当您打算 排序 列表的内容时,除了允许列表中的 "same kind of objects" 之外别无他法。这就是 java 集合以这种方式工作的原因。在某种意义上:一个人使用泛型来表达 List<T>
包含具有某些 common 类型的对象。从概念的角度来看,这只是意味着:不是允许 任何东西 进入特定列表,而是只允许 "have something in common" 的对象。
您报告的问题是
return (String)ob;
应该是
return ob.toString();
如果 ob
永远不会为空;或
return Objects.toString(ob);
如果可能的话。
但请注意,将对象包装在对象中以比较其 toString()
并不是必需的。你可以简单地使用一个 Comparator<Object>
,就像 Guava 的 Ordering.usingToString()
:
int order = Ordering.usingToString().compare(someObject, someOtherObject);
或 Java 8 等价物。我想应该是这样的:
Comparator<Object> usingToString = (a, b) -> a.toString().compareTo(b.toString());
int order = usingToString(someObject, someOtherObject);
在Java中,int是原始类型。原始类型没有方法。所以当你这样做的时候。
b1.ob = 6;
b2.ob = 3;
您正在将一个整数放入 MyObject
class 的 ob
变量中。在 compareTo(Object current)
方法中,您调用 ob
上的 toString()
方法。因为你给了 ob
一个整数,你不能调用它的任何方法;
在不知道对象类型的情况下对对象进行排序在许多情况下没有意义。但是,在某些情况下,您可能希望按类型等对对象进行分组(尽管像地图等不同类型的存储可能更适合这种情况)。
问题在于,如果不知道对象的类型,您的操作就会受到限制。您的比较器可以执行以下操作:
- 检查正在比较的对象是否实现
Comparable
并调用其中一个的compareTo()
方法。 - 如果它们相同 type/class 那么它们可能相等也可能不相等(取决于您的要求)。如何比较取决于你。
- 如果类型不同,您可以尝试通过 class 名称等进行比较。
也就是说你应该真的想想你是否真的需要它,因为你可以依赖的信息很少上。