首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >区分等价DataTypes

区分等价DataTypes
EN

Stack Overflow用户
提问于 2011-09-11 03:55:47
回答 5查看 79关注 0票数 0

在Java语言中,假设我有一个方法,它接受两个整数列表,并根据第二个列表返回第一个列表中的整数的arrayList。

代码语言:javascript
复制
public ArrayList<Integer> func(ArrayList<Integer> A, ArrayList<Integer> B){
   ArrayList result = new ArrayList();

   //A and B have the same length
   for(int index = 0; index < A.length();index++){

      //Decide if a gets added to result based on the corresponding B
      if(decisionFunction(B.get(i)){
          result.add(a.get(i));
      }
   }

 return result;
}

现在假设我做了一些愚蠢的事情,比如将插入更改为

代码语言:javascript
复制
        result.add(b.get(i));

如果我能做点什么就好了

代码语言:javascript
复制
public ArrayList<AInteger> func(ArrayList<AInteger> A, ArrayList<BInteger> B)

为了确保不考虑睡眠剥夺,编译器将防止我犯这种类型的错误。现在我们可以试着

代码语言:javascript
复制
class AInteger extends Integer{}; class BInteger extends BInteger{};

方法调用该方法。

代码语言:javascript
复制
func((ArrayList<AInteger>) A, (ArrayList<BInteger>) B);

不幸的是,向下转换将引发运行时异常。因此,这个解决方案需要我(我认为)将A和B重新构建为具有适当数据类型的新列表,这是很昂贵的。除了更加小心和使用单元测试之外,有没有办法让编译器区分这两个列表呢?

其他语言,如Scala或Haskell,是否提供了允许我在不复制的情况下安全地重新转换的功能?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-09-11 13:17:20

通过使用泛型,可以通过将函数声明修改为

代码语言:javascript
复制
public <IntegerA extends Integer, IntegerB extends Integer>
   List<IntegerA> func(List<IntegerA> A, List<IntegerB> B){
       ArrayList result = new ArrayList();

       //A and B have the same length
       for(int index = 0; index < A.length();index++){

           //Decide if a gets added to result based on the corresponding B
           if(decisionFunction(B.get(i)){
               result.add(A.get(i));
           }
       }

       return result;
}

这确保了result.add(B.get(i))会根据需要引发类型错误。

不幸的是。不允许使用新的IntegerA(int),这会阻止创建新的对象。因此,得到的导出列表只能包含原始列表中的元素(除非执行了向下转换,这会使任何类型保证无效)。

票数 0
EN

Stack Overflow用户

发布于 2011-09-11 04:15:56

你的问题不容易,试着这样做:

接收两个对象类型不同的列表(列表项类型),但是它们对您来说是“等效的”,并且在Java中是可转换的,并且返回的列表包含您希望从其中获取项的类型,从而避免了从另一个列表中获取项。

例如,use public ArrayList<Integer> func(ArrayList<Integer> A, ArrayList<Number> B) this阻止您将项从B复制到返回列表,因为您需要显式执行向下转换。如果您想要整数和/或B项实际上是整数,您仍然可以通过调用Number.intValue()将B项计算为数字。如果B真的被定义为ArrayList<Integer>,那么问题出在调用上,因为您需要使用泛型执行显式强制转换,这会引发一个警告,从而避免将@SupressWarning放在方法定义中。

另一个问题是Type Erasure,它在运行时阻止泛型类型检查,因为在Java语言中编译时泛型类型会被“擦除”。.Net中的C#没有类型擦除,并在运行时保证集合的类型(例如)。

票数 1
EN

Stack Overflow用户

发布于 2011-09-11 04:36:31

实际上,C++有一个叫做私有继承的特性。它与类一起工作,使得父对象的所有功能都是继承的,但用户不能将其视为公共父对象。不幸的是,这不适用于原语。

Java不支持这样的特性。大多数语言都不支持这种直接的“语义区分”。请记住,为两个类生成的代码应该是相等的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7374254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档