java对象转型(向上转型和向下转型)
向下转型和向上转型是什么意思
基本数据类型,转换可以通过隐性和显性(强制)类型转换,例如float类型转成int类型,把double类型转成float类型。
对象类转型的话,就需要用到向上转型或向下转型,
向上转型表现:调用子类重写父类的方法
向下转型表现:一个对象,在经过向上转型行为后才可以进行向下转型,从而可以调用到子类的方法。
大体目的是区分子父类对于方法的调用、节省代码量、减少冗余。
向上转型和向下转型的基本公式:
向上转型: Father f = new Son();
Father是父类或接口,son是子类。
//直接转换,加不加括号强转都无所谓
向下转型: Son s = (Son)f;
//强制类型转换,一定要通过加括号强转,
公式上也有点类似于基本数据类型的转换。
例子:
向上转型:
假设Employee类包含一个Salary()方法
public class Employee {
public void identity() {
System.out.println("员工");
}
}
Employee类有一个子类Manager,Manager类不但继承了Employee类的Salary()方法,同时也有一个自己的方法。
class Manager extends Employee{
public Manager() {
super();
}
//重写父类的Salary方法
public void identity() {
System.out.println("打工人");
}
public void position() {
System.out.println("管理者");
}
}
构造一个对象,实例化Manager类,引用类型是Employee类。调用identity()方法,从而达到子类对象向上转型(引用类型是父类)。
注意:只能调用子类重写父类的方法,如果调用的是子类独有的方法,是会报错的!
public class ManagerTest {
public static void main(String[] args) {
Employee emp=new Manager();
//等同:Employee emp=(Employee)new Manager();
emp.identity(); //打工人
emp.position(); //报错,父类没有定义到该方法
}
}
向上转型的目的:
减少重复代码,使代码变得简洁。
提高系统扩展性。
例子:假设Employee类中有很多子类Director、Leader,…,main类中有work方法需要调用到Employee类的子类引用类型变量,不用向上转型,就需要反反复复的给每一个方法事先写好引用类型。
public class Employee {
public void work() {
System.out.println("此处为空!");
}
}
//假如子类有Director、Leader,........
class Director extends Employee{
public void work() {
System.out.println("技术总监!");
}
}
class Leader extends Employee{
public void work() {
System.out.println("组长!");
}
}..............
public class EmployeeTest {
public static void main(String[] args) {
work0(new Director());
work1(new Leader()); ............
}
public static void work0(Director director){
director.work();
}
public static void work1(Director director){
director.work();
}.................
}
运用向上转型的方法:
注意:向上转型前提是继承和重写过父类已有的方法
public class EmployeeTest {
public static void main(String[] args) {
work2(new Director());
work2(new Leader());.............
}
public static void work2(Employee e){
e.work();
}
}
代码量上显得就少了很多,且可拓展性也明显增强,有要到新的引用变量只需要在后面构造就好了。
向下转型:
在上面例子的基础上,强制类型转换对象emp,转为Manager引用类(子类),再赋给一个变量mana,就实行向下转型的行为,从而mana就可以调用到Manager(子类)类独有的方法。
public class ManagerTest {
public static void main(String[] args) {
Employee emp=new Manager();
//等同Employee emp=(Employee)new Manager();
emp.identity(); //打工人
//emp.position();
Manager mana=(Manager)emp;
mana.position(); //管理者
}
}
当然,也可以用Manager mana=new Manager()来重新new一个对象,但这样是需要在栈中重新添加mana对象,即增加了冗余,同时也没有强制类型转换再赋值处理的快(因为栈中已经有一个emp对象)。
ps:听学长说很少有人会用到向下转型。
关于向下转型的补充1:
前提:不是所有的对象都可以向下转型,只有当这个对象原本就是子类对象通过向上转型得到的,才可以进行。
假设Clerk类是Employee类的另一个子类
class Clerk extends Employee{
public void identity() {
System.out.println("打工人2");
}
public void position() {
System.out.println("普通职工");
}
}
实例化Manager类,构造对象emp,引用类型是Employee类。对Clerk类的变量cle进行向下转型,虽然编译通过,但运行是会报错的。
Employee emp=new Manager();
Clerk cle=(Clerk)emp;
cle.position();
关于向下转型的补充2:
假设Employee类new的一个emp2对象,那么编译的时候也不会报错,运行时会出现java.lang.ClassCastException错误。
所以进行向下类型转换的时候,建议用到instabceof关键字判断,避免出面调用到兄弟类或父类new的对象。
Employee emp2=new Employee();
if(emp2 instanceof Manager){
//instanceof检测emp对象是否关于Manager类
Manager mana2=(Manager)emp2;; //判断失败,不会进入语句
man2a.position();
}