重载的最终效果就是调用同一个方法名称,却可以根据传入参数的不同而得到不同的处理结果,这其实就是多态性的一种体现。
class Person
{
public void fun1()
{
System.out.println("1.Person{fun1()}") ;
}
public void fun2()
{
System.out.println("2.Person{fun2()}") ;
}
}
// Student类扩展自Person类,也就继承了Person类中的fun1()、fun2()方法
class Student extends Person
{
// 在这里复写了Person类中的fun1()方法
public void fun1()
{
System.out.println("3.Student{fun1()}") ;
}
public void fun3()
{
System.out.println("4.Studen{fun3()}") ;
}
}
class TestJavaDemo1
{
public static void main(String[] args)
{
// 此处,父类对象由子类实例化
Person p = new Student() ;
// 调用fun1()方法,观察此处调用的是哪个类里的fun1()方法
p.fun1() ;
p.fun2() ;
}
}
从程序的输出结果中可以发现,p是父类的对象,但调用fun1()方法的时候并没有调用其本身的fun1()方法,而是调用了子类中被复写了的fun1()方法。之所以会产生这样的结果,最根本的原因就是因为父类对象并非由其本身的类实例化,而是通过子类实例化,这就是所谓的对象的多态性,即
子类实例化对象可以转换为父类实例化对象。
这里有两个概念:
1、向上转型:
在上面范例中,父类对象通过子类对象去实例化,实际上就是对象的向上转型。向上转型是不需要进行强制类型转换的,但是向上转型会丢失精度。
2、向下转型:
与向上转型对应的一个概念就是“向下转型”,所谓向下转型,也就是说父类的对象可以转换为子类对象,但是需要注意的是,这时则必须要进行强制的类型转换。
汽车(父类) 《-》 跑车(子类)
跑车是汽车(无需进行强制类型转换)
汽车->跑车(需要进行强制类型转换)
一、向上转型可以自动完成;
二、向下转型必须进行强制类型转换。
注意:
并非全部的父类对象都可以强制转换为子类对象。请看下面范例:
class TestJavaDemo2
{
public static void main(String[] args)
{
// 此处,父类对象由自身实例化
Person p = new Person() ;
// 将p对象向下转型
Student s = (Student)p ;
p.fun1() ;
p.fun2() ;
}
}
由程序可以发现,程序中Person对象p是由Person类本身实例化的,下面将Person对象p强制转换为子类对象,这样写在语法上是没有任何错误的,但是在运行时可以发现出了异常,这是为什么呢?为什么父类不可以向子类转换了呢?其实这点并不难理解,读者可以想一下在现实生活中的例子,假如你今天刚买完一些生活用品,回家的时候在路上碰见一个孩子,这个孩子忽然对你说:“我是你的儿子,你把你的东西给我吧!”,这个时候你肯定不会把你的东西给这个孩子,因为你不确定他跟你是否有关系,怎么能给呢?那么在这程序中也是同样的道理,父类用其本身类实例化自己的对象,但它并不知道谁是自己的子类,那肯定在转换的时候会出现错误,那么这个错误该如何纠正呢?只需要将第3的代码修改成如下形式即可:
Person p = new Student() ;
这个时候相当于是由子类去实例化父类对象,也就是说这个时候父类知道有这么一个子类,也就相当于父亲知道了自己有这么一个孩子,所以下面再进行转换的时候就不会再有问题了。
instanceof关键字
instanceof的作用:
1. 判断一个类是否实现了某个接口
2. 判断一个实例对象是否属于一个类。
instanceof的语法格式为:
对象 instanceof 类(或接口)
它的返回值是布尔型的,或真(true)、或假(false)。