1.重载是根据形参列表的差异来确定,而重写是按照从子类到父类的查找方式来确定使用哪个属性或方法 (具体看本专栏的重写与覆盖)
2.(重点)对象的多态
下面代码是对编译类型和运行类型的理解
package Test;
public class Animal {
public void say(){
System.out.println("我是animal");
}
}//这是父类,定义了say方法
//==================================================
package Test;
public class Dog extends Animal{
public void say(){
System.out.println("我是小狗,小狗汪汪叫");
}
}//这是animal子类dog,也定义了say方法
//===================================================
package Test;
public class Cat extends Animal{
public void say (){
System.out.println("我是cat,小猫喵喵叫" );
}
}//这是animal的另一个子类cat,也定义了say方法
//===================================================
package Test;
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();//这里编译类型是Animal,运行类型是Dog;父类创建子类的对象
animal.say();//这里这样调用方法是会从运行类型开始调用,
// 即使父类和子类都有方法的重写,但是会从运行类型开始
animal = new Cat();
animal.say();//是可以更改运行对象的,但是编译对象不更改
}
}
最后会输出“我是小狗,小狗汪汪叫”
“我是cat,小猫喵喵叫”
因为dog是运行类型,所以调用的say方法是从dog开始的(前提是都有say方法),后面把运行类型改成cat了,就调用的是cat里面的say方法
3.向上转型
理解:
首先只能是拥有继承关系才能转型
只能调用编译类型里的所有成员方法和属性(还是要遵守修饰符的访问条件),不能调用运行类型里的编译类型不存在的属性和方法(就是运行类型特有的),在运行时,是从子类往上开始查找,遵循继承里面的查找方法,比如如果编译类型和运行类型两个都同时有相同的方法的,就调用运行类型。而如果运行里面没有,就一层一层往上找
=======================================
可以理解为对于方法都是从运行类型开始寻找,但是前提是只能是编译类型中有的才有资格寻找
创建的对象是可以更改的
比如上述代码这一段
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();//这里编译类型是Animal,运行类型是Dog;父类创建子类的对象
animal.say();//这里这样调用方法是会从运行类型开始调用,
animal = new Cat();
animal.say();//是可以更改运行对象的,但是编译对象不更改
}
}
4.向下转型
首先也是必须要有继承关系才能转型(必须是直系的就是说在一条继承关系上,而不能是父类的另外一条继承关系上)
对于属性
属性就取决于编译类型的属性,只是在继承时进行初始化时,是就近寻找的
对于方法
有两种方式
package Test;
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();//这里编译类型是Animal,运行类型是Dog;
animal.say();//这里这样调用方法是会从运行类型开始调用,
// 即使父类和子类都有方法的重写,但是会从运行类型开始
animal = new smallCat();//是可以更改运行对象的,但是编译对象不能更改
animal.play();//在smallCat里面没有play就,往上找到cat里面的play
//向下转型
Cat cat = (Cat) animal;//第一种
cat.test();//相当于引出来了个新的叫法。新的引用类型,且该类型是cat类的,所以可以调用cat的方法,属性
((Cat)animal).test();//第二种,没有引入新名字,类似于直接强制转换
}
}
对于第一种,引出来了个新的叫法,可以通过它调用它cat类型的方法,就是cat相当于一个新名字在调用方法上面。但是如果调用属性,调用的是其编译类型的属性
(与直接创建新的cat的区别就是没有新对象,易于管理)
对于第二种,相当于直接强转换,没有新的引用出现,当然也不能 ((Cat)animal).属性的方式去调用属性
5.instanceof
使用
xx instanceof xx
返回布尔类型(前面的那个是不是后面的那个的类型或者子类型)(注意:这里判断的是运行类型)
6.总结