继承中的知识点
继承中的知识点
关于重载
- 方法名相同,参数不同,返回类型不受限制
- 参数不同和参数类型有关,和参数名称无关
- 需要在同一个类体里面
- 和修饰符和返回类型无关
一个子类只能有一个父类
子类只能继承父类所有的非私有成员
关于重写
1、如果父类方法返回类型是基本数据类型,那么子类的返回类型必须和父类的返回类型一致;
如果父类方法返回类型是引用的数据类型(定义的对象),那么子类的方法可以不和父类一致,但返回类型可以是父类和 父类的子类(协变)
2、子类方法可以重写父类的属性
3、访问修饰符:子类重写方法修饰符的范围必须大于等于父类方法修饰符的范围(子类范围只能比父类范围更高)
方法调用
重载解析
调用一个对象的方法x.getSum(int param);虚拟机会为x指向的对象的所有方法创建一个方法表,然后编译器从中找出所有getSum()的方法,再根据传参类型最终找到对应的方法,找不到就报错,这个过程叫重载解析
动态调用
同上重载解析
静态调用
被private,static,final修饰的方法或者构造器,编译器直接就可以找到调用,该调用方式为静态调用
继承中的方法调用(默认可列举object类方法)
调父类方法会把父类中所有方法列举在“方法表”中
调子类方法会把父类和子类所有方法列举
访问修饰符
public:本类、可跨包、继承关系
private:只能本类自己访问
protected:当前类、同包类、垮包子类
默认:当前类、同包类,跨包类不允许
private<默认<protected<public
super关键字(继承关系):子类对父类对象的引用=>访问编译器
-
子类的构造过程中必须调用父类的构造方法
父类的构造方法不允许继承(不能被拿来直接用)=》不能被重写,但也要有,因为它会影响子类的实例化过程
-
在子类中的构造器中,需要对父类进行初始化
-
子类的构造函数没有对父类初始化的话,子类的构造方法会默认调用父类的无参构造,若父类没有无参构造,子类的构造会报错
例外:父类只有一个有参构造,子类中用super指向了父类的有参,也不会报错
子类构造函数默认找父类无参构造函数,找不到报错,这时用super指定另一个存在的构造函数,就不会报错
-
可通过super调用其他有参的构造方法,和this调用其他构造方法相同,必须放在方法的第一行,两个不能同时使用
构造方法的调用必须放在构造方法里
继承关系中的初始化顺序
按照静态代码块>代码块>构建方法的顺序从子类出发找到顶级父类在下来
父静态代码块,子静态代码块,父类代码块,父类的构造方法,子类代码块,子类的构造方法
Object类
equals方法
object中的equals比较的是两个引用在内存中的地址是否相同
public boolean equals(Object obj) {
return (this == obj);
}
String类型重写了equals只来比较字符串的内容是否相等
我们可以通过在类中重写equals的方法来定义比较规则
//重写了equals来比较两个对象内的名字和性别是否相同
@Override
public boolean equals(Object obj) {
if(obj==null)//这里一样要判空
return false;
if (this==obj)//引用是否相同
return true;
if (this.getClass()==obj.getClass())//类名是否相同
return true;
//强转成本类
People obj1 = (People) obj;//类型转化可能会有危险
if (this.getName().equals(obj1.getName()) && this.getGender()==obj1.getGender())
return true;
else
return false;
}
也可以限制传入参数类型
@Override
public boolean equals(People p1) {
if(obj==null)//这里一样要判空
return false;
if (this.getName().equals(p1.getName()) && this.getGender()==p1.getGender())
return true;
else
return false;
}
toString方法
object中的toString方法会返回对象的字符串表示形式
当直接输出对象名时,会访问Object的toString()方法,以类型信息@地址信息的形式打印
com.imooc.object.People@1b6d3586(类名+散列码)
子类可以通过重写toString()方法来自定义打印的内容
@Override
public String toString() {
return "姓名:"+this.name+",年龄:"+this.age+",性别:"+this.gender;
}
//打印姓名:han,年龄:19,性别:男
final关键字
-
修饰的类:没有子类,final修饰后该类所有方法变为final方法
-
修饰的方法(非构造方法):不能被重写,但能被子类继承和调用
-
方法内的局部变量:使用之前赋值,且赋值后不能被修改
-
成员属性:必须在类构造的过程中对他赋值
- 直接赋值
- 构造方法中
- 构造代码块中
-
引用类型:引用一次后不能修改,但内部的属性可以被修改
注解@Override
标注在方法上,说明是对父类方法的重写,标注后他会检查父类是否有这样一个方法,没有会报错
==(比较变量中存储的值)
-
比较的是基本数据类型时,比较的是值
-
比较的是引用数据类型时,变量中存储的是地址,所以就比较的地址
抽象类
从子类中抽象出来的方法不知道写什么具体的内容可以把方法定义成抽象方法
public abstract void raiseSalary();
注意
- 定义方法为抽象方法时,父类也得定义成抽象类
- 没有抽象方法的类也可以定义成抽象类
- 抽象类不允许实例化,但能指向(引用)一个非抽象子类的地址
- 抽象类中也可以有普通方法和属性
构造方法
构造方法有必要和set'方法共存吗
万一你用构造方法创建后想修改呢