Java 我能避免这种情况下的T型铸造吗?

Java 我能避免这种情况下的T型铸造吗?,java,generics,casting,Java,Generics,Casting,我有一个具有以下结构的函数: public class TestOrder { enum Status { CANCELLED, EXECUTED } static class Data { Status status; } private <T extends Order> void process(List<Data> dataList, List&

我有一个具有以下结构的函数:

public class TestOrder {

    enum Status {
        CANCELLED,
        EXECUTED
    }
    
    static class Data {
        Status status;        
    }

    private  <T extends Order> void process(List<Data> dataList, List<T> currentUpdates) {
    List<T> orders = new ArrayList<>();
    for(Data d: dataList) {
        Order order = createOrder(d);
        if(order != null) {
            orders.add((T) order); // <- warning "Unchecked cast Order to T
        }
    }

    // processing
    currentUpdates.clear();
    currentUpdates.addAll(orders);
}

    private Order createOrder(Data data) {
        if(data.status == Status.EXECUTED) {
            // processing
            return new ExecutedOrder();  // implements of Order
        }
        if(data.status == Status.CANCELLED) {
            // processing
            return new CancelledOrder();  // implements of Order
        }

        return null;
    }
}



public interface Order {
}

public class CancelledOrder implements Order {
}

public class ExecutedOrder implements Order {
}

好吧,如果对象总是顺序的子类型,我看不出在可以有列表的时候,首先需要有列表


通过使用Order createOrder方法,您正在丢失有关类型的信息,然后您希望它返回。如果没有特定的要求,这种方法就毫无意义。

好吧,如果对象始终是顺序的子类型,那么我看不出当您可以拥有列表时,首先需要列表


通过使用Order createOrder方法,您正在丢失有关类型的信息,然后您希望它返回。如果没有特定的要求,这种方法是没有意义的。

当代码处于当前形式时,没有办法避免警告。考虑这个简化的场景:

public static void main(String[] args) {
    
    List<ExecutedOrder> executedOrders = new ArrayList<>();
    process(executedOrders);
    
    ExecutedOrder executedOrder = executedOrders.get(0);
}

private static <T extends Order> void process(List<T> currentUpdates) {
    
    currentUpdates.add((T) createOrder());
}

private static Order createOrder() {

    return new CancelledOrder();
}
在这里,当访问列表中的元素时将抛出ClassCastException。因此,编译器之所以告诉您强制转换是不安全的,是因为它是不安全的

尽管您在注释中提到,您的数据参数将保证向列表中添加正确的顺序,但编译器无法验证这一点。这不一定是个问题,不安全的强制转换存在于很多地方,但是你必须意识到你所做的根本上是不安全的


我认为这是最好的选择,因此可能值得重新思考类似的方法。

当代码处于当前形式时,没有办法避免警告。考虑这个简化的场景:

public static void main(String[] args) {
    
    List<ExecutedOrder> executedOrders = new ArrayList<>();
    process(executedOrders);
    
    ExecutedOrder executedOrder = executedOrders.get(0);
}

private static <T extends Order> void process(List<T> currentUpdates) {
    
    currentUpdates.add((T) createOrder());
}

private static Order createOrder() {

    return new CancelledOrder();
}
在这里,当访问列表中的元素时将抛出ClassCastException。因此,编译器之所以告诉您强制转换是不安全的,是因为它是不安全的

尽管您在注释中提到,您的数据参数将保证向列表中添加正确的顺序,但编译器无法验证这一点。这不一定是个问题,不安全的强制转换存在于很多地方,但是你必须意识到你所做的根本上是不安全的


我认为这是最好的选择,因此可能值得重新思考您的类似方法。

基于示例代码很难提供理想的解决方案,但考虑到您提供的内容,重构数据和状态以了解类型可能是值得的:

public class TestOrder {

    static abstract class Status<T extends Order> {
        public static final Status<CancelledOrder> CANCELLED = new Status<>() {
            @Override
            public CancelledOrder createOrder() {
                return new CancelledOrder();
            }
        };

        public static final Status<ExecutedOrder> EXECUTED = new Status<>() {
            @Override
            public ExecutedOrder createOrder() {
                return new ExecutedOrder();
            }
        };

        public abstract T createOrder();
    }
    
    static class Data<T extends Order> {
        Status<T> status;        
    }

    private <T extends Order> void process(List<Data<T>> dataList, List<T> currentUpdates) {
        List<T> orders = new ArrayList<>();
        for(Data d: dataList) {
            T order = d.status.createOrder();
            if(order != null) {
                orders.add(order);
            }
        }
    
        // processing
        currentUpdates.clear();
        currentUpdates.addAll(orders);
    }

}

基于示例代码很难提供理想的解决方案,但鉴于您所提供的,重构数据和状态以了解类型可能是值得的:

public class TestOrder {

    static abstract class Status<T extends Order> {
        public static final Status<CancelledOrder> CANCELLED = new Status<>() {
            @Override
            public CancelledOrder createOrder() {
                return new CancelledOrder();
            }
        };

        public static final Status<ExecutedOrder> EXECUTED = new Status<>() {
            @Override
            public ExecutedOrder createOrder() {
                return new ExecutedOrder();
            }
        };

        public abstract T createOrder();
    }
    
    static class Data<T extends Order> {
        Status<T> status;        
    }

    private <T extends Order> void process(List<Data<T>> dataList, List<T> currentUpdates) {
        List<T> orders = new ArrayList<>();
        for(Data d: dataList) {
            T order = d.status.createOrder();
            if(order != null) {
                orders.add(order);
            }
        }
    
        // processing
        currentUpdates.clear();
        currentUpdates.addAll(orders);
    }

}

除其他答案外,如果您希望逃离演员阵容:

private <T extends Order> void process(
  List<Data> dataList,  
  Class<T> orderType,
  List<T> currentUpdates
) {
 List<T> orders = new ArrayList<>();
 for (Data d: dataList) {
   T order = orderType.cast(createOrder(d)); // check are no longer required
   if (order != null) {
     orders.add(order); 
   }
}

你也许应该首先了解你为什么要使用一个或多个列表。

除了其他答案,如果你想逃离演员阵容:

private <T extends Order> void process(
  List<Data> dataList,  
  Class<T> orderType,
  List<T> currentUpdates
) {
 List<T> orders = new ArrayList<>();
 for (Data d: dataList) {
   T order = orderType.cast(createOrder(d)); // check are no longer required
   if (order != null) {
     orders.add(order); 
   }
}

你也许应该首先明白为什么你要使用一个或多个列表。

你能用一些编译过的代码编辑你的问题吗?@Eugene:说清楚一点,代码现在编译好了,可以工作了。我只是想知道IDE中的警告是否可以避免。除非我误解了你的意思,但我还是理解这个问题。您的强制转换是一个实例的向上转换,该实例肯定是一个T,因此您可以抑制该警告。在我看来,演员阵容是安全的。唯一的问题是,你为什么需要…@HenryTwist right,现在看到了你的答案,以一种使评论过时的方式澄清了这一点。你能用一些编译过的代码编辑你的问题吗?@Eugene:说得清楚,代码现在编译好了,可以工作了。我只是想知道IDE中的警告是否可以避免。除非我误解了你的意思,但我还是理解这个问题。您的强制转换是一个实例的向上转换,该实例肯定是一个T,因此您可以抑制该警告。在我看来,演员阵容是安全的。唯一的问题是,你为什么需要…@HenryTwist right,现在看到了你的答案,在某种程度上澄清了这一点,使评论过时。我更新了帖子。你是对的。我遗漏了一个重要方面。我正在传递一个集合,该集合属于我更新文章的方法中更新的任何子类型。你是对的。我遗漏了一个重要方面。我正在传递一个集合,它是在Method中更新的任何子类型的集合哦,这很可爱!哦,真可爱!