第1章 继承的概述及特点
1.1 继承的概念
1.1.1 继承的概述 is-a
继承是面向对象的核心特性,是面向对象的学习重点。
继承是代码复用的重要方式,是类与类之间的一种关系。
从类与类之间的设计关系来看,子类必须属于父类的一种时,才会继承。
父类抽取出了共性的内容,子类可以在父类基础上扩展新的属性与行为。
子类拥有父类的所有属性与方法,无需重新定义。并且可以直接使用非私有的父类成员。
关键字 extends
1.1案例
父类
package com.igeek.javase.ch02.extendss;
/**
* @version 1.0
* @Description TODO
*
* 继承: is-a
* 1.关键字 extends
* 2.继承本质上是设计层面的思想,本意是提高代码的复用性
* 3.子类继承父类后,父类中的成员变量和成员方法子类都具备,并且子类还可以拓展新的属性和新的方法
* 4.创建的父类对象,可以使用父类中的成员属性和成员方法,但是不能使用子类拓展的属性及方法
* 5.Java中类与类之间是单继承
*/
public class Animal {
private String name;
private String color;
private int age;
public Animal() {
}
public Animal(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//吃
public Animal eat(/*Animal a*/) /*throws Exception*/{
System.out.println("一只"+color+name+"在吃东西...");
return null;
}
}
子类
package com.igeek.javase.ch02.extendss;
/**
* @version 1.0
* @Description TODO
*/
public class Dog extends Animal{
//
private String player;
public Dog() {
}
public Dog(String name, String color, int age, String player) {
super(name, color, age);
this.player = player;
}
public String getPlayer() {
return player;
}
public void setPlayer(String player) {
this.player = player;
}
//
public void kanjia(){
System.out.println("一只"+this.getAge()+"的"+this.getName()+"在看家...");
}
}
1.2 子类通过get&set方法访问父类成员变量
当父类的成员变量用private修饰后,子类无法访问父类的成员变量,但是如果父类提供了public修饰的get/set方法,则子类可以通过get/set方法,正常访问父类的成员变量。
第2章 方法重写及继承内存图解
2.1 方法重写的概念与格式
2.1.1 方法重写的概述
当子类继承父类后,拥有了父类的成员并可以直接调用父类非私有方法。如果子类认为父类提供的方法不够强大,子类可以按照子类自身的逻辑重新定义继承过来的父类方法,这个重新定义父类方法的过程叫做方法重写。
方法重写后,调用该方法时不再调用父类的方法,而调用子类重写后的方法。
package com.igeek.javase.ch02.extendss;
/**
* @version 1.0
* @Description TODO
*
* 方法重载 Overload
* 1.发生在一个类中
* 2.方法名相同
* 3.参数列表不同(参数个数、参数顺序、参数数量不同)
* 4.与返回值无关
*
* 方法重写 Override
* 1.发生在继承中,子类继承父类,子类重写父类的方法
* 2.方法名相同
* 3.形参必须一致
* 4.返回值:若是基本数据类型则返回值一致即可;
* 若是引用数据类型,则子类的返回值类型不可以放大,只可以是<=父类的返回值类型 Object>Animal>Cat 父类>子类
* 5.访问权限修饰符:子类是不可以缩小范围的 public>protected>(default)>private
* 6.抛出异常:子类抛出异常比父类小 Throwable>Exception>NullPointerException
*
* 注意:
* 1.@Override一旦标注在方法上,检测当前方法是否符合重写要求
* 2.子类重写父类的方法后,调用执行时会执行子类重写后的逻辑
*/
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, String color, int age) {
super(name, color, age);
}
//捕捉方法
public void zhua(){
System.out.println("一只"+this.getAge()+"岁的,小"+this.getName()+"在抓鱼...");
}
// Alt+Insert -> Override 或者 Ctrl+O
@Override
public Cat eat(/*Animal a*/) /*throws NullPointerException*/{
Cat cat = new Cat();
//默认调用父类的逻辑
//super.eat();
System.out.println("一只"+getName()+"在吃鱼...");
return cat;
}
}
Test
package com.igeek.javase.ch02.extendss;
/**
* @version 1.0
* @Description TODO
*/
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("小猫咪","花色",2);
cat.eat(); //Cat中方法重写eat(),执行时会按照子类的逻辑进行执行
cat.zhua();
System.out.println("------------------");
Tiger tiger = new Tiger();
tiger.setName("东北虎");
tiger.setColor("白色");
tiger.setAge(3);
tiger.eat();
tiger.hunt();
System.out.println("------------------");
Dog dog = new Dog("哈士奇","灰色",5,"彩钢儿");
dog.eat();
dog.kanjia();
System.out.println("------------------");
Animal animal = new Animal("动物","无色",1);
animal.eat();
//animal.hunt();
//animal.kanjia();
//animal.zhua();
}
}
输出
一只小猫咪在吃鱼...
一只2岁的,小小猫咪在抓鱼...
------------------
一只白色东北虎在吃东西...
东北虎在狩猎中...
------------------
一只灰色哈士奇在吃东西...
一只5的哈士奇在看家...
------------------
一只无色动物在吃东西...
- 是否能被继承?
-
1.成员变量、成员方法 可以继承
-
2.私有的属性 可以继承
-
3.静态的成员 不可以继承,静态成员是所有实例共享
-
4.构造方法 不可以继承
- 是否能进行方法重写?
-
1.成员变量不存在重写的问题
-
2.构造方法 不可以重写
-
3.静态方法 不可以重写
-
4.私有方法 不可以重写
2.2 继承后子父类构造方法调用先后顺序
2.2.1 继承中子父类构造调用顺序概述
在每次创建子类对象时,我们均会先初始化父类内容,再初始化其子类本身内容。目的在于子类对象中包含了其对应的父类存储空间,便可以包含了其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。
代码体现在子类的构造方法调用时,一定先调用父类的构造方法。
第3章 this与super
3.1 this与super访问普通成员
3.1.1 this和super访问注意事项
调用普通成员:
this.成员变量 可以访问本类对象的成员变量
super.成员变量 可以访问父类的成员变量
this.成员方法() 可以访问本类对象的成员方法
super.成员方法() 可以访问父类的成员方法
子类方法中
访问子类自身的成员用this.
访问父类的成员super.
就近原则:
局部 > 本类成员 > 父类成员
3.2 super访问父类构造方法
3.2.1 super调用父类构造方法的格式
调用构造方法:
this(其他参数) 可以访问本类其他的构造方法
super(其他参数) 可以访问父类其他的构造方法
默认子类调用父类构造方法:
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super();
3.3 this访问子类构造方法
在子类构造中使用this() 或 this(参数类型 参数值…)的方法可以调用本类中的其他构造方法。但是最终都是要调用父类的构造方法,完成父类成员的初始化。
第4章 关联关系及依赖关系
4.1 关联关系
对象和对象之间的连接。在Java中,关联关系的代码表现形式为一个类做为另一个类的属性类型存在。即“有”的关系:”has-a”。
- 关联关系 为了提高代码的复用率
-
1.代码层面:一个类作为另外一个类的属性类型存在
-
2.has-a 有
-
3.一对一 、 一对多Phone[] phones、List<Phone> list
-
4.强关联(组合关系)、弱关联(聚合关系)
-
5.单向关联、双向关联
package com.igeek.javase.ch02.has;
import java.util.Arrays;
/**
* @version 1.0
* @Description 关联关系
*/
public class ClassTest {
public static void main(String[] args) {
Student stu1 = new Student("小红",100);
Student stu2 = new Student("小黑",101);
Student stu3 = new Student("小白",102);
Student[] stus = {stu1,stu2,stu3};
Classes classes = new Classes("Java","班级1",stus);
// classes.setStudents(stus);
stu1.setClasses(classes);
stu2.setClasses(classes);
stu3.setClasses(classes);
//双向关联中 , toString()会互相调用的问题,造成堆栈溢出错误 , 一定要注意
System.out.println(classes);
System.out.println("-----------"+classes.getName()+"的学生信息如下------------");
for (Student student : classes.getStudents()) {
System.out.println(student);
}
}
}
class Classes{
private String label;
private String name;
//一对多 强关联 双向关联
private Student[] students = new Student[3];
public Classes() {
}
public Classes(String label, String name) {
this.label = label;
this.name = name;
}
public Classes(String label, String name, Student[] students) {
this.label = label;
this.name = name;
this.students = students;
}
/**
* 获取
* @return label
*/
public String getLabel() {
return label;
}
/**
* 设置
* @param label
*/
public void setLabel(String label) {
this.label = label;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return students
*/
public Student[] getStudents() {
return students;
}
/**
* 设置
* @param students
*/
public void setStudents(Student[] students) {
this.students = students;
}
/*public String toString() {
return "Classes{label = " + label + ", name = " + name
+ ", students = " + Arrays.toString(students) + "}"; //StackOverflowError 堆栈溢出
}*/
public String toString() {
return "Classes{label = " + label + ", name = " + name + "}";
}
}
class Student{
private String name;
private int num;
//一对一 弱关联 双向关联
private Classes classes;
public Student() {
}
public Student(String name, int num) {
this.name = name;
this.num = num;
}
public Student(String name, int num, Classes classes) {
this.name = name;
this.num = num;
this.classes = classes;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return num
*/
public int getNum() {
return num;
}
/**
* 设置
* @param num
*/
public void setNum(int num) {
this.num = num;
}
/**
* 获取
* @return classes
*/
public Classes getClasses() {
return classes;
}
/**
* 设置
* @param classes
*/
public void setClasses(Classes classes) {
this.classes = classes;
}
public String toString() {
return "Student{name = " + name + ", num = " + num + ", classes = " + classes + "}";
}
}
4.2 依赖关系
依赖关系(use-a):指一个类A使用到了另一个类B。依赖关系的特性:这种关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。
- 依赖关系 为了代码复用性
-
1.代码层面 一个类作为另外一个类的方法形参类型存在
-
2.use-a 用
-
3.具备临时性,偶然性
public class Person {
private String name;
//上班的方法 类A使用到了另一个类B
public void work(Bus bus){
System.out.println(this.name+"乘坐"+bus.getName()+"去上班");
}
public Person() {
}
public Person(String name) {
this.name = name;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
public String toString() {
return "Person{name = " + name + "}";
}
}