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中更新的任何子类型的集合哦,这很可爱!哦,真可爱!