java的向上转型
⑴ java中关于向上转型的问题
RTTI机制
向上转型的目的仍然是抽象。
比如
水果有颜色、味道。不同的水果有不同的颜色和味道。那么当
水果
sg
=
new
橘子();
水果
sg1
=
new
苹果();
sg.color();sg.taste();
sg1.color();sg1.taste();
sg,sg1都是水果实例的引用。但会调用不同的具体子类的方法。
其目地都是抽象。通过访问父类或接口的方法(公共)达到一种对具体实现的封装。对于接口的使用者来说,不需要关心实现细节。提高内聚,降低不必要的耦合。
再多说一句:注意转型时带来的
内存切片。
⑵ java 向上转型 向下转型
1.
引用a的类型是animal,是cat的父类。所以是“父类引用指向子类对象”。如果是“子类引用指向父类对象”,那应该写成
cat
a
=
new
animal();但这显然是不和逻辑的。
2.
你说的没错——“向上转型后,父类也只能调用父类已经有的方法”。但是子类如果覆盖了父类的方法,那么即使向上转型,方法的行为也表现为覆盖后的行为。这也是多态的一种体现。向上转型更多的用来体现一种编程上的“约定”。所有继承某个类或者实现某个接口的类,一定包含某个方法,这样在调用的时候,使得你也不必关系具体的实现细节,只要知道“这个类型中的某个方法能帮我完成工作”就可以了。
3.
向下转型,是“引用的类型”的变化,不是对象实例类型的变化。new什么,就是什么。不会因为向上或者向下转型而改变自己的类型。
4.
最后一个问题,不管向上还是向下转型,调用的都是实际类型中的那个方法。比如,animal
a
=
new
cat(); a.叫()。那这个叫就是cat类型实例中的“叫”方法。
⑶ 在java中,向上转型的机制是怎样工作的
向上转型(upcasting):对象可以作为它本身的类型使用也可以作为它父类(基类)对象使用,java中是单继承的,所以是一种安全的做法。
当你初始化子类时,产生一个对象时,该对象将父类的对象作为子对象包含其中。向上转型会丢失子类的方法。但可以将所有对象至于一个共同的容器中存储与调用,实现了容器的复用,(collection 容器集默认将所有对象作为Object存储的),但在具体使用是要确定对象原来的身份。
Java在运行中动态识别对象和类信息有两种机制:
1、RTTI(run-time type identification)运行期类别识别(强制类型转换“()”,类型转换是在运行期进行的),它假定我们在编译和运行期已经知道了所有的类型。
Java是通过Class对象实现RTTI机制的
Java中为每个类创建一个Class对象(*.class),它包括了与类相关的信息,用来创建类的常规对象,在运行期,一旦我们想生成某个类的对象,运行这个程序的JVM首先检查这个类的Class对象是否加载,如果尚未加载,JVM会根据类名查找.class文件,并将其载入,之后你就可以创建这个类的任何对象了。java程序不是一开始执行,所有类就被完全加载的。Class对象仅在需要时被加载,Static语句块是在类被加载时执行。
生成Class对象的两种引用方式:
Class.forName(“Gun”)
类字面常量: Gun.class
RTTI的限制:类在编译期间必须已知,在编译期间打开和检查.class文件。
2、反射机制(reflection)它允许我们在运行期获得类的信息。
反射机制在运行期打开和检查.class文件。
⑷ 在java里面的向上转型和向下转型的具体好处在哪里
java里面的向上转型和向下转型的具体好处如下:
1.转型是在继承的基础上而言的,继承是面向对象语言中,代码复用的一种机制,通过继承,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。
2.向上转型:子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口
向上转型时,父类指向子类引用对象会遗失除与父类对象共有的其他方法,也就是在转型过程中,子类的新有的方法都会遗失掉,在编译时,系统会提供找不到方法的错误。实例如下:
publicclassAnimal{
publicvoideat(){
System.out.println("animaleatting...");
}
}
classBirdextendsAnimal{
publicvoideat(){
System.out.println("birdeatting...");
}
publicvoidfly(){
System.out.println("birdflying...");
}
}
classMain{
publicstaticvoidmain(String[]args){
Animalb=newBird();//向上转型
b.eat();
b.fly();//此处提示在Animal中没有定义fly方法。
}
⑸ 在java 中,什么叫向上转型
java 转型问题其实并不复杂,只要记住一句话:父类引用指向子类对象。
什么叫父类引用指向子类对象,且听我慢慢道来.
从2个名词开始说起:向上转型(upcasting) 、向下转型(downcasting).
举个例子:有2个类,Father是父类,Son类继承自Father。
Father f1 = new Son(); // 这就叫 upcasting (向上转型)
// 现在f1引用指向一个Son对象
Son s1 = (Son)f1; // 这就叫 downcasting (向下转型)
// 现在f1还是指向Son对象
第2个例子:
Father f2 = new Father();
Son s2 = (Son)f2; // 出错,子类引用不能指向父类对象
你或许会问,第1个例子中:Son s1 = (Son)f1;问什么 是正确的呢。
很简单因为f1指向一个子类对象,Father f1 = new Son(); 子类s1引用当然可以指向子类对象了。
而f2 被传给了一个Father对象,Father f2 = new Father();子类s1引用不能指向父类对象。
总结:
1。父类引用指向子类对象,而子类引用不能指向父类对象。
2。把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转换。
如:Father f1 = new Son();
3。把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转换。
如:f1 就是一个指向子类对象的父类引用。把f1赋给子类引用s1即 Son s1 = (Son)f1;
其中f1前面的(Son)必须加上,进行强制转换。
一、向上转型。
通俗地讲即是将子类对象转为父类对象。此处父类对象可以是接口。
1,向上转型中的方法调用。
看下面代码:
[java] view plainprint?
package com.wensefu.others;
public 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...");
}
}
class Main{
public static void main(String[] args) {
Animal b=new Bird(); //向上转型
b.eat();
//! error: b.fly(); b虽指向子类对象,但此时丢失fly()方法
dosleep(new Male());
dosleep(new Female());
}
public static void dosleep(Human h) {
h.sleep();
}
}
[java] view plainprint?
package com.wensefu.others;
public class Human {
public void sleep() {
System.out.println("Human sleep..");
}
}
class Male extends Human {
@Override
public void sleep() {
System.out.println("Male sleep..");
}
}
class Female extends Human {
@Override
public void sleep() {
System.out.println("Female sleep..");
}
}
注意这里的向上转型:
Animal b=new Bird(); //向上转型
b.eat();
此处将调用子类的eat()方法。原因:b实际指向的是Bird子类,故调用时会调用子类本身的方法。
需要注意的是向上转型时b会遗失除与父类对象共有的其他方法。如本例中的fly方法不再为b所有。
2,向上转型的好处。
看上面的代码,
public static void dosleep(Human h) {
h.sleep();
}
这里以父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。不然的话,
如果dosleep以子类对象为参数,则有多少个子类就需要写多少个函数。这也体现了JAVA的抽象编程思想。
二、向下转型。
与向上转型相反,即是把父类对象转为子类对象。
看下面代码:
[java] view plainprint?
package com.wensefu.other1;
public class Girl {
public void smile(){
System.out.println("girl smile()...");
}
}
class MMGirl extends Girl{
@Override
public void smile() {
System.out.println("MMirl smile sounds sweet...");
}
public void c(){
System.out.println("MMirl c()...");
}
}
class Main{
public static void main(String[] args) {
Girl 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();
}
}
}
Girl g1=new MMGirl(); //向上转型
g1.smile();
MMGirl mmg=(MMGirl)g1; //向下转型,编译和运行皆不会出错
这里的向下转型是安全的。因为g1指向的是子类对象。
而
Girl g2=new Girl();
MMGirl mmg1=(MMGirl)g2; //不安全的向下转型,编译无错但会运行会出错
运行出错:
Exception in thread "main" java.lang.ClassCastException: com.wensefu.other1.Girl
at com.wensefu.other1.Main.main(Girl.java:36)
如代码所示,可以通过instanceof来防止出现异常。
⑹ java中向上转型,向下转型,强制类型转换的原理
向上或者向下转型
就要说到继承
比如有2个类
a
b
b继承a
先
b
b
=
new
b();
这个时候
a
a
=
b;
这种用法就是向上转型
使用父类的引用
引用子类对象
向上转型是自动的不需要其他操作
然后在上边的基础上
b
=
(b)a
这个就是向下转型
当用父类引用
引用子类对象
现在想不使用父类的引用
而使用子类的引用
就是向下转型
向下转型必须强制转型
必须确定对象确实是子类对象
如果是父类对象那就会报错
⑺ java 的向上转型到底什么意思,怎么表示
你好,这两点你必须理解:
1、向上转型就是让父类的引用去指向子类的对象。
2、向上转型会自动进行,因此是不需要显示声明的。
为了加深你的理解,举个例子:
class Parent{}
class Child extends Parent{}
Parent p = new Child() ; //这里就用到了向上转型,仔细体会,不难理解
⑻ java中的向上转型向下转型是甚么意思该如何去理解!
下面是我个人看法,仅供参考向上转型指子类向父类转型或与父类型变量产生运算向下转型指父类型向子类转型举个例子Objecto=newHashMap();//变量o定义的是Object类型,实际初始化时是HashMap类型(Object是所有类的父类),属于向上转型,没有任何问题Strings=o.get(id);//会报错//这条语句,从HashMap中获得对象,赋值到String变量由于是原生的HashMap,所以里面的元素是Object类型,赋值给String变量相当于向下转型,有毛病,需要强迫类型转换Strings=(String)o.get(id);//当前条件是HashMap中元素的确是String类型
⑼ 关于java中的向上转型
这个是面向对象的三大特性之一:多态。
如果子类中存在method()方法,则java虚拟机会使用子类的method()方法;
如果没有则去父类找到调用父类的方法。多态是将父类的引用指向子类。
⑽ 关于java的向上转型
来自CSDN。通俗易懂。
我们在现实中常常这样说:这个人会唱歌。在这里,我们并不关心这个人是黑人还是白人,是成人还是小孩,也就是说我们更倾向于使用抽象概念“人”。再例如,麻雀是鸟类的一种(鸟类的子类),而鸟类则是动物中的一种(动物的子类)。我们现实中也经常这样说:麻雀是鸟。这两种说法实际上就是所谓的向上转型,通俗地说就是子类转型成父类。这也符合Java提倡的面向抽象编程思想。来看下面的代码:
package a.b;
public class A {
public void a1() {
System.out.println("Superclass");
}
}
A的子类B:
package a.b;
public class B extends A {
public void a1() {
System.out.println("Childrenclass"); //覆盖父类方法
}
public void b1(){} //B类定义了自己的新方法
}
C类:
package a.b;
public class C {
public static void main(String[] args) {
A a = new B(); //向上转型
a.a1();
}
}
如果运行C,输出的是Superclass 还是Childrenclass?不是你原来预期的Superclass,而是Childrenclass。这是因为a实际上指向的是一个子类对象。当然,你不用担心,Java虚拟机会自动准确地识别出究竟该调用哪个具体的方法。不过,由于向上转型,a对象会遗失和父类不同的方法,例如b1()。有人可能会提出疑问:这不是多此一举吗?我们完全可以这样写:
B a = new B();
a.a1();
确实如此!但这样就丧失了面向抽象的编程特色,降低了可扩展性。其实,不仅仅如此,向上转型还可以减轻编程工作量。来看下面的显示器类Monitor:
package a.b;
public class Monitor{
public void displayText() {}
public void displayGraphics() {}
}
液晶显示器类LCDMonitor是Monitor的子类:
package a.b;
public class LCDMonitor extends Monitor {
public void displayText() {
System.out.println("LCD display text");
}
public void displayGraphics() {
System.out.println("LCD display graphics");
}
}
阴极射线管显示器类CRTMonitor自然也是Monitor的子类:
package a.b;
public class CRTMonitor extends Monitor {
public void displayText() {
System.out.println("CRT display text");
}
public void displayGraphics() {
System.out.println("CRT display graphics");
}
}
等离子显示器PlasmaMonitor也是Monitor的子类:
package a.b;
public class PlasmaMonitor extends Monitor {
public void displayText() {
System.out.println("Plasma display text");
}
public void displayGraphics() {
System.out.println("Plasma display graphics");
}
}
现在有一个MyMonitor类。假设没有向上转型,MyMonitor类代码如下:
package a.b;
public class MyMonitor {
public static void main(String[] args) {
run(new LCDMonitor());
run(new CRTMonitor());
run(new PlasmaMonitor());
}
public static void run(LCDMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
public static void run(CRTMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
public static void run(PlasmaMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
}
可能你已经意识到上述代码有很多重复代码,而且也不易维护。有了向上转型,代码可以更为简洁:
package a.b;
public class MyMonitor {
public static void main(String[] args) {
run(new LCDMonitor()); //向上转型
run(new CRTMonitor()); //向上转型
run(new PlasmaMonitor()); //向上转型
}
public static void run(Monitor monitor) { //父类实例作为参数
monitor.displayText();
monitor.displayGraphics();
}
}
我们也可以采用接口的方式,例如:
package a.b;
public interface Monitor {
abstract void displayText();
abstract void displayGraphics();
}
将液晶显示器类LCDMonitor稍作修改:
package a.b;
public class LCDMonitor implements Monitor {
public void displayText() {
System.out.println("LCD display text");
}
public void displayGraphics() {
System.out.println("LCD display graphics");
}
}
CRTMonitor、PlasmaMonitor类的修改方法与LCDMonitor类似,而MyMonitor可以不不作任何修改。
可以看出,向上转型体现了类的多态性,增强了程序的简洁性。