向上转型 向下转型

转型

转型依据数据类型分为两种,一种是基本数据类型上的转型,一种是引用数据类型的转型

1 基本数据类型依据

byte/char ——> int ——> long ——> float ——> double

的顺序可以自动向上转型,反之向下强制转型(由于窄化转型仅仅是丢弃最低位N个字节的内容,可能会发生精度丢失)

2 引用数据类型:数组 和 对象
其中 数组具有协变性数组的协变性

我们这里主要面向引用类型。。。。

向上转型

引用类型向上转型到父类(extends)以及实现的接口(implements)
向上转型是安全的,不需要强制转换
因为符合子类的对象一定符合父类

        String[] s1 = new String[]{"111"};
        Object[] obj1 = s1;//不需要强转

        Object[] s1 = new String[]{"123"};//向上转型定义,父类引用指向子类对象

引用类型向上转型到父类(extends)以及实现的接口(implements),其中优先级父类大于接口,当没有父类时可以转换成接口,在接口之间优先级相同(如果出现他实现的多个接口,引用类型会因为向上转型模糊而拒绝编译),故在不能出现参数列表仅仅是两个同等级的接口不同的重载方法

以重载为例

public class ArrayList<E> extends AbstractList<E>
      implements List<E>, RandomAccess, Cloneable, java.io.Serializable
      //ArrayList实现ListSerializable接口
public class Test {

   private static void println(int a, AbstractList obj){
        System.out.println("AbstractList");
    }
    private static void println(int a,List list){
        System.out.println("List");
    }
    private static void println(int a, Serializable serializable){
        System.out.println("serializable");
    }

    public static void main(String[] args) {
        println(1new ArrayList());
}
}
//此时编译不通过,编译器提示两个方法都匹配不能指定
//注意这里,即便优先级应该是给父类,但是方法中只要是有两个接口,他就没有办法排列优先级,就无法编译

当然向上转型还可以转换成父类的父类,父类的接口等等。。当然优先级就会减弱

向下转型

向下转型是不安全的,因为不能保证存放在父类中的都是要转换的子类
除了要求强制转换
还有:
1 定义声明时要指向父类引用指向的是子类的实例对象(以保证转换时类型安全),也就是说在向下转型前必须先向上转型
2 只能转换成要转换的子类(自己的实际类型),不能转成其他的,也就是说Object声明时引用的是String实例就不能向下转型成Integer(这点十分重要,所以向下转型只能转成自己的实际类型,转型的范围是固定的)

        Object[] obj2 = new Object[]{"123"};
        String[] s2 = (String[])obj2;
        //报异常 [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

        //正确用法
        Object[] obj3 = new String[]{"1223"};//先向上转型
        String[] s3 = (String[]) obj3;//再强制向下转型

那么转型带给我们有什么优势嘞

向上转型

上下转型中要注意到一点:
向上转型中会忘记对象类型
也就说子类中单独定义而父类中没有的方法将无法访问,子类重写的方法也无法调用,可以调用的只有父类自己的方法

使用场景:
例如目前有父类Object 子类String Integer
现在有一个方法function,要求传入参数Object的子类们
在普通情况下我们需要定义两个方法,一个传String 一个传Integer

public void function(String s){}
public void function(Integer i){}

我们访问时也是

function(new String());
function(new Integer());

如果使用向上转型,我们在定义这个方法的时候使用父类作为参数类型

public void function(Object o);

访问时,因为向上转型是自动非强制的,我们都不需要做其他的操作,直接调用就可
向上转型在Java中运用超级多,源码中Object o方法一大堆
向上转型可以节省大量代码

function(new String());
function(new Integer());

向下转型

上面说过了,向下转型之前必须先要向上转型,那这样的话为什么还要向下转型
向下转型重点在于调用子类自己的方法

使用场景:
既然我们说向下转型前必须先向上转型,那就是说向下转型是为了能更好地服务向上转型的,不会有单独只为了使用向下转型而使用的情况(要不我为啥不用自己的实例)
So,在使用向上转型的时候,子类丧失了自己的类型,然而我们还需要调用子类中自己的方法,怎么办呢,yeah 向下转型

这里就不举例子了,还蛮好理解的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值