Java中List接口变量可引用ArrayList对象,体现多态——父接口引用指向子类对象,提升灵活性与可扩展性;仅能调用List定义的方法,需转型才可用ArrayList特有方法。

在Java中,将 ArrayList 赋值给 List 接口变量,是多态最典型、最常用的体现之一——它利用了“父接口引用指向子类对象”的机制,既保证了代码灵活性,又符合面向接口编程的设计原则。
为什么能这样赋值?
List 是接口,ArrayList 是它的具体实现类。Java允许用接口类型声明变量,并用其实现类的对象来初始化,这是多态的基础语法支持。编译器只检查接口定义的方法是否可用,运行时才决定调用哪个实现。
- 合法写法:
List<string> list = new ArrayList();</string> - 不合法写法:
ArrayList<string> list = new List();</string>(接口不能实例化) - 注意:右侧的
new ArrayList()可以省略泛型(钻石操作符),但左侧接口声明必须带泛型以保障类型安全
实际开发中怎么用?
这种写法不是为了“炫技”,而是为了解耦和扩展。比如方法参数、返回值、字段声明都优先使用 List,而不是具体实现类。
- 作为方法参数:
public void process(List<integer> data) { ... }</integer>,调用时可传ArrayList、LinkedList、甚至Collections.unmodifiableList(...) - 作为返回值:
public List<user> findAll() { return new ArrayList(users); }</user>,调用方无需关心内部用的是哪种List - 作为成员变量:
private List<task> tasks = new ArrayList();</task>,后续若想换成线程安全的CopyOnWriteArrayList,只需改右侧,其他代码几乎不动
需要注意什么?
虽然赋值本身简单,但多态下容易踩坑,关键在于“能调用什么方法”和“能否向下转型”。
立即学习“Java免费学习笔记(深入)”;
- 只能调用
List接口中声明的方法(如add()、get()、size()),不能直接调用ArrayList特有方法(如ensureCapacity()、trimToSize()) - 如果真需要
ArrayList特性,可显式转型:ArrayList<string> al = (ArrayList<string>) list;</string></string>,但务必先用instanceof判断,否则可能抛ClassCastException - 推荐用
Objects.requireNonNull(list)做空校验,避免因传入null或不可变List导致运行时异常
进阶建议:配合 Collections 工具类使用
多态优势在结合工具类时更明显。例如:
-
List<string> unmodifiable = Collections.unmodifiableList(new ArrayList(Arrays.asList("a","b")))</string>—— 同样是List类型,但行为完全不同(不可修改) -
List<integer> synchronizedList = Collections.synchronizedList(new ArrayList())</integer>—— 线程安全包装,对外仍是List接口 - 这些都不影响上层代码逻辑,只要它只依赖
List的契约


















