如何修改类中泛型属性的属性?解决Rocket<?> set方法调用报错
问题原因分析
你遇到的编译错误是因为通配符?的类型限制:当Player中的Rocket属性声明为Rocket<?>时,编译器将其视为「某种未知类型的Rocket实例」。调用set方法时,参数必须严格匹配这个未知类型,但你传入的ArrayList<String>编译器无法确认是否和该未知类型兼容,因此直接抛出错误——这是Java泛型的类型安全机制在起作用,避免你把错误类型的数据写入Rocket。
简单来说:Rocket<?>是只读的(仅能写入null),因为编译器不知道它实际持有的类型是什么,不敢允许你随便写入其他类型。
解决方案
根据你的需求(Player需要持有不同类型的Rocket,且能修改Rocket的内容),这里提供两种可行方案:
方案1:给Player添加泛型参数(推荐)
让Player类成为泛型类,分别指定左右Rocket的类型,既保留灵活性,又能让编译器明确类型信息,支持安全的写入操作。
修改后的Player类:
package dchapter11_1; public class Player<L, R> { public String name; public Rocket<L> leftRocket; public Rocket<R> rightRocket; public Player(String name, Rocket<L> leftRocket, Rocket<R> rightRocket) { this.name = name; this.leftRocket = leftRocket; this.rightRocket = rightRocket; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Rocket<R> getRightRocket() { return rightRocket; } public void setRightRocket(Rocket<R> rightRocket) { this.rightRocket = rightRocket; } public Rocket<L> getLeftRocket() { return leftRocket; } public void setLeftRocket(Rocket<L> leftRocket) { this.leftRocket = leftRocket; } @Override public String toString() { return getClass() + "[name=" + name + ", rightRocket=" + rightRocket.toString() + ", leftRocket=" + leftRocket.toString() + "]"; } }
修改Main类中的实例化代码,指定泛型类型:
package dchapter11_1; import java.util.ArrayList; public class Main { public static void main(String... args) { Player<Integer, ArrayList<String>> kleinerB = new Player<>( "kleinerK", new Rocket<>(42), new Rocket<>(new ArrayList<String>(){{add("BU"); add("BU"); add("BU");}}) ); System.out.println(kleinerB.toString()); ArrayList<String> arrayList = kleinerB.getRightRocket().get(); for(String s : arrayList) { System.out.print(s); } // 现在可以正常调用set方法了 kleinerB.getRightRocket().set(new ArrayList<String>()); } }
这种方式既支持Player持有不同类型的Rocket,又能安全调用set方法,还消除了原代码中的unchecked警告。
方案2:显式类型转换(不推荐,有风险)
如果不想修改Player类的结构,可以通过强制类型转换绕过编译器检查,但这会产生unchecked警告,且如果Rocket实际类型不匹配,运行时会抛出ClassCastException。
修改Main中的代码:
// 强制转换为具体类型的Rocket @SuppressWarnings("unchecked") Rocket<ArrayList<String>> rightRocket = (Rocket<ArrayList<String>>) kleinerB.getRightRocket(); rightRocket.set(new ArrayList<String>());
该方法仅适合你能100%确定Rocket实际类型的场景,否则存在运行时崩溃风险。
关键知识点回顾
- 通配符
?用于表示未知类型,适合只读场景(比如仅调用get方法),不支持写入操作(除null外)。 - 泛型类的参数化可以明确类型信息,在保证类型安全的同时支持读写操作。
内容的提问来源于stack exchange,提问作者Tired8296
相关产品推荐
相关产品推荐

