今天,在阅读ArrayList源码的时候发现一个很有意思的注释。代码中的注释意思是预防c.toArray不按照预期返回Object[],所以才有下面的复制操作。我用代码模拟一次。首先,我用ArrayList的toArray方法,看看返回值是什么类型。运行结果为[Ljava.lang.Object;@42a57993。可以看到返回值是Object[]。
然后我新建一个类,使其继承ArrayList,重写ArrayList的toArray方法。由于这里是测试,因此返回值就写死了,大家不要在意。
使用我们的MyList运行测试方法返回结果会是什么呢?答案是[Ljava.lang.String;@75b84c92。返回了String[]。由此发现Java重写的一个大坑。我们知道Java重写的其中一个条件是父类和子类定义的方法必须具备同样的返回值,参数列表和方法名,于是我写了一段测试代码。B和C各自继承了抽象类A,重写了getNumber方法,然而B和C的getNumber方法返回值却和A定义的不同,并且还能运行出结果,这是为什么呢?我用javap反编译了class文件,输出的字节码如图所示:发现20行和30行正是对应我们代码中调用B和C的getNumber方法。但是其字节码的方法签名为抽象类A的getNumber。仔细想想,发现这种方式其实并没有问题,因为重写是发生在运行时,在编译的时候只能确定方法签名,而只有在运行的时候才能决定最终调用方法的子类对象。因此我们可以得出一个结论:方法重写并不是一定要一样的返回值,只要子类与父类的方法返回值也属于子类和父类的关系,那么方法重写也会成功。
拜托,别再问我MySQL事务的实现原理了!!!
推荐:排查Java应用线上问题工具汇总。
经验:谷歌大佬告诉你,如何写一份面试官爱不释手的简历!
点我,查看更多精彩文章。