多态是面向对象编程中的一个重要概念,指的是同一类型的对象在不同的情况下可以呈现出不同的行为。 在多态中,通过将父类对象赋值给子类对象,可以实现在不改变原有代码的情况下,根据不同的对象类型调用相应的方法。这样可以提高代码的复用性和灵活性。 多态有两种形式:编译时多态(静态多态)和运行时多态(动态多态)。 编译时多态是指通过函数重载和运算符重载实现的多态,编译器在编译阶段根据参数的不同,选择调用不同的函数或运算符重载方法。这种多态是在编译阶段进行决策的。 运行时多态是指通过继承和虚函数实现的多态,编译器在编译阶段无法确定对象的具体类型,只能确定类型为父类,而在运行阶段根据对象的实际类型调用相应的函数。这种多态是在运行阶段进行决策的。 多态的好处是可以提高代码的可扩展性和可维护性。比如,当需要增加一个新的子类时,只需要重写相应的方法,而不需要修改已有的代码。此外,多态还可以实现接口的统一,使得不同的对象可以通过相同的接口来进行操作。 总结起来,多态是面向对象编程中的一种重要机制,通过将相同类型的对象以不同的形式表现出来,实现了代码的复用和灵活性,提高了代码的可扩展性和可维护性。 package lesson13; //多态,同样的消息被不同的对象接收产生不同的行为 public class Animal { public void cry(){ System.out.println("动物叫声"); } } class Cat extends Animal{ @Override public void cry(){ System.out.println("喵喵叫"); } } class Dog extends Animal{ @Override public void cry(){ System.out.println("汪汪叫"); } } class Test1{ public static void main(String[] args) { //多态的条件是 //1.要有继承 2.要有重写 3.要有向上转型 Animal a1 = new Animal(); Animal a2 = new Cat(); Animal a3 = new Dog(); a1.cry(); a2.cry(); a3.cry(); }
向上转型(Upcasting)是指将一个子类对象的引用赋值给父类对象的引用的过程。简单来说,就是将子类对象当做父类对象来使用。
向上转型的语法如下:
父类类型 对象名 = new 子类类型();
例如,假设有一个动物类 Animal 和一个狗类 Dog,狗是动物的子类。可以进行向上转型如下:
Animal animal = new Dog();
这样做的好处是可以通过父类的引用来操作子类的对象,提高了代码的灵活性。在向上转型后,只能访问到父类中定义的方法和成员变量,而无法访问到子类中新增的方法和成员变量。
下面是一个示例代码:
```
class Animal {
public void eat() {
System.out.println("动物吃东西");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("狗叫");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Dog(); // 向上转型
animal.eat(); // 可以调用父类的方法
// animal.bark(); // 无法调用子类的方法
}
}
```
在上述代码中,通过向上转型将 Dog 对象赋值给 Animal 对象。然后使用 Animal 对象来调用 eat() 方法,输出结果为 "动物吃东西"。而如果尝试调用 bark() 方法,会导致编译错误。
需要注意的是,向上转型是自动进行的,无需显式地进行类型转换。同时,向上转型是安全的,不会出现类型转换异常。而在运行时,实际执行的仍然是子类对象的方法。
向下转型(Downcasting)是指将一个父类对象引用转换为一个子类对象引用的过程。 在Java中,如果一个父类对象的引用指向了一个子类对象,那么可以通过强制类型转换将父类对象引用转换为子类对象引用。
下面是一个示例:
```java
class Animal {
public void eat() {
System.out.println("Animal is eating");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Dog();
// 向下转型
Dog dog = (Dog) animal;
dog.eat();
dog.bark();
}
}
```
在上面的例子中,我们首先创建了一个Animal对象,并用一个Animal类型的引用变量 animal 引用它。然后,我们创建了一个Dog对象,并将其赋给animal变量。这是合法的,因为Dog是Animal的子类。
接下来,我们使用向下转型将animal引用转换为Dog类型,并将其赋给dog变量。这样,我们就可以调用Dog类特有的方法bark()。
需要注意的是,向下转型在编译时是合法的,但在运行时可能会抛出ClassCastException异常。因此,在进行向下转型时,我们需要确保父类对象引用确实指向了子类对象。可以使用 instanceof 运算符来检查对象引用是否是某个类的实例。
public class Demo { //引用类型之间也存在类型转换,称之为对象转型 //对象转型分为向上转型和向下转型 public static void main(String[] args) { //向上转型是父类的引用变量指向子类对象(自动转换) //实质就是子类中小的父类对象给父类的引用变量赋值 //第一种写法 Student s1 = new Student(); Person p1 = new Person(); p1 = s1; //第二种写法 Person p2 = new Student(); //向下转型是子类的引用变量指向父类对象(强制转换) //要想向下转型,必须要保证父类对象在子类对象之中,而唯一能保证的就是向上转型 Student s3 = new Student(); Person p3 = new Student(); s3 =(Student) p3; } }
class Animal1{ private String name; public Animal1(String name){ this.name=name; } public void cry(){ System.out.println("动物叫声"); } } class Cat1 extends Animal1{ private String eyeColor; public Cat1(String name,String eyeColor){ super(name); this.eyeColor=eyeColor; } @Override public void cry(){ System.out.println("喵喵叫"); } } class Dog1 extends Animal1 { private String furColor; public Dog1(String name,String furColor){ super(name); this.furColor=furColor;} @Override public void cry(){ System.out.println("汪汪叫"); } } public class Girl { private String name; private Animal1 pet; public Girl(String name, Animal1 pet) { this.name = name; this.pet = pet; } public static void main(String[] args) { Cat1 c = new Cat1("tom", "gary"); Dog1 d = new Dog1("kaier", "black"); Girl l1 = new Girl("Rose", c); Girl l2 = new Girl("Grace", d); l1.pet.cry(); l2.pet.cry(); } }
public class Test { public static void main(String[] args) { Person p = new Person(); Student s = new Student(); //instanceof判断一个对象是否由该类创建的 System.out.println(p instanceof Person); System.out.println(p instanceof Student); System.out.println(s instanceof Person); System.out.println(s instanceof Student); } }