目录
继承
1.什么是继承
在已有类的基础上,对这些类进行扩展,使得新类具有更加丰富的属性和方法,(可以类比为你遗传了你爸爸的基因,但同时你有你自己的比较独特的基因,区别继承是新的类会遗传旧的类里面所有的属性和方法,并且拥有新的属性和方法而你只是遗传一半的基因然后有自己区别于你爸爸的独特的基因)
新类叫子类或扩展类或派生类,旧类叫父类或基类或超类
2.继承的作用
继承的基本作用:代码的复用(有的时候一些类不能满足所有的需求只能满足部分需求,此时需要一个新的类既要有旧类里面的内容又要有新的东西,此时选择用继承的方式来复用原有的代码。就不需要重新再来写一遍旧类的内容了)
继承的重要作用:继承是多态的基础,同时也是方法重写的前提
3.继承的语法格式
【访问权限修饰符】 class 新类名 extends 旧类名{属性;方法}
public class Old{
private String name;
public Old(){
}
public Old(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
}
public class New extends Old{
}
4.继承有哪些特点
1.单继承,一个类只能继承一个类,不可以继承多个类
2.间接继承(虚假的多继承),如果想实现类似多继承的效果,可以多次继承:你的爸爸继承你的爷爷,你继承你的爸爸
3.祖宗类,不论你写不写,所有的类都有个父类:Object类
4.继承的内容就是除了构造方法以外所有的东西(private修饰的东西也会继承)
5.当类被final修饰的时候无法被继承
6.当创建子类的对象的时候会优先加载父类的构造方法,后加载子类的构造方法(因为在子类的构造方法中无论程序员是否调用父类的构造方法,jdk都会在子类的构造方法中默认给你添加上父类的无参构造方法,就算你重写了子类的无参构造方法的时候没有在这里面写调用父类构造方法也没用,他还是会给你默认添加在子类构造方法第一行,只是你看不到)
public class Father{
private String name;
private int age;
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public void setName(String name){
this.name = name;
}
public void setAge(int name){
this.age = age;
}
//无参的构造方法
public Father(){
}
//有参的构造方法,假如就只传入人的名字
public Father(String name){
this.name = name;
}
//有参的构造方法,假如同时传入名字和年龄
public Father(String name,int age){
this.name = name;
this.age = age;
}
}
public class Son extends Father{
private int height;
//像下面这样不在子类构造方法里面申明父类构造方法,jdk一样会给你在第一行默认调用父类的无参构造方法
public Son (){
}
/*如果在子类构造方法里面调用父类的有参构造方法,那么父类当中一定要有对应的有参构造方法,而且还要让*调用构造方法写在子类构造方法的第一行*/
public Son (String name , int age){
super(name,age);
}
public Son (int height,String name){
super(name);
this.height = height;
}
public int getHeight(){
return this.height;
}
public void setHeight(int height){
this.height = height;
}
}
public class Test {
public static void main(String[] args) {
//打印通过子类创建的对象的相关信息(根据之前的内容可以知道在构造方法当中没有赋值就会赋值为默认初始值)
//1.传递了名字和年龄,那么调用没有传递的身高就会被默认为0
Son a = new Son("屌丝",15);
System.out.println("name = "+a.getName()+",age = "+a.getAge()+",height = "+a.getHeight());
//2.传递了名字和身高,那么调用没有传递的年龄就会被默认为0
Son b = new Son(178,"牛马");
System.out.println("name = "+b.getName()+",age = "+b.getAge()+",height = "+b.getHeight());
//3.啥也没传递进去,那么都是默认值
Son c = new Son();
System.out.println("name = "+c.getName()+",age = "+c.getAge()+",height = "+c.getHeight());
}
}
上述程序执行结果如下:
name = 屌丝,age = 15,height = 0
name = 牛马,age = 0,height = 178
name = null,age = 0,height = 0
5.什么时候使用继承
旧类是一个新类的时候:
eg:猫是动物,狗是动物,猫类是动物类的子类,狗类是动物类的子类
6.super关键字
1.super是java的关键字
2.this可以出现在类的方法当中表示当前对象,super也可以放在类的方法中表示当前对象
3.this.属性或方法,super.属性或方法,其实操作的是统一个方法同一块内存空间,this()是构造一个当前类的对象,super()是构造一个父类的对象
4.this.和super.在调用父子共有的属性和方法时操作的是同一块空间
5.super(【形参列表】)只能放在构造方法第一行,不论是否有该方法的显式调用,都会默认在构造方法的第一行添加上父类的无参构造方法,如果有显式调用(明面上写了一遍调用),那么按照显式调用的规则进行(本条与上面那个4里面的第六条类似)
6.super()和this()不可以同时出现在构造方法中
7.this和super分别什么时候不可以省略
this大部分时候可以省略,当用于区分到底是成员属性还是形参(局部变量)的时候不能省略
在父子继承中,如果有相同的属性和方法,区分子类还是父类的时候不可以省略
8.this关键字和super关键字不出现在static修饰的方法当中,因为this是与对象相关的,但是static是与类相关的
//与上一个段代码相比,下列代码仅多出如下内容
//子类中:
public void setThisName(){
this.setName("子类名字");
}
public void showSuperName(){
//通过同时打印this.getName()和super.getName()可以确定操作的this.和super.在此处操作的其实是同一块空间
System.out.println(this.getName());
System.out.println(super.getName());
//通过this关键字来更改weight,然后打印super.weight和this.weight意识到打印结果是相同的,可以确定操作的this.和super.在此处操作的其实是同一块空间
this.weight = 6;
System.out.println(this.weight);
System.out.println(super.weight);
//综合setThisName()和showSuperName()方法可以知道this.和super.在调用父子共有的属性和方法时操作的是同一块空间
}
//测试类中:
b.setThisName();
b.showSuperName();
//所以最新的三个类分别是
public class Father {
private String name;
private int age;
int weight;
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public void setName(String name){
this.name = name;
}
public void setAge(int name){
this.age = age;
}
//无参的构造方法
public Father(){
}
//有参的构造方法,假如就只传入人的名字
public Father(String name){
this.name = name;
}
//有参的构造方法,假如同时传入名字和年龄
public Father(String name,int age){
this.name = name;
this.age = age;
}
}
public class Son extends Father{
private int height;
//像下面这样不在子类构造方法里面申明父类构造方法,jdk一样会给你在第一行默认调用父类的无参构造方法
public Son (){
}
/*如果在子类构造方法里面调用父类的有参构造方法,那么父类当中一定要有对应的有参构造方法,而且还要让*调用构造方法写在子类构造方法的第一行*/
public Son (String name , int age){
super(name,age);
}
public Son (int height,String name){
super(name);
this.height = height;
}
public int getHeight(){
return height;
}
public void setHeight(int height){
this.height = height;
}
//这个方法用来更改子类对象的名字
public void setThisName(){
this.setName("子类名字");
}
public void showSuperName(){
//通过同时打印this.getName()和super.getName()可以确定操作的this.和super.在此处操作的其实是同一块空间
System.out.println(this.getName());
System.out.println(super.getName());
//通过this关键字来更改weight,然后打印super.weight和this.weight意识到打印结果是相同的,可以确定操作的this.和super.在此处操作的其实是同一块空间
this.weight = 6;
System.out.println(this.weight);
System.out.println(super.weight);
//综合setThisName()和showSuperName()方法可以知道this.和super.在调用父子共有的属性和方法时操作的是同一块空间
}
public class Test {
public static void main(String[] args) {
//打印通过子类创建的对象的相关信息(根据之前的内容可以知道在构造方法当中没有赋值就会赋值为默认初始值)
//1.传递了名字和年龄,那么调用没有传递的身高就会被默认为0
Son a = new Son("屌丝",15);
System.out.println("name = "+a.getName()+",age = "+a.getAge()+",height = "+a.getHeight());
//2.传递了名字和身高,那么调用没有传递的年龄就会被默认为0
Son b = new Son(178,"牛马");
System.out.println("name = "+b.getName()+",age = "+b.getAge()+",height = "+b.getHeight());
//3.啥也没传递进去,那么都是默认值
Son c = new Son();
System.out.println("name = "+c.getName()+",age = "+c.getAge()+",height = "+c.getHeight());
b.setThisName();
b.showSuperName();
}
}
运行结果是:
name = 屌丝,age = 15,height = 0
name = 牛马,age = 0,height = 178
name = null,age = 0,height = 0
子类名字
子类名字
6
6
7.方法重写
1.什么时候需要方法重写
当现有的代码方法(从父类那里继承来的)无法满足需求的时候(不满足子类的需求)需要进行方法的重写,在“多态”的时候会有例子。
2.重写的标志
方法重写的时候要在方法重写前声明一句@Override
3.如何重写
在子类中把父类的方法体重写
4.重写的特点
1.重写的是方法不是属性
2.私有方法和final修饰的无法重写
3.重写的方法必须和原有方法返回值类型相同,方法名相同,参数列表相同,而且访问权限修饰符不能变的更小,(重写的方法的返回值类型可以是原有方法中返回值类型的子类(向上转型自动转型))
5.重写和重载的区别
重载在一个类当中发生,重写发生在有继承关系的类当中
重载方法名相同,参数列表不同(个数,类型,顺序)
重写方法名相同,参数列表相同,返回值类型相同,访问权限修饰符不能变小
//假如每个动物都有一种方法就是吃了东西会长肉,
//猫吃了长食物重量的一半,狗吃了长食物重量的30%
public class Anamail{
private int height;
public double add(int foodWeight){
return height+foodWeight;
}//这是要被重写的方法
public Anamail(){
}
public Anamail(int height){
this.height = height;
}
public int getHeight(){
return this.height;
}
public void setHeight(int height){
this.height = height;
}
}
public class Cat extends Anamail{
public Cat(){
}
public Cat(int height){
super(height);
}
@Override
public double add(int foodWeight){
return super.getHeight()+0.5*foodWeight
}
}
public class Dog extends Anamail{
public Dog(){
}
public Dog(int height){
super(height);
}
@Override
public double add(int foodWeight){
return super.getHeight()+0.3*foodWeight;
}
}
public class Run {
public static void main(String[] args) {
Cat a = new Cat(6);
Dog b = new Dog(10);
System.out.println(a.add(10));
System.out.println(b.add(10));
//如果方法没有重写,那么a和b执行的都是父类中的直接相加的方法
//但是重写了方法之后,执行的是重写后的方法
}
}
运行结果是:
11.0
13.0