为什么我们在使用时会丢失类型安全性List
而不是在使用时List<Object>
?他们基本上不一样吗?
编辑:我发现以下给出了编译错误
public class TestClass
{
static void func(List<Object> o, Object s){
o.add(s);
}
public static void main(String[] args){
func(new ArrayList<String>(), new Integer(1));
}
}
Run Code Online (Sandbox Code Playgroud)
而事实并非如此
public class TestClass
{
static void func(List o, Object s){
o.add(s);
}
public static void main(String[] args){
func(new ArrayList<String>(), new Integer(1));
}
}
Run Code Online (Sandbox Code Playgroud)
为什么?
为什么我们在使用时会丢失类型安全性
List
而不是在使用时List<Object>
?他们基本上不一样吗?
不,他们不是一回事.
如果您要提供API,
class API {
static List<Object> getList() { ... }
static void modifyList(List<Object> l) { ... }
}
Run Code Online (Sandbox Code Playgroud)
并且客户使用它不正确
List<Integer> list = API.getList();
API.modifyList(list);
for (Integer i : list) { ... } // Invalid
Run Code Online (Sandbox Code Playgroud)
那么当你的API指定List<Object>
他们得到一个编译时错误,但他们没有当API.getList()
回报List
,并API.modifyList(list)
采取List
不泛型类型参数.
编辑:
在评论中你提到了改变
void func(List<Object> s, Object c) { s.add(c); }
Run Code Online (Sandbox Code Playgroud)
至
void func(List s, Object c) { s.add(c); }
Run Code Online (Sandbox Code Playgroud)
以便
func(new List<String>(), "");
Run Code Online (Sandbox Code Playgroud)
会工作.
这违反了类型安全.这种类型安全的方法是
<T> void func(List<? super T> s, T c) { s.add(c); }
Run Code Online (Sandbox Code Playgroud)
这基本上说func
是一个参数化函数,它List
的类型可以是T的任何超类,类型为T的值,并将值添加到列表中.
List
是您不知道的某种类型的列表.它可能是一个List<String>
,List<Integer>
等等.
它实际上等同于List<?>
,或者List<? extends Object>
,除了它没有记录这个事实.它仅支持向后兼容性.
List<Object>
是一个对象列表.任何类型的任何对象都可以放在其中,例如,它只接受字符串.List<String>
所以不,他们不是一回事.