Java中以接口为类型创建对象的作用及ArrayList两种创建方式差异解析
两种ArrayList创建方式的区别与使用场景
核心区别
两种写法的本质是变量声明的类型不同:
- 方式1:
ArrayList<Integer> myArrayList = new ArrayList<>();
变量myArrayList的类型是具体实现类ArrayList,它既可以调用List接口定义的通用方法(如add()、get()),也能直接调用ArrayList特有的方法(比如trimToSize()、ensureCapacity())。但后续不能把这个变量赋值为其他List实现类(比如LinkedList)的对象,编译会报错。 - 方式2:
List<Integer> myArrayList = new ArrayList<>();
变量myArrayList的类型是List接口,它只能调用List接口中定义的方法,无法直接使用ArrayList的独有方法。但好处是后续可以轻松切换成任意List的实现类,比如LinkedList、Vector,代码无需大量修改。
为什么优先用List接口作为类型?
这是面向接口编程的核心思路,核心优势是解耦具体实现,提升代码灵活性和可维护性,结合示例看更清楚:
示例1:实现类切换的灵活性
// 方式2:用List声明 List<Integer> nums = new ArrayList<>(); nums.add(1); nums.add(2); // 业务需求变化,需要换成LinkedList(比如频繁增删头部元素的场景) nums = new LinkedList<>(); // 后续调用add、get等方法的代码完全不用改 nums.add(3); System.out.println(nums.get(0));
如果用方式1声明:
// 方式1:用ArrayList声明 ArrayList<Integer> nums = new ArrayList<>(); nums.add(1); // 这里尝试赋值LinkedList会直接编译报错,必须修改变量类型才能切换 // nums = new LinkedList<>(); // 编译错误
示例2:方法参数的通用性
假设写一个打印列表的方法,用List作为参数类型:
public static void printNumbers(List<Integer> list) { for (int num : list) { System.out.println(num); } } // 调用时,ArrayList和LinkedList都能传 ArrayList<Integer> arrayList = new ArrayList<>(List.of(1,2,3)); LinkedList<Integer> linkedList = new LinkedList<>(List.of(4,5,6)); printNumbers(arrayList); printNumbers(linkedList);
如果方法参数用ArrayList:
public static void printNumbers(ArrayList<Integer> list) { for (int num : list) { System.out.println(num); } } // 这里传LinkedList会编译报错,方法只能处理ArrayList,通用性极差 // printNumbers(linkedList); // 编译错误
什么时候用方式1?
只有当你明确需要使用ArrayList特有的方法时,才适合直接声明为ArrayList类型。比如需要手动调整底层数组容量:
ArrayList<Integer> nums = new ArrayList<>(); nums.ensureCapacity(100); // 提前扩容,避免频繁自动扩容 nums.trimToSize(); // 缩小容量到实际元素数,节省内存
内容的提问来源于stack exchange,提问作者adhi
相关产品推荐
相关产品推荐

