Java笔记(8)——多态和对象实例化
文章目录
this和super的区别
在子类中,通过this或者说super调用构造器,只能使用一个,因为都要占据第一行
简单类对象的实例化过程
public class Person{
public Person(){
Person p =new Person();
}
int age=1;
String name="zhangsan";
int sex=0;
public void showInfo(){
System.out.println(this.age);
System.out.println(this.name);
System.out.prinln(this.sex);
}
public voif setInfor(int age,String name,int sex){
this.age=age;
this.name=name;
this.sex=sex;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/ab60f79fa8100518a5fd36157a9245c6.png)
子类对象实例化过程
(1)先加载父类,后加载子类
(2)本例子中类的属性没有赋值,所有显示初始化就省略了
面向对象特征之三:多态性
多态性——面向对象最重要的概念,在Java里面有两种体现:
-
方法的重载(overload)和重写(overwrite)。重载体现同名方法不同逻辑,重写体现子类可使用父类相同方法名覆盖父类逻辑,父类想修改逻辑,有别的代码要使用父类方法,,用子类继承父类,重写父类的方法
-
对象的多态性 ———可以直接应用在抽象类和接口上。
Java引用变量有两个类型:
(1)编译时类型和运行时类型。编译时类型有声明该变量使用的类型决定,运行时类型由实际赋给该变量的对象决定
(2)若编译时类型和运行时类型不一致,就出现多态(Polymorphism)
多态性(2):
对象的多态——在java中,子类的对象可以代替父类的对象使用
(1)一个变量只能有一种确定的数据类型
(2)一个引用类型变量可能指向(引用)多种不同类型的对象
Person p =new Studnet();
Person e =new Studnet();//Person类型的变量e,指向Student类型的对象
子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象;向上转型(upcasting);把子类的对象可以给父类的类型的变量引用。
多态类型(3):
一个引用类型变量如果声明为父类的类型,但实际引用的是子类的对象,那么该变量就不能再访问子类中添加的属性和方法。
Student m=new Student();
m.school="pku";//合法,Student类有school成员变量
Person e=new Student();
e.school="pku";//非法,Person类没有school成员变量
//属性是在编译时确定的,编译时e为Person类型。没有school成员变量,因而编译错误。
虚拟方法调用(Virtual Method Invocation)
正常的方法调用
Person p=new Person();
p.getInfo();
Student s=new Studnet();
s.getInfo();
虚拟方法调用(多态情况下)
Person e =new Student();
e.getInfo;//调用Student类的getInfo()方法
编译类型和运行时类型
编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法——动态绑定。
多态小节
前提:
(1)需要存在继承或者实现关系、
(2)要用覆盖操作
成员方法:
(1)编译时,要查看应用变量所属的类中是否有所调用的方法。
(2)运行时,调用实际对象所属的类中的重写方法。
(3)成员方法的多态性,也就是动态绑定,必须得存在于方法的重写之上
成员变量:
不具备多态性,只看引用变量所属的类。
子类继承父类:
(1)若子类重写了父类方法,意味着子类定义的方法彻底覆盖父类同名方法,系统不可能把父类的方法转移到子类中
(2)对于实例变量则不存在这样的现象,即使子类中定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量。
多态性应用举例
方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法
public class Test(){//把子类看做一个特殊的父类
public void method(Person e){
//...
e.getInfo();
}
public static void main(String[] args){
Test t=new Test();
Student m=new Studnet();
t.method(m);//子类的对象m传给父类类型的参数a
}
}
instanceof操作符
x instanceof A: 检验x是否为A的对象,返回值为boolean型。
(1)要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
(2)如果x属于类A的子类B,x instanceof A值也为true。
//检验某个对象是不是类A的子类
public class Person extends Object{...}
public class Stundet extends Person{...}
public class Graduate extends Person{...}
-----------------------------------------
public void method1(Person e){
if(e instanceof Person)
//处理Person类及其子类对象
if(e instanceof Student)
//处理Student类及其子类对象
if(e instanceof Graduate)
//处理Graduate类及其子类对象
}
Object类
(1)Object类是所有java类的根父类(最顶层父类/基类)
(2)如果在类的声明中未使用etends关键字指明其父类,则默认父类为Object类
(3)多层继承,处于最高层的父类一定是Object类
public class Person{
...
}
//等价于:
public class Person extends Object{
...
}
//例如:
method(Object obj){...}//可以接收任何类作为其参数
Person o=new Person();
method(o);