Some confusing mechanisms in Java

I am sure many people heard some concepts or mechanisms while learning Java and almost always got confused by differentiate them. These are: overload, override, hide, shadow, and obscure. Many books talk a lot about the first three, but the last two may be a little strange. Overload is the easiest, I think, because it is applied in only one class. The only trick is that a class can have more than one member method with the same name but different parameter lists. The other four are applied in two or more classes in the inheritance hierarchy, and much more complex and confusing sometimes. We will discuss them next.

Override

It allows an instance member method in a subclass to override (or we can say overwrite) the method with the same signature in its superclass. When calling such methods, the JVM will choose the corresponding method according to the runtime type of the instance used, not the compile-time type. For example:

class  Base
{
    
public void f()
    
{
        System.out.println(
"Base");
    }

}


public
class  Derived  extends  Base
{
    
public void f()
    
{
        System.out.println(
"Derived");
    }
        public static void main(String[] args)
        {
            Base b = new Derived();
            b.f();
        }
}

The command line will print "Derived". Though the compile-time type of b is Base, in fact it is an object of Derived, which is its runtime type.

Hide

It allows a field, a static member method, or a member type in a subclass, to all the fields, static member methods, and member types with the same names in the super class unvisible, respectively. That means, the JVM will choose the right one according to the compile-time type of the reference.

class  Base
{
    
public int i = 1;
    
public static void f()
    
{
        System.out.println(
"Base");
    }

}


public   class  Derived  extends  Base
{
    
public int i = 10;
    
public static void f()
    
{
        System.out.println(
"Derived");
    }


    
public static void main(String[] args)
    
{
        Base b 
= new Derived();
        b.f();
        System.out.println(b.i);
        Derived d 
= (Derived)b;
        d.f();
        System.out.println(d.i);
    }

}

It prints: Base 1 Derived 10(each occupies one line), which shows how it works.

Shadow

With this mechanism, a variable, a method, and a type can make all the variables, all the methods, and all the types in a closed context void. The following example is drawn from <Java Puzzlers>:

public   class  StrungOut  {
    
public static void main(String[] args) {
        String s 
= new String("Hello world");
        System.out.println(s);
    }

}


class  String  {
    
private final java.lang.String s;

    
public String(java.lang.String s) {
        
this.s = s;
    }


    
public java.lang.String toString() {
        
return s;
    }

}

This won't be compiled at all. The reason is that the class String defined in this file (a closed context) make the java.lang.String void. So the parameter of the main method is of a different type from the correct one, and the compiler won't recognize this new signature.

Obscure

What do you think will be print out when executing the example below?

public   class  ShadesOfGray  {
    
public static void main(String[] args){
        System.out.println(X.Y.Z);
    }

}


class  X  {
    
static class Y {
        
static String Z = "Black";
    }
 

    
static C Y = new C();
}


class  C  {
    String Z 
= "White";
}

Yes, White. A little confusing, huh? A variable can obscure a type with the same name in the same closed context, which means if this name is used in a circumstance where both the variable and the type are permitted, it will be referenced to the variable instead of the type. similarly, a variable or a type can obscure a package. This is the only situation of reuse of the same names with these names being in different namespaces, which include variables, types, methods and packages.

Maybe you will ask how to print "Black" then? You can use this statement to replace the one in the code above:

System.out.println(((X.Y)null).Z);

So, if a type or a package is obscured, you cannot use simple names to reference to them, unless you specify the type explicitly.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值