前段时间刷到一个牛客题目,问输出的结果。虽苦思冥想蒙对了,但查看解析终不解其意,遂自己查找资料测试。
牛客题目如下,问输出是什么?
Javapublic 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";
}
}
}
答案:
txtSuper:collection Super:collection Super:collection
所以是为什么呢?
由 private
、final
、static
所修饰的方法和构造器,决定对象调用方法采用的是静态绑定。
Javaimport 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");
}
}
}
输出结果:
txtstatic list sub non-static ArrayList sub static list sub non-static ArrayList
对以上测试结果的个人理解,调用方法时,先根据方法参数判断使用哪个重载方法。
javapublic 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");
}
}
}
输出结果:
txttest private method sub test method
由于 private
方法被自动认为 final
方法,而且对导出类,也就是子类是屏蔽的,所以在这种情况下,SubTest
类中的 func()
方法就是一个全行的方法,既然 Test
中的 func()
方法在 SubTest
类中不可见,所以甚至不能进行重写。
由于 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"); } } }
输出结果:
txttest method sub test method sub test method
我们使用父类的 func()
方法调用了子类的 func()
方法。这种绑定是在运行时完成的,因此称为动态绑定。这是多态的一种重要体现。
本文作者:Zerol Acqua
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!