Java中的多态

多态也就是一个名字多中状态,这就叫多态。

例如,人(老师,学生),老师和学生都是人,也就是人现在有两种状态。

多态有四种类型:

        1,基本类型的多态。例如, byte,int,double,float,long。例如2,我们可以把它当作int类型,byte类型,long类型,还可以把其当作double类型。2说成是double类型的时候,本质上是存在自动类型转换的。

        2,方法的多态(显然,重载就是一个最好的例子)。

        3,类或者接口的多态。定义一个父类的引用,让这个引用指向一个new出来的子类对象,这就是类或者接口的多态。

        4,参数传递过程中的多态,这是最重要的一种,是引用类型和基本类型的结合使用。

多态主要用来设计方法的参数和返回值的类型。

类多态的前提条件是继承(这也是继承最重要的应用之一)。

Person p = new Student();


这句代码在执行的时候,会在栈内存中放一个Person类型的引用,然后new一个Student对象,然后让这个引用指向这个对象。这是典型的发生多态的一个代码。因为引用的类型和Student对象的类型是不一样的啊。栈和堆内存类型不相同的时候,究竟以谁作为真正的类型呢?sun公司是这样规定的,我们把p当作父类的对象来用,即把子类的对象当做父类的对象来用。这样就会发生一个有趣的现象:

         发生多态时候,父类中的定义的东西都可以使用,子类中定义的不能直接使用;

//发生多态时候 需要注意的几点
public class Student extends Person{
	private int id;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	public void test(){
		System.out.println("Student");
	}
	public static void test1(){
		System.out.println("Student");
	}
	public static void main(String[] args){
		Person p = new Person();   //无多态
                     Person p1 = new Student(); //多态       //这里一定发生的自动类型的转换
		Student s = new Student(); //无多态
		
		p1.setAge(13);
		//p1.setId(2);     //发生多态时候,子类中定义的不能直接使用但是分配内存,所以有使用的方法
		p.setAge(13);
		//p.setId(2);      //  Person没有setId()方法
		s.setAge(13);
		s.setId(2);
		
		p1.test();         //执行子类中从写的方法
		p1.test1();        //static方法被执行的是父类的 
	}
}

public class Person {
	private int age;
	private String name;
	public Person(){
		
	}
	public Person(int age, String name){
		this.setAge(age);
		this.setName(name);
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void test(){
		System.out.println("Person");
	}
	public static void test1(){
		System.out.println("Person");
	}
}

public class TestCast {
	public static void main(String[] args){
		Person p1 = new Person();
		Person p2 = new Student();
		//Student s1 = (Student)p1;    //内存中不存在的时候,这个转换时一定不会成功的
		//Student s2 = (Student)p2;    //因为内存中存在getId(),所以可以发生类型转换

//System.out.println(s1.getId()); if(p1 instanceof Student){Student s1 = (Student)p1;}if(p2 instanceof Student){Student s2 = (Student)p2;System.out.println(s2.getId());}if(p2 instanceof Person){ //instanceof兼容父类的类型System.out.println("is Person");}if(p2 instanceof Student){System.out.println("is Student");}if(p2 instanceof Object){System.out.println("is Object");}//System.out.println(p2.getId());//就是在内存中重新定义一个子类类型的对象 //Student s1 = (student)p1;//Student s2 = (Student)p2;//以上两句在编译时候不会报错,但是确实存在非法的类型转换,如何保证类型可以发生转换呢?使用instanceof 关键字来判断对象的类型}}


 解决多态发生的时候,使用子类中的属性和方法的问题。其实多态说得彻底一点就是类型转换。由于发生多态的时候,我们创建的子类的对象赋值给父类的引用,这是我们把这个引用当作了父类的对象来用,但是创建子类对象时候,子类中的一些属性和方法都是存在对内存当中。我们却不能直接用这个父类的引用来访问子类的一些属性和方法。解决这个问题,我们引入了抽象类型的强制类型转换。其实,发生多态时候,进行强制类型转换是一种还原行为,即原来是什么,还原成什么。

引用类型的强制类型转换只发生在子类与父类之间。(1)子类到父类的转换属于自动类型转换;(2)父类到子类的类型转换需要进行强制类型转换。

                   Person p1 = new Person();
		 Person p2 = new Student();
		//Student s1 = (Student)p1;    //内存中不存在的时候,这个转换时一定不会成功的
		//Student s2 = (Student)p2;    //因为内存中存在getId(),所以可以发生类型转换
正如上面发生强制类型转换的两句,在编译的时候能通过,不会报错和警告。第一句的强制类型转换确实不是合法的。如何在才能保证强制类型转换的正常进行呢?这里引入instanceof关键字。这个关键字的作用是用来判断对象的类型的(注意判断的是对象的类型而非引用的类型,这是有区别的)。instanceof在判断对象的类型的时候,是兼容父类的,所以说,在判断一个对象的类型的时候,这时只告诉我们是否可以发生强制类型转换,但是不能告诉我们对象确切的类型。
发生多态,子类重写的时候,new出来的对象,在执行一些操作的时候。对应static方法是执行父类的,而非static方法则执行的是子类的。
### Java多态的具体表现形式 #### 接口实现多态Java中,除了通过继承来实现多态外,还可以利用接口达到相同的效果。一个类能够实现多个接口,并且不同类可以各自实现相同的接口却表现出各异的行为模式[^2]。 ```java interface Flyable { void fly(); } class Bird implements Flyable { @Override public void fly() { System.out.println("Bird is flying"); } } class Airplane implements Flyable { @Override public void fly() { System.out.println("Airplane is flying at high speed."); } } ``` #### 继承层次中的方法重写 当子类覆盖来自其父类的方法时,在运行期间会根据实际对象类型决定执行哪个版本的方法——这便是动态绑定机制发挥作用之处。即使声明类型的引用指向某个特定实例,只要该实例所属的最具体类中有相应方法定义,则优先调用后者[^3]。 ```java public class Animal { public void makeSound(){ System.out.println("Animal sound..."); } } public class Dog extends Animal{ @Override public void makeSound(){ System.out.println("Woof woof!"); } } // 测试代码片段 Animal myPet = new Dog(); // 编译器只知道myPet是一个Animal类型 myPet.makeSound(); // 输出 "Woof woof!" 而不是默认动物叫声 ``` #### 使用 `instanceof` 关键字安全转型 为了防止因强制转换失败而导致程序崩溃(`ClassCastException`)的情况发生,可以在尝试向下造型之前先检查目标对象是否确实属于预期类别之一。如果条件成立则继续操作;反之则采取其他措施处理未知情况[^1]。 ```java if (object instanceof String){ String str = (String)object; } else { // Handle non-string objects here. } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值