动手动脑(四)

一,

 1 public class Grandparent {
 2     public Grandparent()
 3      {
 4             System.out.println("GrandParent Created.");
 5 }
 6     public Grandparent(String string) 
 7     {
 8             System.out.println("GrandParent Created.String:" + string);
 9  }
10 }
11 public class Parent extends Grandparent {
12      public Parent(){         
13             //super("Hello.Grandparent.");该语句可用于调用Grandparent中的有参数的构造函数
14             System.out.println("Parent Created");    
15            //super("Hello.Grandparent.");该语句必须写在子类构造方法的首句,否则编译会报错
16       }
17 }
18 public class Child extends Parent{
19     public Child(){    
20        System.out.println("Child Created");
21       }
22 }
23 public class TestInherits {
24 public static void main(String[] args){    
25     Child c = new Child();    
26 }
27 }

运行结果(调用Grandparent默认构造函数):

运行结果(调用Grandparent中的有参数的构造函数):

注意:通过super调用基类构造方法,必须是子类构造方法的首句!

原因:构造方法的作用为初始化对象,必须先初始化父类,之后才能初始化子类对象。

 二,

1 public class ExplorationJDKSource {
2     public static void main(String[] args) {
3         System.out.println(new A());
4     }
5 
6 }
7 class A{}

运行结果:

探究输出上述结果的原因:

(1)使用javap -c命令反汇编.class文件

最后我们发现:

main方法实际上调用的是:
public void println(Object x),这一方法内部调用了String类的valueOf方法。
valueOf方法内部又调用Object.toString方法:
public String toString() {
 return getClass().getName() +"@" +
 Integer.toHexString(hashCode());
}
hashCode方法是本地方法,由JVM设计者实现:
public  native int hashCode();

也就是说输出的是java中顶层基类Object的toString()方法。

三,

 1 public class Fruit
 2 {    
 3     public String toString()
 4     {
 5         return "Fruit toString.";
 6     }
 7     public static void main(String args[])
 8     {
 9         Fruit f=new Fruit();
10         System.out.println("f="+f);
11         System.out.println("f="+f.toString());
12     }
13 }

运行结果:

分析:

在“+”运算中,当任何一个对象与一个String对象,连接时,会隐式地调用其toString()方法,默认情况下,此方法返回“类名 @ + hashCode”。为了返回有意义的信息,子类可以重写toString()方法。

在这个例子中正是Fruit类覆盖了Object类的toString方法,所以才会输出“Fruit toString”。

四,

 1 public class Parent {
 2     public Parent() {
 3         System.out.println("Parent Creat");
 4     }
 5     public void show() {
 6         System.out.println("Parent Wecome");
 7     }
 8 }
 9 public class Child extends Parent {
10     public Child() {
11         System.out.println("Child Creat");
12     }
13     public void show() {
14         //super.show();该行是运用关键字super调用父类中被覆盖的函数
15         System.out.println("Child Wecome");
16     }
17 }
18 public class text {
19     public static void main(String[] args) {
20         Child a=new Child();        
21         a.show();
22     }
23 
24 }

运行截图(未使用super):

运行截图(使用super):

总结:若要调用父类中被覆盖的方法,可以使用super关键字。

五,

 1 public class TestInstanceof
 2 {
 3     public static void main(String[] args) 
 4     {
 5         //声明hello时使用Object类,则hello的编译类型是Object,Object是所有类的父类
 6         //但hello变量的实际类型是String
 7         Object hello = "Hello";
 8         //String是Object类的子类,所以返回true。
 9         System.out.println("字符串是否是Object类的实例:" + (hello instanceof Object));
10         //返回true。
11         System.out.println("字符串是否是String类的实例:" + (hello instanceof String));
12         //返回false。
13         System.out.println("字符串是否是Math类的实例:" + (hello instanceof Math));
14         //String实现了Comparable接口,所以返回true。
15         System.out.println("字符串是否是Comparable接口的实例:" + (hello instanceof Comparable));
16         String a = "Hello";
17         //String类既不是Math类,也不是Math类的父类,所以下面代码编译无法通过
18         //System.out.println("字符串是否是Math类的实例:" + (a instanceof Math));
19     }
20 }

运行截图:

总结:

判断一个对象是否可以转换为指定的类型可以使用运算符instanceof

六,

 1 class Mammal{}
 2 class Dog extends Mammal {}
 3 class Cat extends Mammal{}
 4 
 5 public class TestCast {
 6     public static void main(String args[])
 7     {
 8         Mammal m;
 9         Dog d=new Dog();
10         Cat c=new Cat();
11         m=d;
12         //d=m; 编译无法通过,类型不匹配,不能从Mammal转换为Dog
13         d=(Dog)m; //将m的类型强制转换为Dog,与d类型匹配,编译通过
14         //d=c; 编译无法通过,类型不匹配,不能从Cat转换为Dog
15         //c=(Cat)m; 该行会运行时出错,因为m已经被强制转换为Dog类型,但Dog类型不能强制转换为Cat.
16 
17     }
18 }

七,

 1 public class ParentChildTest {
 2     public static void main(String[] args) {
 3         Parent parent=new Parent();
 4         parent.printValue();//调用父类的printValue()方法,输出父类的myValue值
 5         Child child=new Child();
 6         child.printValue();//调用子类的printValue()方法,输出子类的myValue值
 7         
 8         parent=child;//用子类初始化父类对象
 9         parent.printValue();//调用Child类的printValue()方法,输出Child类的myValue值
10         
11         parent.myValue++;//使父类的myValue值+1
12         parent.printValue();//因为上面执行了“parent=child;”,所以仍调用的是子类的printValue()方法
13         
14         ((Child)parent).myValue++;//因为前面使用了强制类型转换,所以使Child类的myValue值+1
15         parent.printValue();//同上
16                 
17     }
18 }
19 
20 class Parent{
21     public int myValue=100;
22     public void printValue() {
23         System.out.println("Parent.printValue(),myValue="+myValue);
24     }
25 }
26 
27 class Child extends Parent{
28     public int myValue=200;
29     public void printValue() {  
30         System.out.println("Child.printValue(),myValue="+myValue);
//System.out.println("父类中此时myValue值:"+super.myValue); 此行代码可用于显示父类中呗被隐藏的同名字段
31 } 32 }

运行结果:

总结:

(1)当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。

(2)如果子类与父类拥有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。

运行截图(添加super显示被隐藏的父类myValue值):

原文地址:https://www.cnblogs.com/mawangwang/p/9892468.html