Java基础语法,面向对象-4

IDE:IntelliJ IDEA Community Edition 2024.3

JDK:jdk api 1.8

System:Windows11

继承

继承顾名思义,就是某一事物继承了某一事物的某种属性或者特质,就像是猫和狗他们都是动物,在类当中我们就可以将抽象一个动物类,让猫和狗都继承动物。

语法格式:访问限定符 class 继承类 extends 被继承类 。就像是public class Dog extends Animal

狗继承了动物,这里我们把继承类叫做子类,被继承的类叫做父类或者基类。

public class Animal {
    public String name;
    public String color;
    public int age;
    public double weight;
    public void eat () {
        System.out.println("进食");
    }
    public void sleep() {
        System.out.println("睡觉");
    }
    public void walk () {
        System.out.println("走路");
    }
}

这里以动物为父类,我们写出大多数动物都有的共性,这样子类就可以直接继承我们的父类,而不是重新把共有的属性再进行一次编写。然后我们可以在子类里面写入一些父类没有的特质。

class Dog extends Animal {
    public void bark () {
        System.out.println("汪汪叫");
    }
}

我们都知道只有狗会汪汪叫,所以我们就认为bark汪汪叫就是狗Dog类独有的特质,同时我们还继承了Animal动物类里的所有特质。

class Run {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.age=10);
        System.out.println(dog.name="小白");
        System.out.println(dog.color="白色");
        System.out.println(dog.weight=20.4);
        dog.eat();
        dog.sleep();
        dog.walk();
    }
}

当我们实例化对象时就会初始化父类和子类里的成员变量。

类似的如果是猫的话,猫特有的特质就是喵喵叫。

public class Cat extends Animal{
    public void meow() {
        System.out.println("喵喵叫");
    }
}
class Run2 {
    public static void main(String[] args) {
        Cat cat = new Cat();
        System.out.println(cat.age=10);
        cat.meow();
    }
}

父类成员访问

public class Base {
    public int a;
    public int b;
}
class Derive extends  Base {
    public int c;
    public void method () {
        a = 10;
        b = 20;
        c = 30;
    }
}

当子类没有目标变量时就访问父类继承下来的变量,a和b都是父类的,如果子类自己有目标变量就访问自己的变量。

子父类同名变量

public class Base2 {
    int a ;
    int b ;
    int c ;
}
class Derive2 extends Base2 {
    int a ;
    int b ;
    public void method() {
        a=10;
        b=20;
        c=30;
    }
}

当子类和父类有同名变量时,遵从以下:

如果访问的成员变量子类中有,优先访问自己的成员变量。 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。 如果访问的成员变量与父类中成员变量同名,则优先访问自己的。

简而言之:成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。

成员方法也使用以上原则,但是略微有些不同。

成员方法名字相同

public class Base3 {
    public void methodA(){
        System.out.println("Base3中的methodA()");
    }

    public void methodB(){
        System.out.println("Base3中的methodB()");
    }
}

class Derive3 extends Base3 {
    public void methodA(int a) {
        System.out.println("Derive3中的method(int)方法");
    }

    public void methodB() {
        System.out.println("Derive3中的methodB()方法");
    }

    public void methodC() {
        methodA(); 
        methodA(20);
        methodB();
    }
}

当出现同名方法时,如果含有参数,则会在父类和子类中寻找符合参数列表的方法,如果没有则遵从子类优先的原则。

通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到 则访问,否则编译报错。 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用 方法适传递的参数选择合适的方法访问,如果没有则报错。

super关键字

当子类和父类拥有相同的成员,我们又需要访问父类的成员,这个时候我们就要用到super关键字。

public class Base4 {
    int a;
    int b;
    public void method () {
        System.out.println("Base4中的method");
    }
}
class Derive4 extends Base4 {
    int a = 10;
    int b = 20;

    public void method(int a) {
        System.out.println(a + "Derive4中的method");
    }

    public void r() {
        super.a = 30;
        super.b = 40;
        method(1);
        super.method();
    }
}

通过super关键字就可以调用父类里面的成员。需要注意的是:super只能在非静态方法中使用,在子类方法中,访问父类的成员变量和方法。

代码块(补)

代码块分为:普通代码块,构造块,静态块。代码块其实就是用大括号引起来的代码部分。

普通代码块:定义在方法中的代码块.

构造块:构造块也叫实例代码块,实例代码块的运行和对象的实例化同步。

public class Student{
    private String name;
    private String gender;
    private  int age;
    private double score;
    
    public Student() {
        System.out.println("I am Student init()!");
    }
    
    {
        this.name = "小明";//实例代码块
        this.age = 12;
        this.sex = "男";
        System.out.println("I am instance init()!");
    }
    
    public void show(){
        System.out.println("name: "+name+" age: "+age+" sex: "+sex);
    }
 }
 
public class Main {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.show();
    }
 }

 这里用前面写过的Student类来举例。

静态代码块:一般用于初始化静态成员变量,只需要在大括号前面加上static关键字

static {
 System.out.println("Hello");
}

需要注意的是,静态代码块不管生成多少个对象,其只会执行一次 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并) 实例代码块只有在创建对象时才会执行 。

子类构造方法

子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。前面我们进行举例时并没有满足这个要求,这是因为我们在没有进行构造的情况下,编译器默认会隐性的帮我们进行构造。

public class Base {
    public Base() {
        System.out.println("Base");
    }
}
class Derive extends Base {
    public Derive() {
        //super();//这里的super如果不写编译器会自动写一个
        System.out.println("Derive");
    }

    public static void main(String[] args) {
        Derive D = new Derive();
    }
}

可以看到会先执行父类的构造方法,后再执行子类的构造方法。为了提高代码可读性,还是建议把super();调用父类构造方法写上。

在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执 行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子 肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整 ,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。

要注意:如果父类的构造方法带有参数,此时子类中一定要下写super()并且往括号里加入相符的参数,super调用父类构造方法必须写在子类构造方法内部的第一行,super()只能在子类构造方法中出现一次,并且不能和this()同时出现。

初始化时的执行顺序

 

public class Base {
    public Base() {
        System.out.println("父类构造");
    }
    {
        System.out.println("父类实例");
    }
    static {
        System.out.println("父类静态");
    }
}
class Derive extends Base {
    public Derive() {
        super();
        System.out.println("子类构造");
    }
    {
        System.out.println("子类实例");
    }
    static {
        System.out.println("子类静态");
    }
}
class Run {
    public static void main(String[] args) {
        Derive D1 = new Derive();
        System.out.println("===============================");
        Derive D2 = new Derive();
    }
}

父类静态代码块优先于子类静态代码块执行,且是最早执行,父类实例代码块和父类构造方法紧接着执行,子类的实例代码块和子类构造方法紧接着再执行,第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行 。

顺序可以总结为:父类静态,子类静态,父类实例,父类构造,子类实例,子类构造。其中静态不管初始化几次都只执行一次。

组合

class Tire{

}
class Engine{

}
class VehicleSystem{

}
class Car{
    private Tire tire;        
    private Engine engine;      
    private VehicleSystem vs;  
}
class Benz extend Car{
    // 将汽车中包含的:轮胎、发送机、车载系统全部组合继承下来
}

protected 关键字

为了实现封装特性,Java中引入了访问限定符,现在最后一个protected关键词可以说了,protected的权限大于default,但是它可以让被修饰的类的子类在不同的包中被访问。这里就不用代码具体举例了。

访问修饰限定符的权限总结

从小到大权限:

private:只能同一个包同一个类访问

default:可以同一个包不同类间访问

protected:可以同一个包不同类间访问,还可以不同包中的子类访问

public:随便访问

-4到这里结束了,后续内容会持续更进,如有错误欢迎指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值