深入理解JAVA多态

何为多态,多态有什么用,多态有什么表现

多态是同一个行为具有多个不同表现形式或形态的能力。

比如说,你喜欢喝酒,你去酒店买酒让服务员给你拿一瓶酒,这个时候服务员问你“要红酒、白酒、洋酒”,这也是多态,下面给出一定代码演示
酒 a=new 洋酒();
酒 a=new 红酒();
酒 a=new 白酒();
从上例就可以看出,酒有不同的形态,有不一样的特性,这就是多态

多态的声明

同样用上面的例子给出解释,例如我有一个类
class 酒{
String color;
}
以及还有几个子类(洋酒、红酒、白酒)派生自酒类,每个都有一个各自的特性变量price
这个时候以下声明是合法的
酒 a=new 白酒();
然后 a.color=“白色”;这样是没问题的,因为你本身就是继承与酒类,可以实现酒的方法以及变量,同时JAVA也是运行父类对象指向子类对象,但是如果你像下面这样就是会报错的
a.price=1000;
很多人就不明白了,明明是new的白酒类,是一个子类对象,为什么还不能用自己的特性方法,这个时候你需要了解一下java的内存加载,首先是编译看左边,如果你父类中不存在这个变量,那么根本通不过编译,就别说后期的运行了。那么,如果你问我需要运行这个变量,应该怎么办,这个时候就需要转型了

向上转型以及向下转型

上转型:是子类对象由父类引用,格式:parent p=new son
下转型:是父类向下强制转换到子类对象(前提是该父类对象必须是经过上转型的对象)
一定注意这里的前提,下转型必须要经过上转型才行,接着用上面的例子举例
现在我们已经经过了上转型:酒 a=new 白酒();
接下来就是下转型:白酒 白=(白酒)a;
然后你现在白.price=1000;就可以运行了

上面的理论就这些了,下面给出两道实际例子

提示:方法以及静态变量是编译看“左边”,运行看“左边”,变量是编译看“左边”,运行看“右边”

public class demo2 {

public static void main(String[] args) {
	 	A a1 = new A();
		A a2 = new B();
		B b  = new B();
		C c  = new C(); 
		D d  = new D(); 
		System.out.println(a1.show(b));   
		System.out.println(a1.show(c));   
		System.out.println(a1.show(d));  
		System.out.println(a2.show(b));   
		System.out.println(a2.show(c));  
		System.out.println(a2.show(d));   
		System.out.println(b.show(b));    
		System.out.println(b.show(c));    
		System.out.println(b.show(d));      
	}
}
class A {
	public String show(D obj) {
		return ("A and D");
}

	public String show(A obj) {
		return ("A and A");
	}
}

class B extends A {
	//重载
	public String show(B obj) {
		return ("B and B");
	}
	//重写
	public String show(A obj) {
		return ("B and A");
	}

}

	class C extends B {
}

	class D extends B {
}

输出结果是:
A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D

关于上面代码的解释如下:
1.首先我们需要明白,题目最开始我说的原则,以及,题目中有重写方法和重载方法

(1)首先a1就是A的对象,所以直接调用A自身的方法,然后传入的对象b,这个时候因为类A中没有比配的方法,所以将对象b提升成父类a,然后找到比配的方法,输出AA
(2)同(1),一个道理,只是提升多经历了一步
(3)因为传入的本身就是d对象,所以直接有比配的方法,直接打印
(4)这里需要注意前面说的原则了,编译看左边,运行看右边,所以首先去看父类中是否存在这个方法,找到了,这个show(A obj)方法,然而这个方法被B类重写,所以运行B类的show(A obj)打印BA
(5)这里存在一个问题,按道理运行看右边,然后将C对象提升,打印应该是BB,然而结果却是BA,这里我们需要注意,编译是看的左边,如果类A都不存在这个方法,那么编译就直接报错,所以,这个时候一样是在类A里面找,找到了show(A obj)方法,然后被重写,所以打印BA
(6)同(5)一个道理,也是首先在类A里面找到,然后有一个直接比配show(D obj)就可以直接打印AD
(7)(8)就很简单了,本身就是类B的对象,所以直接在类B中寻找,然后找到了,就打印BB
(9)这里需要注意,虽然是类B的对象,但是B是继承的A类,所以A类的方法也可以使用,所以会比配到A类的show(D obj)打印AD

好了,这就是这个题的解释,或许还有其他人的解释和我不一样,

以下我会给出我的总结

1.方法以及静态变量是编译看“左边”,运行看“左边”,变量是编译看“左边”,运行看“右边”
2.有多态,先看父类方法是否存在,或者可以经过提升转换,然后再看子类的重写
3.继承链中对象方法的调用存在一个优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

猜你喜欢

转载自blog.csdn.net/qq_37871033/article/details/85256091