【java】向上转型和向下转型

来源:互联网 发布:云计算和大数据 编辑:程序博客网 时间:2024/06/11 23:44

参考链接:http://blog.csdn.net/lzm18064126848/article/details/53872332

Java面向对象向上转型和向下转型有什么区别?

面向对象中的转型只会发生在有继承关系的子类和父类中(接口的实现也包括在这里)。加入有父类:人,子类:男人和女人。向上转型: Person p = new Man() ; //向上转型不需要强制类型转化向下转型: Man man = (Man)new Person() ; //必须强制类型转化

若想操作拥有共同父类的不同(子)类们的实例,就向上转型;

若想当成指定的具体的子类的实例,就向下转型。

越向上,概念越模糊,可以代表多种不同的类的实例,

越向下,概念越具体详细,可以代表特定的类的实例。


子类对象向上转型为父类实例后,调用的是父类方法,还是子类方法?

当子类重写了父类方法,向上造成后调用的是子类方法

子类没有重写父类方法,向上造型后调用的是父类方法。


package test;public class HelloWorld {public static void main(String[] args)  {A k=new B();k.sayHi();k.hello();}}class A {public void sayHi(){System.out.println("我是父类");}public void hello(){System.out.println("我是父类hello");}}class B extends A{public void sayHi(){System.out.println("我是子类");}}

输出结果:

我是子类
我是父类hello


向上转型之后 子类原有的一些方法已经消失:

package test;class Animal {public void eat(){System.out.println("animal eatting...");}}class Bird extends Animal{public void eat(){System.out.println("bird eatting...");}public void fly(){System.out.println("bird flying...");}}public class HelloWorld{public static void main(String[] args) {Animal b=new Bird(); //向上转型b.eat(); //! error: b.fly(); b虽指向子类对象,但此时丢失fly()方法/*b实际指向的是Bird子类,故调用时会调用子类本身的方法。需要注意的是向上转型时b会遗失除与父类对象共有的其他方法。如本例中的fly方法不再为b所有。*/}}  


package test;class Human {public void sleep() {System.out.println("Human sleep..");}}class Male extends Human {@Overridepublic void sleep() {System.out.println("Male sleep..");}}class Female extends Human {@Overridepublic void sleep() {System.out.println("Female sleep..");}}    public class HelloWorld{public static void main(String[] args) {dosleep(new Male());dosleep(new Female());}/*以父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。不然的话,如果dosleep以子类对象为参数,则有多少个子类就需要写多少个函数。这也体现了JAVA的抽象编程思想。*/public static void dosleep(Human h) {h.sleep();}}


package test; class father {   protected String name="父亲属性";   public void method() {   /* 关于java this.getClass(); * Java的每个类都带有一个运行时类对象,该Class对象中保存了创建对象所需的所有信息。可以用.class返回此 Object 的运行时类Class对象,也可以用getClass()获得。获得此对象后可以利用此Class对象的一些反射特性进行操作,例如:this.getClass().newInstance(); //用缺省构造函数创建一个该类的对象this.getClass().getInterfaces(); //获得此类实现的接口信息this.getClass().getMethods();//获得此类实现的所有公有方法Class.forName(" ... JDBC driver class name...."); // Class类的静态方法forName, 向DiverManager注册这个JDBC driver类 * */ System.out.println("父类方法,对象类型:" + this.getClass());    }   } public class HelloWorld extends father {   protected String name="儿子属性";   public void method() {   System.out.println("子类方法,对象类型:" + this.getClass());   }public static void main(String[] args) {  father sample = new HelloWorld();//向上转型   System.out.println("调用的成员:"+sample.name);sample.method(); } }

输出结果:

调用的成员:父亲属性
子类方法,对象类型:class test.HelloWorld

注意:

在处理Java类中的成员变量时,并不是采用运行时绑定,而是一般意义上的静态绑定。所以在向上转型的情况下,对象的方法可以“找到”子类,而对象的属性还是父类的属性。

方法和属性的差别;

试图调用子类的成员变量name,该怎么做?最简单的办法是将该成员变量封装成方法getter形式。

package test;class Father {protected String name = "父亲属性";public String getName() {return name;}public void method() {System.out.println("父类方法,对象类型:" + this.getClass());}}public class HelloWorld extends Father {protected String name = "儿子属性";public String getName() {return name;}public void method() {System.out.println("子类方法,对象类型:" + this.getClass());}public static void main(String[] args) {Father sample = new HelloWorld();// 向上转型System.out.println("调用的成员:" + sample.getName());}}


向下转型:

package test;class Girl {public void smile(){System.out.println("girl smile()...");}}class MMGirl extends Girl{@Overridepublic void smile() {System.out.println("MMirl smile sounds sweet...");}public void c(){System.out.println("MMirl c()...");}}public class HelloWorld{public static void main(String[] args) {//父类的引用可以指向子类的对象,但是子类的引用不能指向父类的对象。//http://www.cnblogs.com/gold-worker/archive/2012/09/26/2704717.htmlGirl g1=new MMGirl(); //向上转型g1.smile();MMGirl mmg=(MMGirl)g1; //向下转型,编译和运行皆不会出错mmg.smile();mmg.c();Girl g2=new Girl();//MMGirl mmg1=(MMGirl)g2; //不安全的向下转型,编译无错但会运行会出错//mmg1.smile();//mmg1.c();/*output:* CGirl smile sounds sweet...* CGirl smile sounds sweet...* CGirl c()...* Exception in thread "main" java.lang.ClassCastException: com.wensefu.other1.Girl* at com.wensefu.other1.Main.main(Girl.java:36)*//*if(g2 instanceof MMGirl){MMGirl mmg1=(MMGirl)g2; mmg1.smile();mmg1.c();}*/}}

instanceof使用实例:


package test;/*java 中的instanceof运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。   用法:                        result = object instanceof class                        参数:                        Result:布尔类型。                        Object:必选项。任意对象表达式。                        Class:必选项。任意已定义的对象类。                        说明:                        如果object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是                                                 null,则返回 false。*/interface A{}class B implements A{}class C extends B {}public class HelloWorld { public static void main(String[] args){    A a=null;    B b=null;    boolean res;       System.out.println("instanceoftest test case 1: ------------------");      res = a instanceof A;      System.out.println("a instanceof A: " + res);           res = b instanceof B;      System.out.println("b instanceof B: " + res);         System.out.println("\n"+" instanceoftest test case 2: ------------------");      a=new B();    b=new B();       res = a instanceof A;    System.out.println("a instanceof A: " + res);       res = a instanceof B;    System.out.println("a instanceof B: " + res);    res = b instanceof A;    System.out.println("b instanceof A: " + res);       res = b instanceof B;    System.out.println("b instanceof B: " + res);      System.out.println("\n  instanceoftest test case 3: ------------------");    B b2=(C)new C();       res = b2 instanceof A;    System.out.println("b2 instanceof A: " + res);       res = b2 instanceof B;    System.out.println("b2 instanceof B: " + res);       res = b2 instanceof C;    System.out.println("b2 instanceof C: " + res); }}



0 0