面向对象编程有三大特征:封装、继承和多态
思维导图概览:

1. 封装的概念
—— 把抽象出的数据(属性)和对数据的操作(方法)封装到一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(方法),才能对数据进行操作
2. 封装的理解和优势
1)隐藏实现细节:调用方法时才能传入参数,不能直接进行对数据的改动
2)可以对数据进行验证,保证安全合理
3. 封装的实现
1)将属性进行私有化(private)【不能直接修改属性】
2)提供公共的(public)set/get方法,对数据进行判断并赋值
a. 提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰
b. 提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰
3)提供相应的构造器/构造方法,与set/get方法结合
4.案例分析
- class Student {
- //成员变量
- private String name;
- private int age;
-
- //构造方法
- public Student() {
- }
-
- public Student(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- //成员方法
- public void setName(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void setAge(int age) {
- //对数据进行校验
- if(age >= 0 && age <= 150) {
- this.age = age;
- } else {
- this.age = 0;
- }
- }
-
- public int getAge() {
- return age;
- }
-
- public void show() {
- System.out.println(name + "," + age);
- }
- }
- /*
- 创建对象并为其成员变量赋值的两种方式
- 1:无参构造方法创建对象后使用setXxx()赋值
- 2:使用带参构造方法直接创建带有属性值的对象
- */
- public class StudentDemo {
- public static void main(String[] args) {
- //无参构造方法创建对象后使用setXxx()赋值
- Student s1 = new Student();
- s1.setName("林青霞");
- s1.setAge(30);
- s1.show();
-
- //使用带参构造方法直接创建带有属性值的对象
- Student s2 = new Student("林青霞",30);
- s2.show();
- }
- }
思维导图概览:

1. 为什么需要继承?
—— 如果两个类有很多相同的属性和方法,这个时候就可以使用继承来提高代码的复用性
2. 继承基本了解和继承示意图
1)继承的了解:继承可以解决代码复用,当多个类中存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。
2)继承的格式
class Dog extends Animal { }
3)继承示意图

3. 继承的基本语法
1)class 子类 extends 父类 {}
2)子类就会自动拥有父类定义的属性和方法
3)父类又叫做超类,基类
4)子类又叫派生类
4. 一个小case快递了解继承
- public class Student {
- public String name;
- public int age;
- private double score;
-
- public void setScore(double score) {
- this.score = score;
- }
-
- public double getScore() {
- return score;
- }
-
- public void show() {
- System.out.println("学生名:" + name + " 年龄:" + age + " 成绩:" + score);
- }
- }
-
-
- public class Pupil extends Student {
-
- public void testing() {
- System.out.println("小学生 " + name + "age = " + age + " 正在考小学数学");
- }
- }
-
-
- public class Graduate extends Student {
- public void testing() {
- System.out.println("大学生" + name + " 年龄为:" + age + " 正在考大学数学");
- }
-
- public void print() {
- System.out.println("大学生的分数为 " + getScore());
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- Pupil pupil = new Pupil();
- Graduate graduate = new Graduate();
- pupil.name = "小米";
- pupil.age = 10;
- pupil.testing();
-
- graduate.name = "小强";
- graduate.age = 20;
- graduate.setScore(80.0);
- graduate.testing();
- graduate.print();
- }
-
- }
5. 继承的优势与劣势
1)优势
a. 代码的复用性提高了
b. 代码的扩展性和维护性提高
2)劣势
—— 继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性
6. 继承的细节讨论及实现
1)子类继承了所有的属性和方法,非私有的属性和方法可以在子类中直接访问,但是私有属性和方法的访问,要通过父类提供公共的方法去访问
- public class Test1 {
- public static void main(String[] args) {
- //给A中的私有属性进行赋值
- A a = new A();
- a.setA(18);
- a.setAge(20);
-
- //B继承A后,可访问
- B b = new B();
- b.getMethod();
- System.out.print(b.getA());
- System.out.print(b.getAge());
- }
- }
-
- class A {
- public int age;
- private int a;
-
- //无参构造器
- public A() {
- }
-
- //有参构造器
-
- public A(int age, int a) {
- this.age = age;
- this.a = a;
- }
-
-
- //相关的set/get方法 --> 用来访问私有属性
-
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public int getA() {
- return a;
- }
- public void setA(int a) {
- this.a = a;
- }
-
-
- //私有方法
- private void method() {
- System.out.println("这是父类的私有方法~~~");
- }
-
- //通过公共方法去访问私有方法
- public void getMethod() {
- method();
- }
- }
-
- class B extends A {}
2)子类必须调用父类的构造器,完成父类的初始化(子类中所有的构造方法默认都会访问父类中无参的构造方法)
3)当创建子类对象时,不管使用子类的那个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的那个构造器完成对父类的初始化工作,否则,编译不会通过
4)想要指定去调用父类的某个构造器,则可以显示的调用一下:super(参数列表);
5)super在构造器中使用时,必须放在构造器的第一行
- public class Test1 {
- public static void main(String[] args) {
-
- }
- }
-
- class A {
- public int age;
- private int a;
-
- //无参构造器
- public A() {
- }
-
- //有参构造器
-
- public A(int age, int a) {
- this.age = age;
- this.a = a;
- }
-
-
- //相关的set/get方法 --> 用来访问私有属性
-
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public int getA() {
- return a;
- }
- public void setA(int a) {
- this.a = a;
- }
-
- }
-
- class B extends A {
- //1.若是一样都没有写,则存在一个默认的无参构造器public A() {},默认的无参构造器中存在父类的无参构造器
-
- public B(){
- //2. 写出了子类的无参构造器,在无参构造器中默认调用了父类的无参构造器,无法对父类进行初始化,因为父类的无参构造器中也没有属性,注意:super()只能放在第一行
- }
-
-
- public B(int age , int a) {
- super(age, a);// 3.显示调用了父类的有参构造器(则不再会调用父类的默认无参构造器),对父类的属性进行初始化,注意:super()只能放在第一行
- }
- }
6)super() 和 this()都只能放在构造器的第一行,因此这两个关键字不能共存于同一个构造器中
- class A () {
-
- }
-
- class B extends A{
- public B() {
- this(age);//表示到进入到下面的这个有参构造器中去了
- //使用this的使用无法使用默认是super();
- }
- public B(int age) {
- //注意:里面默认存在一个super();
- }
- }
7)Java所有类的父类都是Object类,Object类是所有类的父类(顶级父类)
- public class Test1 {
- public static void main(String[] args) {
-
- }
- }
-
- class A extends Object{
- }
-
- class B extends A {
-
- }
8)子类最多只能继承一个父类(指直接父类),即Java是单继承机制
- public class Test {
- public static void main(String[] args) {
-
- }
- }
-
- class A {}
- class B {}
-
- class C extends B extends A {}//错误代码,Java是单继承模式
注:不能滥用继承,子类和父类之间必须满足is - a的逻辑关系
意思是如果有一个动物类(父类),你创建了一个猫类,继承动物类, 这是满足 is - a的形式,但是如果你创建了一个树木类,继承了动物类, 则不满足is - a 的形式
7. 继承的本质分析
- public class ExtendsTheory {
- public static void main(String[] args) {
- Son son = new Son();//内存的布局
- //?-> 这时请大家注意,要按照查找关系来返回信息
- //(1) 首先看子类是否有该属性
- //(2) 如果子类有这个属性,并且可以访问,则返回信息
- //(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
- //(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object...
- System.out.println(son.name);//返回就是大头儿子
- System.out.println(son.age);//返回的就是 39
- System.out.println(son.getAge());//返回的就是 39
- System.out.println(son.hobby);//返回的就是旅游
- }
- }
-
- class GrandPa {//爷类
- String name = "大头爷爷";
- String hobby = "旅游";
- }
-
- class Father extends GrandPa {//父类
- String name = "大头爸爸";
- private int age = 39;
- public int getAge() {
- return age;
- }
- }
-
- class Son extends Father { //子类
- String name = "大头儿子";
- }
1. super介绍
—— super代表父类的引用,用于访问父类的属性、方法、构造器
2. super语法
1)访问父类的属性,但不能访问父类的private属性 ---> super.属性名
2)访问父类的方法,但不能访问父类的private方法 ----> super.方法名(参数列表)
3)访问父类的构造器 ----> super(参数列表);只能放在构造器的第一句,也只能出现一句
3. 一个小case快速了解super
- public class Test1 {
- public static void main(String[] args) {
-
- }
- }
-
- class A {
- public int num1;//公共
- protected int num2;//受保护
- int num3;//默认
- private int num4;//私有
-
- //构造器
- public A() {
- }
-
- public A(int num1, int num2) {
- this.num1 = num1;
- this.num2 = num2;
- }
-
- public A(int num1, int num2, int num3, int num4) {
- this.num1 = num1;
- this.num2 = num2;
- this.num3 = num3;
- this.num4 = num4;
- }
-
- //set/get方法
- public int getNum1() {
- return num1;
- }
-
- public void setNum1(int num1) {
- this.num1 = num1;
- }
-
- public int getNum2() {
- return num2;
- }
-
- public void setNum2(int num2) {
- this.num2 = num2;
- }
-
- public int getNum3() {
- return num3;
- }
-
- public void setNum3(int num3) {
- this.num3 = num3;
- }
-
- public int getNum4() {
- return num4;
- }
-
- public void setNum4(int num4) {
- this.num4 = num4;
- }
-
- //私有方法
- private void print() {
- System.out.println("这是A类中的私有方法");
- }
- }
-
- class B extends A {
- public B(int num1, int num2 ,int num3 ,int num4) {
- //super();//访问父类的无参构造器,不写也默认有
- //super(num1,num2); 访问父类中的有有两个参数的构造器,使用这个构造器时,默认构造器不执行
- super(num1, num2, num3, num4);
- }
-
- public void pout() {
- super.num1 = 10;
- super.num2 = 20;
- super.num3 = 30;
-
- //super.num4 = 40; 错误,私有成员变量不能访问
-
- //super.print(); 错误,私有方法不能访问
- }
- }
4. super的细节讨论及实现
1)调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类属性由子类初始化)
2)当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super和this直接访问是一样的效果
3)super的访问不限于直接父类,如果爷爷类和本类中有相同的成员,也可以使用super去访问爷爷类中的成员;如果有多个基类(上级类)中都有同名的成员,使用super访问时遵循就近原则。
5. this和super的比较
| 区别点 | this | super |
| 访问属性 | 访问本类中的属性,如果本类没有此属性则从父类中继续查找 | 从父类开始查找 |
| 调用方法 | 访问本类中的方法,如果本类中没有此方法,则从父类中继续查找 | 从父类中开始查找 |
| 调用构造器 | 调用本类的构造器,必须放在构造器首行 | 调用父类的构造器,必须放在子类的首行 |
| 特殊 | 表示当前对象 | 子类中访问父类的对象 |
1. 方法重写概念
—— 方法重写就是子类有一个方法和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法重写了父类的方法
2. 一个小case快速了解方法重写
- public class Test {
- public static void main(String[] args) {
- B b = new B();
- b.print();//?输出什么? ---》 父类中的print()方法被子类中的print()方法重写了~
- //注意:重写的权限修饰,父类中的一定不能是private,不然不能重写,且子类重写的方法不能降低父类方法的访问权限,但可以提高
- }
- }
-
- class A {
- private String name;
- private int age;
-
- void print() {
- System.out.println("name = " + name + " age = " + age);
- }
-
- public A() {
- }
- public A(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
- }
-
- class B extends A {
- public void print() {
- System.out.println("父类中的print()方法被子类中的print()方法重写了~");
- }
- }
注:重写的权限修饰符,父类方法中的一定不能是private,不然不能重写,且子类重写的方法不能降低父类方法的访问权限,但可以提高【public > protected > 默认 > private】
3. 方法重写的细节讨论及实现
1)子类的方法的形参列表,方法名称,要和父类方法的形参列表,方法名称完全一样
2)子类方法中的返回类型和父类方法中的返回类型一样,或者是父类返回类型的子类
- //如:父类返回类型是 Object,子类方法返回类型是String,String是Object的子类
- //父类方法:
- public Object getInfo() {}
- //子类方法
- public String getInfo() {}
3)子类方法不能缩小父类方法的访问权限,但能提高【public > protected > 默认 > private】
4. 方法重写与方法重载的比较
| 名称 | 发生范围 | 方法名 | 形参列表 | 返回类型 | 修饰符 |
| 方法重载(overload) | 本类 | 必须一样 | 类型,个数或者顺序至少有一个不同 | 无要求 | 无要求 |
| 方法重写(override) | 父子类 | 必须一样 | 相同 | 子类重写的方法,返回的类型和父类返回的类型一致,或者是父类的子类 | 子类不能缩小父类方法的访问范围 |
思维导图概览:

1. 多态的介绍
—— 方法或对象具有多种形态。多态是面向对象的第三大特征,多态是建立在封装和继承的基础上的
2. 多态的具体体现
1)方法的重写和方法的重载就体现多态
2)对象的多态
3. 如何判断编译类型和运行类型
1)编译类型看 = 号的左边,运行类型看 = 号的右边
2)编译类型在定义对象时,就确定了,不能改变
3)运行类型是可以改变的
4)一个对象的编译类型和运行类型可以不一致
- //编译类型为animal,运行类型为Tiger
- Animal animal = new Tiger();
- //编译类型为animal,运行类型为Cat
- animal = new Cat();
4. 一个小case快速了解对象的多态
- public class TestOne {
- public static void main(String[] args) {
- //编译类型是Animal, 运行类型是Tiger
- Animal tiger = new Tiger();
-
- tiger.print();//打印什么? 老虎会咆哮~~~
- //为什么会打印老虎会咆哮? ---> 我们使用多态的时候,先看看子类中里面是否有重写父类的方法,如果有,那就使用,
- //如果没有,在父类中查看有没有该方法,如果有则使用
- }
- }
-
-
- public class Animal {
- public String name;
- public int age;
-
- public void print() {
- System.out.println("动物会睡觉~~");
- }
-
- //构造器
- public Animal() {
- }
-
- public Animal(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- //提供成套的set/get方法
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
- }
-
-
- public class Tiger extends Animal{
- public void print() {
- System.out.println("老虎会咆哮~~");
- }
- }
5. 多态的细节讨论及实现
1)多态的向上转型
a. 本质:父类的引用指向子类的对象
- //父类
- class Animal{}
- //子类
- class Cat() extends Animal {}
- //父类的引用指向了子类的对象
- Animal cat = new Cat(); //编译类型:Animal,运行类型:Cat
b. 语法:父类类型 引用名 = new 子类类型();
c. 特点:编译类型看左边,运行类型看右边。可以调用父类中的所有成员变量(需遵守访问权限),不能调用子类中的特有成员,可以调用方法重写,注意,在访问的时候,从运行类型开始访问。
- public class TestOne {
- public static void main(String[] args) {
- //编译类型是Animal, 运行类型是Tiger
- Animal tiger = new Tiger();
-
- tiger.print();//打印什么? 老虎会咆哮~~~
- //为什么会打印老虎会咆哮?
- // ---》 我们使用多态的时候,先判断编译类型中是否有该方法,如果没有,则报错,运行类型从子类开始查找,查找与访问相匹配的方法或属性,如果父类中的方法被重写了,则调用重写的方法
-
- //看看访问特有方法是否报错
- //tiger.output(); --> 错误,不能访问子类中特有的方法
- }
- }
-
-
- public class Animal {
- public String name;
- public int age;
-
- public void print() {
- System.out.println("动物会睡觉~~");
- }
-
- //构造器
- public Animal() {
- }
-
- public Animal(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- //提供成套的set/get方法
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
- }
-
-
- public class Tiger extends Animal {
- public void print() {
- System.out.println("老虎会咆哮~~~");
- }
-
- //特有的方法
- public void output() {
- System.out.println("老虎在打滚~~");
- }
- }
2)多态的向下转型(在向上转型的基础上)
a. 语法:子类类型 引用名 = (子类类型) 父类引用;
- /*
- 怎么理解?
- 1.因为向上转型无法访问子类中的特有方法,但是,向下转型则帮助我们解决了此问题
- 2.怎么理解 子类类型 引用名 = (子类类型) 父类引用?
- //一段代码搞定:
- //编译类型:Animal,运行类型:Tiger
- Aniaml animal = new Tiger();
- //向下转型之后,编译类型Tiger,运行类型:Tiger
- Tiger tiger = (Tiger)animal;
- //子类类型 引用名 = (子类类型)父类引用
- //解决!!!
- 3.思考以下代码能不能向下转型?
- Animal animal = new Cat();
- Dog dog = (Dog)animal;
- //错误,为什么?因为我们没有使用父类的引用类型指向子类的对象,前面说过了,向下转型是基于向上转型的,所以想要向下转型的前提是要使父类的引用指向子类对象,也就是向上转型
- //代码改正
- Animal animal = new Dog();
- Dog dog = (Dog)animal;
- */
b. 只能强转父类的引用,不能强转父类的类型
- //代码解释
- Person p = new Xh();
- Xh xh = (Xh)Person;//错误,这样是强转父类的类型
c. 要求父类的引用必须指向的是当前目标类型的对象(看a.的解释)
d. 向下转型后,可以调用子类类型中的所有成员(属性和方法)
- public class TestOne {
- public static void main(String[] args) {
- //编译类型是Animal, 运行类型是Tiger
- Animal animal = new Tiger();
-
- animal.print();//打印什么? 老虎会咆哮~~~
- //看看访问特有方法是否报错
- //tiger.run(); --> 错误,不能访问子类中特有的方法
-
- //对父类的引用进行强转
- Tiger tiger = (Tiger)animal;
- tiger.run();//可以使用特有方法了
- }
- }
-
-
- public class Animal {
- public String name;
- public int age;
-
- public void print() {
- System.out.println("动物会睡觉~~");
- }
-
- //构造器
- public Animal() {
- }
-
- public Animal(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- //提供成套的set/get方法
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
- }
-
-
- public class Tiger extends Animal{
- //重写的方法
- public void print() {
- System.out.println("老虎爱睡懒觉~~~");
- }
-
- //特有方法
- public void run() {
- System.out.println("老虎跑得快~~~");
- }
- }
3)属性没有重写的说法,属性的值看编译类型
- public class Test {
- public static void main(String[] args) {
- Person person = new Smith("jack",18,"smith",20);
- Smith smith = new Smith();
- Person p = new Person();
-
- System.out.println(person.name); //jack
- System.out.println(person.age);//18
-
-
- System.out.println(smith.name);//null ? --> 因为Smith是我们新开的对象,所有里面的值是默认值
- System.out.println(smith.age); //0
-
- Smith s = (Smith)person; //向下转型
- System.out.println(s.name); //smith
- System.out.println(s.age);20
- }
- }
-
-
- public class Person {
- public String name;
- public int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
- }
-
-
- public class Smith extends Person{
- public String name;
- public int age;
-
- public Smith() {
- }
-
- public Smith(String name, int age, String name1,int age1) {
- super(name, age);
- this.name = name1;
- this.age = age1;
- }
- }
4)instanceof 比较操作符,用于判断对象的运行类型是否是XX类型或XX类型的子类型
- public class Test {
- public static void main(String[] args) {
- BB bb = new BB();
- System.out.println(bb instanceof BB);//true
- System.out.println(bb instanceof AA);//true
-
- //编译类型:AA 运行类型:BB
- AA aa = new BB();
- System.out.println(aa instanceof AA); //true
- System.out.println(aa instanceof BB); //true
-
- Object obj = new Object();
- System.out.println(obj instanceof AA); //false
- String str = "hello";
- //System.out.println(str instanceof AA); //编译器报错,因为两者是不相同的类型
- System.out.println(str instanceof Object); //true
- }
- }
-
- class AA {}
-
- class BB extends AA {}
1. Java重要特性:动态绑定机制
2. Java动态绑定机制的特点
1)当调用对象方法的时候,该方法会和对象的内存地址/运行类型进行绑定
2)当调用对象属性的时,没有动态绑定机制,哪里声明,哪里使用
- public class Test {
- public static void main(String[] args) {
- AA aa = new BB();
-
- System.out.println(aa.sum()); //40
- System.out.println(aa.sum1()); //30
- //为什么会是以上答案?因为运行类型从子类开始执行,查找当中的方法,执行了父类中发方法重写
-
- //去掉子类中的sum()方法
- System.out.println(aa.sum()); //30 --> Java的动态绑定机制:父类中的sum()方法调用子类中重写的getI()方法
- }
- }
-
- class AA {
- public int i = 10;
-
- public int sum() {
- return getI() + 10;
- }
-
- public int sum1() {
- return i + 10;
- }
-
- public int getI() {
- return i;
- }
- }
-
-
- class BB extends AA {
- public int i = 20;
-
- //注意:以下方法全部为重写方法
- /* public int sum() {
- return i + 20;
- }*/
-
- public int getI() {
- return i;
- }
-
- public int sum1() {
- return i + 10;
- }
- }
3.多态数组
—— 数组的定义类型为父类类型,里面保存的对象类型为子类类型或父类类型
- public class Test {
- public static void main(String[] args) {
- Person[] person = new Person[2];
-
- person[0] = new Person("jack",19);
- person[1] = new Student("小红",10,100);
-
- //调用say()方法
- for (int i = 0; i < person.length; i++) {
- System.out.println(person[i].say());
-
- //调用子类的特有方法
- if(person[i] instanceof Student) {
- //向下转型,调用子类中特有的方法
- ((Student) person[i]).study();
- }
- }
- }
- }
-
- public class Person {
- private String name;
- private int age;
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String say() {//返回名字和年龄
- return name + "\t" + age;
- }
- }
-
- public class Student extends Person {
- private double score;
- public Student(String name, int age, double score) {
- super(name, age);
- this.score = score;
- }
- public double getScore() {
- return score;
- }
- public void setScore(double score) {
- this.score = score;
- }
- //重写父类 say
- @Override
- public String say() {
- return "学生 " + super.say() + " score=" + score;
- }
-
- //特有的方法
- public void study() {
- System.out.println("学生 " + getName() + " 正在学 java...");
- }
- }
2. 多态参数
—— 方法定义的形参类型为父类类型,实参类型为父类类型或子类类型
- public class Test {
- public static void main(String[] args) {
- Test test = new Test();
- Person[] person = new Person[2];
-
- person[0] = new Person("jack",19);
- person[1] = new Student("小红",10,100);
-
- test.printSay(person[0]);
- test.printSay(person[1]);
- }
-
- public void printSay(Person p) {
- System.out.println(p.say());
- }
- }
-
- public class Person {
- private String name;
- private int age;
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String say() {//返回名字和年龄
- return name + "\t" + age;
- }
- }
-
-
-
- public class Student extends Person{
- private double score;
- public Student(String name, int age, double score) {
- super(name, age);
- this.score = score;
- }
- public double getScore() {
- return score;
- }
- public void setScore(double score) {
- this.score = score;
- }
- //重写父类 say
- @Override
- public String say() {
- return "学生 " + super.say() + " score=" + score;
- }
- }
1. 一个类可以有几个直接父类?一个父类可有多少个子类?子类能获取直接父类的父类中的结构吗?子类能否获取父类中private权限的属性或方法?
2. 方法的重写(override/overwrite)的具体规则有哪些,两者的区别?
3. super调用构造器,有哪些具体的注意点?
4. 如何实现向下转型?需要注意什么问题?如何解决此问题?
5. == 和equals()有何区别?