编辑
2025-03-15
编程学习
00

目录

静态绑定和动态绑定
static 方法的静态绑定
private 方法的静态绑定
final 方法的静态绑定
构造器的静态绑定
动态绑定
参考

前段时间刷到一个牛客题目,问输出的结果。虽苦思冥想蒙对了,但查看解析终不解其意,遂自己查找资料测试。

牛客题目如下,问输出是什么?

Java
public class Demo { public static void main(String[] args) { Collection<?>[] collections = {new HashSet<String>(), new ArrayList<String>(), new HashMap<String, String>().values()}; Super subToSuper = new Sub(); for (Collection<?> collection : collections) { System.out.println(subToSuper.getType(collection)); } } abstract static class Super { public static String getType(Collection<?> collection) { return "Super: collection"; } public static String getType(List<?> list) { return "Super: list"; } public String getType(ArrayList<?> list) { return "Super: arrayList"; } public static String getType(Set<?> set) { return "Super: set"; } public String getType(HashSet<?> set) { return "Super: hashSet"; } } static class Sub extends Super { public static String getType(Collection<?> collection) { return "Sub"; } } }

答案:

txt
Super:collection Super:collection Super:collection

所以是为什么呢?

静态绑定和动态绑定

privatefinalstatic 所修饰的方法和构造器,决定对象调用方法采用的是静态绑定。

static 方法的静态绑定

Java
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { Test test = new SubTest(); SubTest subTest = new SubTest(); List<Integer> list = new ArrayList<>(); ArrayList<Integer> arraylist = new ArrayList<>(); test.print(list); test.print(arraylist); subTest.print(list); subTest.print(arraylist); } abstract static class Test { public static void print(List<Integer> list) { System.out.println("static list"); } public void print(ArrayList<Integer> list) { System.out.println("non-static ArrayList"); } } static class SubTest extends Test { public static void print(List<Integer> list) { System.out.println("sub static list"); } public void print(ArrayList<Integer> list) { System.out.println("sub non-static ArrayList"); } } }

输出结果:

txt
static list sub non-static ArrayList sub static list sub non-static ArrayList

对以上测试结果的个人理解,调用方法时,先根据方法参数判断使用哪个重载方法。

  • 如果使用了静态方法,则由于静态绑定的原因,调用绑定在的类型上的静态方法,而非真实的对象类上的静态方法。
  • 如果使用了实例方法,则由于动态绑定的原因,调用真实对象实例的方法,与绑定到什么类型上无关。
  • 需要注意的是方法虽然分静态和非静态,但是子类重写方法时相同的参数列表对应的一定是相同的静态/非静态方法。不能父类是静态,而相同的参数列表在子类变为非静态了,这是不行的。

private 方法的静态绑定

java
public class Main { public static void main(String[] args) { Test.print(); } static abstract class Test { private void func() { System.out.println("test private method"); } public static void print() { Test test = new SubTest(); SubTest subTest = new SubTest(); test.func(); subTest.func(); } } static class SubTest extends Test{ public void func() { System.out.println("sub test method"); } } }

输出结果:

txt
test private method sub test method

由于 private 方法被自动认为 final 方法,而且对导出类,也就是子类是屏蔽的,所以在这种情况下,SubTest 类中的 func() 方法就是一个全行的方法,既然 Test 中的 func() 方法在 SubTest 类中不可见,所以甚至不能进行重写。

final 方法的静态绑定

由于 final 方法无法重写,父类子类方法相同,没有动态绑定的说法。

构造器的静态绑定

构造器无法被重写,也就没有动态绑定的说法。

动态绑定

public class Main { public static void main(String[] args) { Test test1 = new Test(); Test test2 = new SubTest(); SubTest subTest = new SubTest(); test1.func(); test2.func(); subTest.func(); } static class Test { public void func() { System.out.println("test method"); } } static class SubTest extends Test{ public void func() { System.out.println("sub test method"); } } }

输出结果:

txt
test method sub test method sub test method

我们使用父类的 func() 方法调用了子类的 func() 方法。这种绑定是在运行时完成的,因此称为动态绑定。这是多态的一种重要体现。

参考

本文作者:Zerol Acqua

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!