Java对象类型向上转型和向下转型
首先,我们要知道基础知识类是什么?类是具有相同特征和行为的事物,Java中的继承机制使得一个类可以继承另一个类,继承的类称为子
类,被继承的类称为父类。子类继承了父类 ,拥有了父类的特征,具有了父类的行为,但是子类却不能直接使用父类的private修饰的属性和
方法,虽然可以通过调用父类的public声明的get方法来获取父类的private属性,但父类的private方法还是无法访问。子类虽然拥有了父类的
方法,但是不满足自己当前类的行为方式(方法体中的逻辑不同),由此引出子类可以对继承的方法进行重写。(子类拥有父类中的方法,
但是方法体需要根据自己类的特征重新书写-------------方法重写 (@Override))
其次,我们要知道为什么会出现向上转型和向下转型?这点可以延伸到基本数据的大转小和小转大,对应到类中就是当父类转换为子类的
时候就是向下转型,反之则是向上转型。(父类在上,子类在下继承时的位置关系)
表示的范围:
父类,通用特征,只要满足这个类的特征的事物都可以表示 Animal
父类表示的数据范围大----大范围数据
子类,在父类基础上做的扩展 (在父类的基础上 增加了自己的特征)Cat
子类表示的数据范围小----小范围数据
向上转型(小范围转大范围)
小范围转大范围 ----------------------规则 :直接转---------向上转型
byte a = 1;------------------------------Cat cat = new Cat();
long b = a;------------------------------Animal a = cat;
long b =1;-------------------------------Animal a = new Cat();
(小范围是子类 ,大范围是父类,子类转父类-------向上转型)
向上转型,对于父类隐藏了自己的功能(自己的功能还有,就是父类不能使用)
应用场景:定义多个方法,实现逻辑,参数不能写具体的某一个类型 为了进行简化,使用父类进行参数的接收
动态绑定:程序运行时,找到变量中存放对象的实际类型,执行实际类型或者实际类型中的方法
向上转型两种使用方式
1、赋值向上转型
父类Animal中有eat()方法,子类Cat中有继承重写的eat()方法和属于它自己的play()方法。
//父类代码
public class Animal {
//创建变量
private Integer height=0;
private Integer weight=0;
//定义带参构造方法需要定义一个默认的无参构造方法
//防止别人在使用你这个方法时自己不带参数的new对象
public Animal(){
// this(50,50);
// System.out.println("这是无参构造方法");
}
//定义一个带参数的构造方法,它必须和类同名
public Animal(Integer height,Integer weight) {
System.out.println("这是带参构造方法");
//为变量赋值
//this.height为这里的局变量 height为传入的参数
this.height = height;
this.weight = weight;
}
public void eat(){
System.out.println("动物吃了东西");
}
//获取变量的值
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
//获取变量的值
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
}
//子类代码
public class Cat extends Animal{
private String color;
private Integer varieties;
public Cat() {
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void play(){
System.out.println("猫在毛线球!");
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Integer getVarieties() {
return varieties;
}
public void setVarieties(Integer varieties) {
this.varieties = varieties;
}
}
实例化Cat类,并新建一个Animal类的引用变量引用该实例,调用实例的eat()方法,结果为:
//控制类
public class Control
{
public static void main( String[] args )
{
Animal animal = new Cat();
animal.eat();
//animal.play();
}
}
尝试调用Cat类自身的方法play(),结果报错,这也就是之前说的,向上转型之后,父类引用变量可以访问子类中属于父类的属性和方法,但是不能访问子类独有的属性和方法。
注意:
方法重写时,访问权限修饰符,子类的大于等于父类的,如果进行方法重写 方法不能被
private修饰。
2、传参向上转型
实例化Cat类,调用test()方法传入刚刚实例的Cat类对象,结果为:
//控制类
public class Control
{
public static void main( String[] args )
{
Cat cat = new Cat();
test(cat);
}
public static void test(Animal animal){
animal.eat();
}
}
向下转型
大范围转小范围 ----------------------规则 :强制类型转换---------向下转型
long a = 1;------------------------------Animal a = new Animal();
byte b=(byte)a;-----------------------------Cat c = (Cat)a;
(小范围是子类,大范围是父类,父类转子类-------向下转型)
向下转型,强制要求父类一定要拥有子类的特征,但是父类没有如果强制转换,出现强制转换异常,如果要避免异常,可以先进行判断 (对
象 instanceof 类型)再进行转换.如果要向下转型成功 必须建立在向上转型基础上。
向下转型
子类Dog中有继承重写的eat()方法和属于它自己的play()方法。
//子类
public class Dog extends Animal {
private String color;
private Integer varieties;
public Dog() {
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
public void play(){
System.out.println("狗在抓挠沙发!");
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Integer getVarieties() {
return varieties;
}
public void setVarieties(Integer varieties) {
this.varieties = varieties;
}
}
新建一个返回值类型为Animal的test含参测试方法,传入参数具体值,给animal赋上实际的类型(先向上转型),最后根据实际类型进行的转换(再向下转型),结果为:
// 1、先做到了向上转型
public static Animal test(int num){
if (num==0){
return new Cat();
}else{
return new Dog();
}
}
//2、传入参数具体值是0,animal的实际类型是Cat类型,可以进行强制类型转换
Animal animal = test(0);
//根据实际类型进行的转换 -----------向下转型
if (animal instanceof Cat){
Cat cat = (Cat)animal;
cat.eat();
}else if(animal instanceof Dog){
Dog dog = (Dog)animal;
dog.eat();
}else{
System.out.println("类型不匹配");
}
//如果想成功的进行向下转型,一定要建立在向上转型基础上