(一)泛型-Java的多态-Java向下转化和向上转化

本文深入探讨Java中的多态概念,包括特殊多态、参数化多态及子类型多态等不同形式。重点介绍子类型多态,解释其实现机制、必要条件及应用场景,并通过实例演示向上转化与向下转化的过程。

起先向单刀直入的解决 Java 泛型的相关概念和应用,发现有一些概念不是很理解,于是发现是被卡在“协变和逆变”的概念上了,接着看,终于发现根源是在 Java 的多态。

Java 的多态
Java 的多态分为三种情况
  • 特殊多态(Ad hoc polymorphism),此类下又包含函数重载(function overloading)以及类型转换多态(coercion polymorphism)
  • 参数化多态(Parameteric polymorphism),对应到Java里即泛型。
  • 子类型多态(Subtyping polymorphism),子类型多态,即通过类型继承关系获得的多态。

    对于第三种情况有三个必要条件:

    • 要有继承
    • 要有重写
    • 父类引用指向子类对象,这里涉及到向上转化,比如 Number n=new Integer(1);

    依旧是针对第三种情况:

    • 子类只能覆盖重写父类的非静态成员方法,常量(不管是否是静态的)、静态成员方法都是不可被覆盖的,而且,这种方式下,子类特有的方法不可以被直接访问。
Java 的向下转化和向上转化

我们以简单的代码来说明。
背景内容:子类 extends 父类,子类覆盖重写父类的普通成员方法,子类有一个自己特有的方法。
然后,父类 f=new 子类();
这个时候,f 是可以运行子类中的方法的,但是不能调用子类自己特有的方法,即虽然我们实例化的是子类,但是所能
调用的方法被局限在了父类的成员方法中,这个过程就是向上转化,Java 的多态是基于这一过程的。至于向下转化,如果通过声明父类而以子类实例化得到了对象a,把对象a强制类型转化为子类型,并赋值给一个新声明的子类型,这样也是可以的,而且子类型中自己特有的方法也可以调用了,类似于把父类对象转化为了子类型的对象,即向下转化。

再一个,向下转化并不体现多态,这只是一个强制转化的过程,而且,只有父类实例化对象是子类型时,才可能成功,换而言之,如果一个父类实例化对象是父类本身,其就不可以再被强制转化为子类对象了。

我们以简单的代码来说明,
背景内容:子类 extends 父类,子类覆盖重写父类的普通成员方法,子类有一个自己特有的方法。
然后,父类 f=new 子类();
这个时候,f 是可以运行子类中的方法的,但是不能调用子类自己特有的方法,即虽然我们实例化的是子类,但是所能
调用的方法被局限在了父类的成员方法中,这个过程就是向上转化,Java 的多态是基于这一过程的。至于向下转化,如果通过声明父类而以子类实例化得到了对象a,把对象a强制类型转化为子类型,并赋值给一个新声明的子类型,这样也是可以的,而且子类型中自己特有的方法也可以调用了,类似于把父类对象转化为了子类型的对象,即向下转化。

再一个,向下转化并不体现多态,这只是一个强制转化的过程,而且,只有父类实例化对象是子类型时,才可能成功,换而言之,如果一个父类实例化对象是父类本身,其就不可以再被强制转化为子类对象了。

class father{  
    public void m1(){  
        System.out.println("father.m1");  
    }  
}  
class son extends father{  
    @Override  
    public void m1(){  
        System.out.println("son.m1");  
    }  

    public void m2(){  
        System.out.println("son.m2");  
    }  
}  
public class JavaTest {  
    public static void main(String[] args) {  
        father f=new son();//向上转化  
        f.m1();//打印结果为 son.m1  

        son s=(son) f;//向下转化-强制转化的一种  
        s.m2();//打印结果为 son.m2   

    }  
}  
### 类的多态实现 在 Java 中,类支持多态行为的方式主要体现在通过继承接口实现来扩展类的功能。类的多态性允许在不同的子类中使用不同的类参数,同时保持统的接口设计。这种多态性可以通过类的继承接口实现来体现。 #### 类的继承多态 类可以通过继承来实现多态行为。子类可以指定具体的类参数,也可以继续使用。例如: ```java public class Box<T> { private T item; public void setItem(T item) { this.item = item; } public T getItem() { return item; } } public class IntegerBox extends Box<Integer> { public void printItem() { System.out.println("Integer Item: " + getItem()); } } public class StringBox extends Box<String> { public void printItem() { System.out.println("String Item: " + getItem()); } } ``` 在使用时,可以通过父类引用指向子类实例,从而实现多态行为: ```java public class Main { public static void main(String[] args) { Box<?> box1 = new IntegerBox(); box1.setItem(10); System.out.println(box1.getItem()); Box<?> box2 = new StringBox(); box2.setItem("Hello"); System.out.println(box2.getItem()); } } ``` 在这个例子中,`Box<?>` 是父类引用,指向了 `IntegerBox` `StringBox` 的实例,实现了多态性[^3]。 #### 接口多态 接口同样支持多态行为,通过实现接口并指定不同的类参数来实现。例如: ```java public interface Container<T> { void add(T item); T get(); } public class IntegerContainer implements Container<Integer> { private Integer item; public void add(Integer item) { this.item = item; } public Integer get() { return item; } } public class StringContainer implements Container<String> { private String item; public void add(String item) { this.item = item; } public String get() { return item; } } ``` 在使用时,可以通过接口引用指向不同的实现类实例: ```java public class Main { public static void main(String[] args) { Container<Integer> intContainer = new IntegerContainer(); intContainer.add(20); System.out.println(intContainer.get()); Container<String> stringContainer = new StringContainer(); stringContainer.add("World"); System.out.println(stringContainer.get()); } } ``` 这种方式展示了接口的多态性,允许通过统的接口调用不同的实现类[^1]。 #### 类的多态擦除 Java是通过类擦除来实现的,这意味着在运行时,类的类信息会被擦除。因此,在实现类的多态时,需要注意类擦除带来的限制。例如,不能直接创建数组,也不能在运行时获取具体的类参数信息。 尽管如此,通过继承接口实现,类仍然可以在编译时提供类安全多态行为。例如,通过使用通配符(`?`)有界类参数(如 `T extends Number`),可以实现更灵活的多态行为[^4]。 #### 示例:类的多态行为 下面是个完整的示例,展示了如何通过类实现多态行为: ```java public abstract class Animal { public abstract void speak(); } public class Dog extends Animal { public void speak() { System.out.println("Woof!"); } } public class Cat extends Animal { public void speak() { System.out.println("Meow!"); } } public class AnimalBox<T extends Animal> { private T animal; public void setAnimal(T animal) { this.animal = animal; } public T getAnimal() { return animal; } public void makeSound() { animal.speak(); } } ``` 在使用时,可以通过 `AnimalBox` 的实例来调用不同子类的 `speak` 方法: ```java public class Main { public static void main(String[] args) { AnimalBox<Dog> dogBox = new AnimalBox<>(); dogBox.setAnimal(new Dog()); dogBox.makeSound(); // 输出: Woof! AnimalBox<Cat> catBox = new AnimalBox<>(); catBox.setAnimal(new Cat()); catBox.makeSound(); // 输出: Meow! } } ``` 在这个例子中,`AnimalBox<T>` 是类,通过继承 `Animal` 类的子类实例,实现了多态行为[^5]。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值