类的继承,以及类的调用
extends 子类继承父类
super 调用父类的变量或者方法
继承的使用场景:定义的多个类中有共性的内容,优点:减少代码量
继承的热点:
继承不支持多继承,不能同时继承多个类
继承支持单层继承,多层继承
一个父类可以拥有多个子类
子类父类的重名函数的覆盖(重写)
子类创建的对象调用重名函数:子类的重名函数会覆盖掉父类的函数,即执行的是子类中的重名函数方法体
注意:
- 子类继承父类后,可以拥有父类中非私有的内容
- 构造方法不能被继承(因为构造方法的方法名是根据本类来的)
方法的重写:
前提:子父类继承关系
注意:
1、子类方法覆盖父类方法,必须保证权限大于等于父类权限
public protected 默认(default) private
2、子类方法覆盖父类方法,返回值类型、函数名和参数列表要一致
3、私有方法不能被重写(父类私有成员子类是不能继承的)
4、子类方法重写父类时,子类的方法返回值要是父类方法的返回值的子类或者一样
class A{
int a=10;
public A(){}
public void ADemo(){
System.out.println("这是A父类");
}
//重名函数Print
public void Print(){
System.out.println("这是父类的重名函数!");
}
}
class B extends A{
int b=10;
//构造方法的话,先执行父类的构造方法初始化参数,在子类中有隐藏的super调用父类构造方法
public B(){}
public void BDemo(){
//子类中调用父类的变量
super.a=20;
//子类中调用父类的方法
super.ADemo();
System.out.println(a);
System.out.println("这是B子类");
}
public void Print(){
System.out.println("这是子类的重名函数!已经覆盖父类的函数");
}
}
public class Extends {
public static void main(String[] args) {
B b = new B();
b.ADemo();
b.BDemo();
//子类调用重名函数
b.Print();
/*除非用父类创建对象,才可以调用父类中的重名函数
A a = new A();
a.Print();*/
}
}
继承中成员变量及方法访问特点:
成员变量和方法不重名:
父类对象只能调用自己的成员变量和成员方法不能调用子类的成员变量和方法
子类对象可以调用父类的成员变量和成员方法,也可以调用自己特有的方法
成员变量和方法重名:
父类对象只能调用自己的成员变量和成员方法不能调用子类的成员变量和方法
子类对象调用的重名函数和重名的成员变量实现的是子类中的成员变量和方法
class A {
int i = 10;
public void run() {
System.out.println("run");
}
}
class B extends A {
int i = 20;
int b = 20;
public void run() {
System.out.println("子类中的run");
}
public void run1() {
System.out.println("run1");
}
}
public class Array {
public static void main(String[] args) {
//父类调用子类不重名的成员变量和方法是不行的
A fa = new A();
//System.out.println(fa.b);//报错
//fa.run1();//报错
//父类无法调用子类的重名函数,只能调用本类的成员变量和方法
fa.run();
System.out.println(fa.i);
}
}
注意当父类的成员变量,子类的成员变量,子类的局部变量都重名时,优先访问子类的局部变量
super代表的是父类成员,可以区分子类和父类重名的成员空参构造。注意:如果自己定义了父类和子类的无参构造方法,调用子类对象时,首先执行的是父类的构造方法,然后执行的是子类的构造方法。
子类中的构造方法中第一行默认会有一个super(),它代表的时父类的空参构造。
子类中如果写了有参勾选,默认第一行会调用父类的有参构造,如果子类的有参构造中将super(参数)去掉,就去找父类的无参构造
匿名对象
匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址赋值给某个变量
每创建一次匿名对象就要分配一次内存空间,缺点:浪费资源。
使用场景:一般用于单纯的调方法
如果使用匿名对象对属性进行赋值,再用匿名对象取值是不可以的,会产生多个对象
class A{
public void run(){
System.out.println("run");
}
}
public class Array {
public static void main(String[] args) {
//创建匿名对象并调用类中方法
new A().run();
}
}
this--->代表的是当前对象
作用:区分成员变量和局部变量重名的问题
使用本类的成员变量:在本类中 this.成员变量
调用本类的方法:this.方法名
调用本类的构造方法 this(参数)
this和super在构造方法中不能同时出现。
this在有参,空参构造方法中不能相互调用。
扩展:Object类是所有类的父类。
定义抽象类以及抽象方法
抽象类的作用一般是:
方便开发者知道调用方法的数量以及方法的作用,便于修改
抽象方法没有方法体,用修饰符 abstract来修饰
注意:
抽象方法所在的类一定是抽象类
抽象类中不一定非得有抽象方法
抽象类中除了有抽象方法还可以有构造方法,成员变量,普通方法,get、set方法
抽象类不能new对象
抽象类的子类,必须重写抽象父类中的所有抽象方法,否则编译无法通过报错
//定义抽象类Animal
public abstract class Animal {
private String name;
private int age;
public Animal() {
System.out.println("无参构造函数");
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参构造函数");
System.out.println(name + "的年纪是:" + 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 abstract void eat();
public abstract void sleep();
}
//抽象类的方法的具体实现
public class Dog extends Animal {
public Dog() {
}
public Dog(String name, int age) {
super(name,age);
}
public void eat() {
System.out.println("狗喝水");
}
public void sleep() {
System.out.println("狗睡觉");
}
}
//创建子类对象并调用方法
public class Test {
public static void main(String[] args) {
Dog dog=new Dog("斑点狗",5);
dog.eat();
dog.sleep();
}
}