08_继承
static关键字
statuc(特殊修饰符)是用来修饰类(静态类)、方法(静态方法)、成员变量(静态变量)、代码块(静态代码块)
成员变量和类变量(static 修饰的成员变量)区别:
- 成员变量又被称为对象变量/实力变量,它是随着对象的创建而产生的,对象之间互不影响。
- 成员变量是通过对象名.属性名来进行访问和操作
- 类变量(静态变量),它是随着类的加载而产生的,被该类所有的对象共享
- 类变量是通过类名.属性名来进行访问和操作的
// 类变量建议采用类名.属性名方式使用
类名.属性名
成员方法和静态方法的区别:
-
在同一类中,成员方法之间可以直接相互调用,也可以调用静态方法。
- 成员方法可以直接使用成员变量,也可以直接使用静态变量。
-
在同一个类中,静态方法之间可以相互调用,但不能调用成员方法。
- 静态方法可以直接使用静态变量,但不可以使用成员变量。
代码块/非静态代码块/成员代码块/构造代码块和静态代码块区别:
public class 类名 {
// 代码块:用于存储一些希望在构造方法执行前执行的程序段
// 总是在构造方法执行前执行
{
// 若干代码
// 若干程序段
}
// 静态代码块:用于存储一些希望在类加载时只执行一次的程序段
// 类加载时执行,且只执行一次
static {
// 程序段
}
}
注意:(暂时可以用它解决的问题)
- 一些工具类的方法,可以定义为静态的,这样不需要创建对象就可以使用。
- 有一些内容需要被多个对象共享,就可以将这些内容定义静态的。
- 在类加载时,希望执行一些代码段,可以将其定义在静态代码块中。
- …
继承的概述
继承是 Java 中实现代码重用的重要手段之一也是面向对象的三大特性之一。 在继承这一概念中,会引申出” 父类” (superclass)和” 子类”/“派生类”(subclass) ,就像现实生活中的父子一样, 子女是父辈的继承人, 可以继承父辈的财产。
在父类中定义子类共有的信息(变量、方法),子类只需要继承父类就可以拥有这些内容,以达到重用的目的。(提升扩展性)
继承的使用
不是看到重复的代码段就考虑继承,也要结合当前场景。
场景需要符合一个 子类 is a 父类 的关系。
1.先定义父类(将子类共有的信息:属性、方法定义到父类中)
public class 父类名 {
// 共有属性
// 共有方法
}
2.定义子类(给子类继承好相应的父类)
extends:继承
public class 子类名 extends 父类名 {
}
在 Java 中继承是单根继承,如果已经继承了一个类,就不能再继承其他的类。继承还有一个传递性。
联想记忆:你只能有一个亲爹,你爷爷的财产可以由你爸爸继承,你爸爸的财产由你继承。
super关键字
联想 this 关键字。
this:代词,当前类的一个对象。
- this.自身的属性
- this.自身的方法
- this(构造参数) 调用自身的构造方法
super:代词,当前类的父类的一个对象。
- super.父类的属性 调用父类的信息是会受到访问权限修饰符的影响。无法调用父类私有的内容。
- super.父类的方法
- super(构造参数) 调用父类的构造方法
在调用子类的构造方法时,无论是带参还是无参,都会先默认调用父类的构造方法。
调用父类构造一定是写在子类的构造方法的有效代码的第一行。
protected访问权限修饰符
本类中、同包的不同类中、不同包的子类中。
修饰符\访问范围 | 本类中 | 同一个包的不同类中 | 不同包的子类中 | 本项目中 |
---|---|---|---|---|
private(私有的) | 🔥 | |||
默认的(包级的) | 🔥 | 🔥 | ||
protected(受保护的) | 🔥 | 🔥 | 🔥 | |
public(公共的) | 🔥 | 🔥 | 🔥 | 🔥 |
方法重写(Override)
方法重写是发生在有继承关系的前提下。
方法重写的概述
在子类继承了父类的方法后,如果父类方法无法满足子类的要求时,子类可以第一继承过来的方法进行重写!重写后执行时会执行重写后的方法。
方法重写的使用
子类对父类方法进行重写:
-
继承来的
子类也不是能继承所有父类的内容
- 父类私有的内容,无法被子类继承
- 父类和子类不再同一个包时,默认修饰(包级)的内容,无法被子类继承
- 父类的构造方法,无法被子类继承
-
方法名和父类方法名要一致
-
方法参数和父类方法参数要一致
-
方法返回值类型和父类方法返回值类型要一致
-
方法的访问修饰符和父类方法访问修饰符要一致,或范围更大(不能严于父类方法)。
-
方法的抛出的异常类型和父类方法抛出的异常类型一致,或范围小或类型少(不能抛出比父类更多更大的异常类型)
可以使用 @Override 注释(Anotation)/注解,来标注重写的方法,可以帮助你在编译期检查该方法是否是正常的重写。
方法重写与重载的区别
方法重载:Overload
- 在同一个类中,多个方法的**方法名相同,参数列表不同(类型不同、顺序不同、个数不同)**与返回值类型、访问权限修饰符无关
- 通过相同的方法实现对不同数据的处理
方法重写:Override
- 在子类中,与父类的方法名相同,参数列表相同,返回值相同,访问权限修饰符不严于父类,抛出的异常类型不多于或大于父类方法
- 方法重写是为了增强继承过来的父类方法
Object
java.lang.Object:祖宗类
Java 中所有的类都是直接或间接继承自 Object 类,不写默认就是继承自 Object 类。
在 Object 类中定义了一系列的方法,这些方法被所有类继承。
-
toString() : String 将对象转换为字符串
// demo09.Pet@15db9742 public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
在我们之前输出对象引用时,输出的是像
demo09.Pet@15db9742
内容,原因就是因为输出方法,在方法内调用了对象的 toString() 方法,把对象转换为字符串。如果你想在输出对象时,输出对象的特征信息而不是哈希值等,在类中重写 Object 类的 toString() 方法。
-
equals(Object obj) : boolean 判断两个对象是否相等
public boolean equals(Object obj) { return (this == obj); }
String 类重写 equals() 方法:
public boolean equals(Object anObject) { // == 比较引用数据类型,比较地址值,地址值一致说明是同一个对象 if (this == anObject) { // 同一个对象不需要比较,肯定相同 return true; } // 判断要比较的是不是 String 类型 // 如果不是 String 类型没必要比较了 if (anObject instanceof String) { // 将要比较的内容转换为字符串类型 String anotherString = (String)anObject; // 获取两个字符串的长度,判断字符串长度是否一致,不一致也没必要比较了 int n = value.length; if (n == anotherString.value.length) { // 两个字符数组,1个下标1个下标的去比较字符,只要有一个字符不一致,立马返回false char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
如果以后我们要比较两个对象内容是否相同,也可以模仿 String 实现重写 equals() 方法。
-
…
equals和==的区别
如果是基本数据类型,== 可以用来比较两者的内容是否相同。
如果是引用数据类型,== 比较的是两者的地址值是否相同(如果地址值相同,代表是同一个对象)。
int num1 = 10;
int num2 = 10;
boolean flag = (num1 == num2);
equals() 方法是定义在 Object 类中的,默认是使用 == 来比较两者是否相同,所以它比较的是两者的地址值。如果你想比较两者的内容是否一致,可以模仿 String 的做法,String 对继承来的 equals() 方法进行了方法重写。