精华内容
下载资源
问答
  • 在学习Java编程中,最头疼事情之一就是数据类型转换。时候它在不经意之间就完成了(自动类型转换),时候却又要求程序员必须手动指定(强制类型转换)。基本数据类型,转换规则还可以通过类型本身空间大小精度...

    9b8b0af85f1f0b022f0f80ac74773f2b.png

    在学习Java编程中,最头疼事情之一就是数据类型转换。有时候它在不经意之间就完成了(自动类型转换),有时候却又要求程序员必须手动指定(强制类型转换)。基本数据类型,转换规则还可以通过类型本身空间大小和精度分析明白,而且最多就是丢失精度但运行起来至少是不会报错。可是面对引用数据类型,这个“坑”就大了:有自动转的,有强制转的,居然还有强制都转不了的;自动转了的却把对象身上的方法丢了看不见;强制转的编译过了运行却可能报异常。

    e5953c5b9eaeb84beddc33901d2ac447.png


    一口老血,有木有?更要命的是,这个转型还相当的重要,Java中的动态多态还非它不可了。你说要命不要命?没关系,今天就让我们花点时间聊聊它,搞定它!

    对象不是你想转,想转就能转

    先人说:知己知彼,百战不殆。我们先来认知一下引用数据类型的一些基本概念,以下所有分析都基于两个方面进行:Java语法 和 面向对象场景。
    在普通情况下,我们会书写这样的代码:

    Dog snoopy = new Dog();
    snoopy.play();//调用Dog的玩耍行为
    snoopy.sitDown();//调用Dog的坐下行为
    snoopy.shakeHands();//调用Dog的握手行为

    我们看到在这个语法当中,赋值符号左右两边的数据类型是相同。赋值号左边是Dog类的引用snoopy变量,指向了右边new出来的Dog类对象。

    这个语法在对应的日常场景中是非常形象的。我们用snoopy称呼一个狗对象,并且确定一定以及肯定snoopy就是一个狗东西。然后我们就可以大喊:snoopy来玩游戏啦,snoopy坐下,snoopy握手。你看,多自然。

    但是,如果我们写出下面的代码:

    Dog snoopy = new Cat();
    snoopy.sitDown();

    赋值符号左右两边的数据类型是不同。赋值号左边是Dog类的引用snoopy变量,指向了右边new出来的Cat类对象。编译后,你就发现这句代码根本通不过。为什么?

    因为这个语法是荒谬的。snoopy明明是狗的代名词,结果你却让它指向了一只猫?还想让它执行狗才有的指令?铲屎的,你是不是不想活了?

    这个时候有同学想到了,那就强转。

    Dog snoopy = (Dog)new Cat();
    snoopy.sitDown();

    这就更令人发指了吧,你要怎么做才能强行让一只猫咪对象变成一只汪对象?上帝也疯狂了……你觉得Java会让允许你干这种完全匪夷所思不合常理的事情吗?所以,这句代码的下场也只有一个,那就是编译不通过。

    因此,我们得到了第一个结论:在Java当中不是任意引用数据类型之间都能进行转换!那么,哪些引用类型之间可以呢?

    向上转型—自动转换,没问题

    我们分别定义两个类:一个叫做Pet(宠物);一个叫做Dog,并且让Dog继承于Pet。

    public class Pet{
        public void play(){
            System.out.println("玩游戏");
        }
    }
    public class Dog extends Pet{
        public void sitDown(){
            System.out.println("坐下");
        }
    }

    那么,我们在需要调用处写下这个代码会发生什么呢?

    Pet myBaby = new Dog();

    你会发现虽然在赋值符号两边的数据类型不一致,但是这句代码无论是编译还是运行都完全没有问题,也就是说Java中父类的引用指向子类对象是自动成功的。这是为啥呢?其实无论是从语法上还是从场景分析上,我们会发现这是非常自然的,本身就应该自动成功。继承关系本就是一种is a关系,即所谓的“是一个“,所以Dog对象是一个Pet类型的呀(狗就是一种宠物嘛~~),这完全没有问题。

    在继承关系上,我们设计时通常在继承树上把父类画在上,子类在下,由于这种转型是沿着继承树往上走,所以我们把它称为–向上转型

    但是,

    myBaby.play();//编译通过
    myBaby.sitDown();//编译失败

    这又是为啥呢?

    因为myBaby是一个Pet类型的引用,所以是站在宠物的角度去看待汪对象。虽然对象还是狗狗,但是只能看到来自于父类宠物定义的play方法了。所以父类引用指向子类对象,只能调用到来自父类的属性/行为

    那如何调用到sitDown方法呢?答案很简单:换成狗的角度去看待这个汪星人。

    向下转型—强制转换,有风险

    Pet myBaby = new Dog();
    myBaby.play();
    Dog snoopy = (Dog)myBaby;
    snoopy.sitDown();

    这段代码无论编译还是运行都不会有任何问题。
    我们先使用Pet类型的myBaby指向了狗对象,然后再换成Dog类型的snoopy去指向同一个狗对象。前者由于是父类型所以只能看到定义在父类的方法,后者是子类型,当然就可以看到狗对象身上的特有行为了。这种转型是从父类引用转为子类引用,从继承树的角度说就是向下转型
    那为什么在把myBaby赋给snoopy的时候要使用强转语法呢?我们假设下面这种情况:
    如果Pet类还有一个子类叫做Cat类。

    public class Cat extends Pet{
        public void climbTree(){
            System.out.println("爬树");
        }
    }

    然后书写代码:

    public class Master{
        public void playWithPet(Pet myBaby){
            //操作代码
        }
    }

    那么,你告诉我传进来的myBaby到底是Dog对象呢?还是Cat对象?或者是Pet对象?由于父类引用可以指向子类对象,所以上面几种情况皆有可能了。所以我们如果想转型Dog类,就必须强制告诉Java,myBaby确实是一个Dog类型的对象。因此我们需要在注释部分书写:

    Dog snoopy = (Dog)myBaby;

    不过,就算你这么书写也只能保证编译通过,这个代码运行起来还是有可能失败,这就是所谓的强转风险性吧。如果你赋给myBaby的是 对象,当然没有问题;但假如赋的是 对象呢?这是不是相当于我们又从狗的角度去看待一个猫对象了?如何让一只狗变成一只猫,这又是一个荒谬的事情了。所以,如果向下转型想要编译和运行都成功,必须使用强制转型语法,还必须要求运行起来父类引用确实指向该子类的对象。

    所以,为了降低这种风险性,我们可以使用Java中的instance运算符,在强转前进行一次判断。所以最终代码是:

    public class Master{
        public void playWithPet(Pet myBaby){
            myBaby.play();
            if(myBaby instanceof Dog){
                Dog snoopy = (Dog)myBaby;
                snoopy.sitDown();
            }
        }

    结论

    1. 在引用数据类型中,只有有继承关系的类型才能进行类型转换;
    2. 类型转换只是转换看待对象的引用的类型,对象本身没有也不可能参与转换;
    3. 父类引用可以自动指向子类对象,但只能访问和调用到来自于父类的属性和行为;
    4. . 子类的引用不能指向父类或其它子类对象,就算强转也会导致运行失败并抛出ClassCastException;
    5. . 把父类引用赋给子类引用,语法上必须使用强制类型转换,要想运行也成功还必须保证父类引用指向的对象一定是该子类对象(最好使用instance判断后,再强转)。
    展开全文
  • 例如我们常用的整型浮点型数据的转换;float a = 1.23 ;int b = a ;cout<输出的将会是1,小数部分会被舍弃;int a = 1;float b = a ;cout<输出结果将是1.000000,会自动加上小树部分类,其实也与int、float...

    在程序开发中,数据类型转换是再正常不过的事情了,特别是C++这种强类型语言。例如我们常用的整型和浮点型数据的转换;

    float a = 1.23 ;

    int b = a ;

    cout<

    输出的将会是1,小数部分会被舍弃;

    int a = 1;

    float b = a ;

    cout<

    输出结果将是1.000000,会自动加上小树部分

    类,其实也与int、float一样是一种数据类型,那么类也就自然存在类型转换了,今天就来讲一讲C++的向上转型:

    所谓向上转型就是将子类转换为父类。请看下面代码:

    class Father

    {

    public:

    Father();

    ~Father();

    string firstName ;

    void showName()

    {

    cout<firstName<

    }

    private:

    };

    class Child:public Father

    {

    public:

    Child();

    ~Child();

    string lastName ;

    void showName()

    {

    cout<firstName<lastName<

    }

    private:

    };

    void main()

    {

    Father father ;

    father.firstName = "mickal";

    Child child ;

    child.firstName = "nike";

    child.lastName = "jordan" ;

    father = child ;

    father.showName();

    system("pause");

    }

    最后打印出来的结果是:father's name: nike;

    向上转型有以下两点要注意:

    1、子类除继承父类数据成员,并且还会有自己的数据成员,但是在向上转型后子类的数据成员会被舍弃

    2、赋值的本质是将现有的数据写入已分配好的内存中,对象的内存只包含了成员变量,所以对象之间的赋值是成员变量的赋值,成员函数不存在赋值问题。这点从运行结果就能看出来,虽然有father = child赋值过程,但是father.showName()始终调用的都是 Father 类的 showName() 函数。换句话说,对象之间的赋值不会影响成员函数,也不会影响 this 指针。

    图示原理如下:

    1a8973fcdc51bba71d01ab7d2917da52.png

    向上转型原理示意图

    向上转型非常安全,可以由编译器自动完成,但是向下转型非常危险,需要程序员自己处理,有可能会导致数据的丢失,原因是父类的指针或者引用的内存中可能不包含子类的成员的内存。

    关于向下转型的处理,后续我会从原理上详细的分享出来。今天工作太忙了,就先分享这个最基础的但是又十分重要的内容。

    展开全文
  • java作为面向对象的语言,同样可以描述一个事物的多种形态,java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口) 变量赋值。...

    一、多态的概念

    多态是继封装,继承之后,面向对象的三大特性。

    现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的张三同学既是学生也是人,即出现两种形态。

    java作为面向对象的语言,同样可以描述一个事物的多种形态,java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口) 变量赋值。

    父类的引用变量指向子类对象。多态的前提需要有继承关系或者是实现关系,否则没法完成多态。在使用多态后的父类引用变量调用方法时,会调用子类重写的;

    二、多态的定义与使用

    多态的定义格式:就是父类的引用变量指向子类的对象;

    父类类型变量名 = new 子类对象();

    变量名.方法名();

    1.普通类的多态定义格式:

    父类类型变量名 = new 子类();

    3fa4257f894d06b1c9984ac01a1437b2.png

    2.抽象类多态的定义:

    抽象类变量名 =new 抽象类子类();

    130fba7cb8bd3f45e43e2a2c55e93017.png

    3.接口多态定义的格式:

    接口变量名 =new 接口实现类();

    00e8be7319743bd651d57432ec2a664c.png

    注意:虽然变量指向子类的对象,但表现的是一个父类的形态,可以调用一切父类的方法,子类特有的方法将不能调用

    三、多态调用的注意事项:

    编译:成员变量,成员方法都需要看父类;父类没有编译报错;

    运行:成员变量运行父类的成员变量,成员方法运行父类重写的方法

    四、多态的好处与弊端

    好处:多态配合继承子类重写,提高了代码的复用性与扩展性

    弊端:不能调用子类特有的方法

    五、向上向下类型转换

    多态本身是子类类型向父类类型向上转型的过程;

    1.向上转型:

    当子类的对象赋值给一个父类的引用时,便是向上转型,多态本身就是向上转型的过程

    使用格式:父类类型 变量名= new 子类类型();

    2.向下转型:

    一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类的引用转换为子类引用,这个过程是向下转型。直接创建父类对象的无法使用向下转型;

    使用格式:

    子类类型 变量名= (子类类型) 父类类型的变量;

    六、instanceof 关键字

    可以通过instanceof关键字来判断某个对象是否属于某种数据类型;

    使用格式:

    boolean b= 对象(new ) instanceof 数据类型;

    展开全文
  • 生活中具体一类的事物也抽象一类的事物所以类当然也分为普通类抽象类。对象:是实现类的具体实列。2.定义类的步骤定义类名编写属性编写方法举例:public class person{ //定义类名:人类 private Stri...

    01

    类和对象

    1.定义类和对象

    :通俗的讲,类可以表示生活中的某一类事物,该事物所具有的特征(属性)和行为(方法)归结为一类。生活中有具体一类的事物也有抽象一类的事物所以类当然也分为普通类和抽象类。对象:是实现类的具体实列。
    2.定义类的步骤
    • 定义类名

    • 编写属性

    • 编写方法

    例:
    public class person{                 //定义类名:人类   private String name;      //定义属性:人类有名字 年龄     private int age;          public Person(String name, int age) {  //构造方法      this.name = name;      this.age = age;}  public void eat(){      //定义方法:吃饭    System.out.print(this.name+"吃饭");  }}
    3.使用类方法通过实例化一个类对象去调用
    实例化对象的方法:类名称 对象名称 = new 类名称();并通过对象.(点操作符)访问方法
    例:
    public class person{                 //定义类名:人类   private String name;      //定义属性:人类有名字 年龄     private int age;          public Person(String name, int age) {  //构造方法      this.name = name;      this.age = age;}  public void eat(){      //定义方法:吃饭    System.out.print(this.name+"吃饭");  }  public static void main(String[] args) {    //实例化一个person对象    Person p1 = new Person("zs",18);    //通过对象访问类方法    p1.eat();  }}
    总结1、类就是有相同特征的事物的集合,而对象就是类的一个具体实例。2、对象的产生需要以下三步:
    • 加载类;

    • 给对象开辟内存空间;

    • 调用构造方法;

    3、对象属性的初始化方式:
    • 提供一系列setter和getter方法;

    • 构造一个函数来重载;

    02

    封装

    1.封装的定义

    隐藏对象内部的复杂性,只对外公开简单的接口,便于外界使用,从而提高系统的扩展性、可维护性

    2. 封装的实现

    在JAVA中使用访问权限修饰符,实现封装。
    Java用于限定其他对象对该类内部定义的访问权限
    public、protected 、private、default 四个

    3.访问权限修饰符

    (1)public修饰的变量或者方法在不同包中,相同包中,子类中,当前类中都是可以直接访问的。
    (2)protected修饰的变量或者方法在相同包中,子类中,当前类中都是可以直接访问的,在不同包中的类则不能访问。
    (3)default(也就是默认的) 的变量或者方法在相同包中,当前类中都是可以直接访问的,在不同包中,即便是子类中也不能访问。
    (4)private 修饰的变量或者方法只能在当前类中都是直接访问,在不同类中就不能访问,只能提供向外的公开的方法去调用,也就是面向对象的封装。

    03

    继承(extends)

    1.继承的定义

    是面向对象的最显著的一个特征。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力
    比如上面的人类,每一个人都有名字和年龄,都会吃。但是具体人又分为男人和女人,又有自己特有的属性和行为,甚至相同的行为,也有千差万别。

    2.继承的语法格式

    class Man extends Person{private String voice;public Man(String name, int age, String voice){super(name, age);             //调用父类中的构造方法,使用super();this.bonous = bonous;}//子类重写父类方法public void eat(){return super.eat() + voice; }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.重载和重写

    重写:表示子类中的方法名、返回值、参数列表和父类当中的方法是一模一样。重载:表示两个方法方法名相同,参数列表不同(返回值不能作为重载的衡量标准)。重写和重载的区别和联系
    • 1)重写发生在具有继承关系两个类之间的;重载既可以发生在具有继承关系的两个类之间,也可以发生于同一个类当中
    • 2)构造方法可以构成重载,但是不可以构成重写
    • 3)子类重写父类的方法实现叫做重写;两个方法方法名相同,参数列表不同叫做重载
    • 4) 静态方法可以被重载但是不能被重写,重写静态方法相当于隐藏父类中的方法

    总结:

    • 1)一个父类,并不是优于子类或者比子类拥有更多的功能,子类比父类功能更加丰富
    • 2)设计类时,一般将一些通用的功能放至父类当中,特有的功能则由子类所持有
    • 3)子类中调用父类的普通方法/构造方法,需要通过super关键字,调用父类中的构造方法,则使用super(), 调用父类中的普通方法则使用super.xxx
    • 4)父类中包含什么样的构造器,子类中也需要包含什么样的构造器
    • 5)父类私有的属性在该类之外是不可以访问的
    • 6)Java当中的继承是单继承,一个Java类只能继承一个父类

    04

    多态

    1.多态的定义

    指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。当一个类A有很多子类B,C,D时,并且子类都重写了父类中的某个方法func(),A a = new B,C,D(),这样的对象称之为向上转型对象,通过它调用func, 不同的向上转型对象就会在调用func时表现不同的行为,这样就称之为多态。

    2.多态的三要素

    • 具有继承关系的两个类
    • 重写
    • 向上转型对象 父类的引用指向创建的子类的对象
    向上转型:
    class Person{      public void method(){      }  }  class Son extends Person{      public void method(){      }  }   Person p = new Son();  p.method();
    3.多态的实现原理

    50f9c1dbecab459b021016c4afcbf9ef.png

    注意事项

    对象转换: 一个对象的引用可以类型转换为另外一个对象的引用
    • 向上转型:当前的子类的对象赋值给父类的引用 隐式转换
    • 向下转型:当把一个父类的实例转换为子类的引用 显式转换
    • instanceOf避免向下转型会出现ClassCastException异常发生
    3736f315dc3083d020cfb4bb3aa2051c.gif

    扫码二维码

    获取更多精彩

    壹伴编辑器

    a1c98e61ee7ef912c3a4f752defc975b.pngf84ce44dd466583c9cb283659d5afa47.giff5dfd8dcc29b8e6511409e6e8cee15ad.png

    点个在看,你最好看

    bd465d9ae73c13525305edeb0086e1f3.png
    展开全文
  • 一、static关键字作用:用来修饰类的成员(属性、方法)static关键字特点:在类加载时就加载(运行、初始化)(类先于对象加载,程序中只加载一次,搞清楚看先后顺序)静态初始化优于对象的静态的成员(属性方法)可以通过...
  • 【目录结构】Java基础1,Java语言的特点2,配置开发环境3,经典HelloWorld3.1 命令行运行Java程序3.2 使用IDEA 运行Java程序4,数据类型&变量4.1 为什么要设计不同种类的数据类型?4.2 数据变量&类型的...
  • 咨询向下,产品向上,殊途同归,都是为了规模化加速数字化转型。图片来源于水印从上图可以看到,如果规模化要加快数字化转型的速度,那么可行的方法就是尽量多的将无序域,混乱域难解域的问题,解构成复杂域简单...
  • 二多态的定义作用 :不同类的对象对同一消息作出不同的响应就叫做多态。多态的作用主要就是解耦。三多态存在的三个条件:1、继承关系 2、子类重写父类方法 3、父类引用指向子类对象四多态在实际应用中的理解:...
  • 这篇文章主要介绍了Java向上转型和向下转型实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下学习向上转型和向下转型怎么没多难,但是为什么那样,我...
  • 学习向上转型和向下转型怎么没多难,但是为什么那样,我搞了很多次没弄明白。没弄明白的原因是平时学习时之看例子,而例子一般都比较简单,没有对象之间的调用,一般就是一个对象调用自己的方法。首先看下怎么...
  • 学习向上转型和向下转型怎么没多难,但是为什么那样,我搞了很多次没弄明白。没弄明白的原因是平时学习时之看例子,而例子一般都比较简单,没有对象之间的调用,一般就是一个对象调用自己的方法。 首先看下怎么...
  • 学习向上转型和向下转型怎么没多难,但是为什么那样,我搞了很多次没弄明白。没弄明白的原因是平时学习时之看例子,而例子一般都比较简单,没有对象之间的调用,一般就是一个对象调用自己的方法。首先看下怎么...
  • 学习向上转型和向下转型怎么没多难,但是为什么那样,我搞了很多次没弄明白。没弄明白的原因是平时学习时之看例子,而例子一般都比较简单,没有对象之间的调用,一般就是一个对象调用自己的方法。 首先看下怎么...
  • 一、认识多态1、方法调用在Java中,方法调用两类,动态方法调用与静态方法调用。(1)静态方法调用是指对于类的静态方法的调用方式,是在编译时刻就已经确定好具体调用方法的情况,是静态绑定的。(2)动态方法调用...
  • 向下转型有什么用? 定义一个Animal父类: public class Animal {  public void eat(){  System.out.println("吃饱了!");  } } 定义一个Bird类继承Animal: public class Bird extends Animal {  ...
  • java多态的向上转型和向下转型有什么好处啊 我直接子类类型对象接收不一样的吗 父类对象接收有什么好处吗 而且此对象只能引用父类和子类共有的方法 多局限啊~~ 向下转型什么意思的忘了 。。。反正迷迷糊糊的...
  • 学习向上转型和向下转型怎么没多难,但是为什么那样,我搞了很多次没弄明白。没弄明白的原因是平时学习时之看例子,而例子一般都比较简单,没有对象之间的调用,一般就是一个对象调用自己的方法。 首先看下怎么...
  • 什么要存在向下转型?因为子类除了父类的方法,也可以自己额外的方法。这些方法是基类所没有的。一旦向上转型,就不能调用子类中的新方法。必须别的方式调用这些新方法。这需要向下。...
  • 向上转型) 举个栗子: //多态的学习 /*存在,三个必要条件:继承,方法重写,父类引用指向对象 * 父类引用指向子类对象后,该父类引用调用子类重写的方法,此时出现多态 * * */ public class Te...
  • 在经过阅读书籍查看别的博主写的关于向上向下转型的博客后,发现题目中这么写完全就是为了出题,它仅仅写Car car = new Benz(); 是一样的,都是向上转型。但是相信还是会人对于向上转型意义不太明白,所以我...
  • java转型和下转型

    2020-02-27 09:49:22
    学习向上转型和向下转型怎么没多难,但是为什么那样,我搞了很多次没弄明白。没弄明白的原因是平时学习时之看例子,而例子一般都比较简单,没有对象之间的调用,一般就是一个对象调用自己的方法。 首先看下怎么...
  • Java向上转型的作用(详细代码介绍)

    千次阅读 多人点赞 2018-05-11 11:04:58
    今天看到一道Java的练习题,题目如下 当时对于主函数中 ... 在经过阅读书籍查看别的博主写的关于向上向下转型的博客后,发现题目中这么写完全就是为了出题,它仅仅写Car car = new Benz(); ...
  • 什么使用上转型?因为当一个父类很多子类,子类都重写了父类的方法并加以使用。这时候,如果要在之前代码让你其他子类来实现,就变得很简单,...为什么向下转型?因为当我们拿到一个父类,我们想把它当作我们需
  • 跟汤老师学Java笔记:总结多态 完成:第一遍 1.实现多态的条件是什么? (1).继承的存在(继承是多态的基础,没有...父类引用变量指向子类对象(向上转型) 2.多态的优点是什么 减少代码量 提高可扩展性和可维护性 ...
  • java中多态polymorphism,向上转型和动态方法调度有什么用? java中什么叫多态,动态方法调度(dynamic method dispatch)? java中downcast向下转型到底有什么用? 举例说明! java中如何使用派生类指针指向基类,即...

空空如也

空空如也

1 2
收藏数 34
精华内容 13
关键字:

java向上转型和向下转型有什么用

java 订阅