java所有参数传递都是值传递,接口参数也不例外:传递的是对象引用的副本,而非对象本身或接口定义;方法内可修改对象状态,但重新赋值形参不影响原引用。

这是引用传递,但更准确地说:Java中所有参数传递都是值传递,接口参数也不例外。
接口参数本质是引用类型的值传递
当方法声明为 void process(List<string> list)</string>,你传入 new ArrayList(),实际传递的是该 ArrayList 对象在堆内存中的地址值的一个副本。JVM 并不复制对象本身,也不复制接口定义,只是把指向那个对象的“引用值”拷贝了一份给形参。
这意味着:
- 方法内可以调用该对象的所有 public 方法(包括接口定义的方法和实现类自己的方法,只要可见)
- 方法内修改对象状态(如
list.add("x"))会影响原对象——因为两个引用指向同一块堆内存 - 但若在方法内重新赋值形参(如
list = new LinkedList()),不会影响调用方的原始引用
为什么能传实现类给接口参数?
这是多态性的体现,依赖于编译期类型检查 + 运行时动态绑定:
- 编译器确认:实现类确实实现了该接口(否则编译失败)
- 运行时:JVM 根据实际对象类型(而非形参声明类型)决定调用哪个具体方法(即虚方法调用)
例如:process(new ArrayList()) 和 process(new LinkedList()) 都合法,且各自调用各自类中重写的 add()、size() 等方法。
和泛型擦除无关,但和类型安全有关
接口参数本身不涉及泛型擦除问题;擦除发生在泛型类型(如 List<string></string>)被编译后变成裸类型 List 的过程。而接口作为类型约束,在编译期就完成了合法性校验。即使泛型信息被擦除,List 接口本身仍存在,其方法签名也完整保留。
真正保障类型安全的是:
- 编译器对实参是否实现接口的检查
- 泛型在编译期提供的类型约束(如防止往
List<string></string>中 add(Integer))
常见误区澄清
✘ “传的是接口,所以只能调用接口里的方法”——错。只要方法可见,且编译通过(比如实现类有 public void sort()),你可以在方法内部向下转型后调用:((ArrayList) list).sort(...)(当然不推荐,破坏抽象)
✘ “接口参数会自动转换成实现类类型”——错。类型变量仍是接口类型,JVM 不做隐式转换;转型需显式强制,且运行时检查类型兼容性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











