Java SE 是什么,包括哪些内容(十八)?
本文内容参考自Java8标准
再次感谢Java编程思想对本文的启发!
缺陷一:无法"覆盖"私有方法
如果我们试图像下面这样做也是无可厚非的:
// 试图"覆盖"私有方法
//类PrivateOverride
public class PrivateOverride{
//私有方法f()
private void f(){
//打印字符串"private f()"
System.out.println("private f()");
}
//程序执行入口main方法
public static void main(String[] args) {
//创建类Derived的对象,赋值给类PrivateOverride的引用po
PrivateOverride po = new Derived();
//调用方法f()
po.f();
}
}
//类Derived继承类PrivateOverride
class Derived extends PrivateOverride{
//方法f()
public void f(){
//打印字符串"public f()"
System.out.println("public f()");
}
}
按照多态的一贯思路,我们所期望的输出是public f(),但是由于private方法被自动认为是final方法,同时对子类也是屏蔽、不可见的。因此,在这种情况下,Derived类中的方法f()就是一个全新的方法;既然父类中的方法f()在子类Derived中不可见,所以不能被重载(也可以说是不能被重新实现)。
**结论:**只有非private方法才可以被覆盖,但是还是需要密切关注"覆盖"private方法的现象,虽然编译器不会对此报错,但是也不会按照我们期望的结果来执行,确切的说:在子类中,对于父类中的private方法,最好采用不同的名字。
缺陷二:域与静态方法
一旦你了解了多态机制,可能就会开始认为所有事物都可以多态地发生,然而,只有普通的方法调用是多态的。例如,你可以直接访问某个域,这个访问就将在编译器进行解析,就像下面的示例所演示的:
代码示例:
// 访问域
//父类Super
class Super{
//int类型的类变量(域)field,初始化值为0
public int field = 0;
//方法getField()
public int getField(){
//返回类变量field
return field;
}
}
//类Sub继承类Super
class Sub extends Super{
//int类型的类变量(域)field,初始化值为1
public int field = 1;
//方法getField()
public int getField(){
//返回类变量field
return field;
}
//方法getSuperField()
public int getSuperField(){
//返回父类变量field
//在继承关系中,在子类中都是通过关键字super
//类明确调用父类的组成部分(域,方法等)
return Super.field;
}
}
//类FieldAccess
public class FieldAccess{
//程序执行入口main方法
public static void main(String[] args) {
//创建子类Sub的对象赋值给父类的引用sup
//这里会自动发生向上转型
Super sup = new Sub();
//打印字符串"sup.field = "+sup.field+",sup.getField() =
//"+sup.getField()
System.out.println("sup.field = "+sup.field+",sup.getField() =
"+sup.getField());
//创建子类Sub的对象,赋值给子类的引用sub
Sub sub = new Sub();
//打印字符串"sub.field = "+sub.field+",sub.getField() =
//"+sup.getField()+",sub.getSuperField()="+sub.getSuperField()
System.out.println("sub.field = "+sub.field+",sub.getField() =
"+sup.getField()+",sub.getSuperField()="+sub.getSuperField());
}
}
结果示例:
当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的(如果域访问也是多态的,那么第一条打印语句中sup.field的值应该是1,而不是父类的0,但是方法是多态的,所以第二条打印语句sup.getField()值为1)。
在上面的例子中,为Super.field和Sub.field分配了不同的存储空间,这样,子类Sub中实际上包含了两个称为field的域:它自己的和它从父类Super得到的。然而,在引用Sub中的field时所产生的默认域并非Super版本的field域,因此,为了得到Super.field(也就是为了得到父类中的field,必须通过关键字super),必须显式地指明super.field。
尽管上面的示例代码看起来好像会成为一个容易令人混淆的问题,但是在实践中,它实际上从来不会发生。主要基于以下两点:
⑴、通常会将所有的域都设置成private,因此不能直接访问。之多通过set/get方法来访问。
⑵、你可能不会选择对父类中的域和子类中的域赋予相同的名字。因为这种做法本身就容易令人产生混淆。
如果某个方法是静态的(也就是有static关键字修饰的),它就不具有多态性
代码示例:
// 静态方法不具有多态性
class StaticSuper{
public static String staticGet(){
return "Base statcGet()";
}
public String dynamicGet(){
return "Base dynamicGet()";
}
}
class StaticSub extends StaticSuper{
public static String staticGet(){
return "Derived statcGet()";
}
public String dynamicGet(){
return "Derived dynamicGet()";
}
}
public class StaticPolymorphism{
//程序执行入口main方法
public static void main(String[] args) {
StaticSuper sup = new StaticSub();
System.out.println(sup.staticGet());
System.out.println(sup.dynamicGet());
}
}
结果示例:
你需要明确知道的是:静态方法是与类,而并非与单个对象相关联的。
PS:时间有限,有关Java SE的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正。