Java面向对象编程语法知识点

Java面向对象编程语法知识点,第1张

目录

一、封装

二、继承

1、继承的作用

2.继承的表示方法

3.隐式继承private

4.继承的权限

三、super关键字

1.super修饰属性

2.super修饰构造方法

3.super修饰普通方法和属性

4、final

四、多态

1.向上转型

2.多态的方法重写

4.重写权限

5、向上转型三种发生方式

6.构造方法和多态

7.关于方法的调用

五、向下转型:

1.向下转型风险

六、抽象类

1.Java中定义抽象类规则

七、接口

1.而接口的使用表示两种场景

2.接口表示能力


一、封装

封装: 使用private将属性进行封装(这个属性只在当前类的内部可见,对外部隐藏)

保护性、易用性(通过程序对外提供的方法来 *** 作属性),例如汽车启动,电脑启动等隐藏在内部的过程。

二、继承 1、继承的作用

例子

定义了三个类,Animal类、Cat类、Dog类

public class Animal {
    public String name;
    public void eat(String food){
        System.out.println(this.name + "正在吃" + food);
    }
}
public class Cat {
    public String name;
    public void eat(String food){
        System.out.println(this.name + "正在吃" + food);
    }
}
public class Dog {
    public String name;
    public void eat(String food){
        System.out.println(this.name + "正在吃" + food);
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.name = "动物";
        animal.eat("食物");
        Dog dog  = new  Dog();
        dog.name = "旺财";
        dog.eat("狗粮");
        Cat cat = new Cat();
        cat.name = "小白";
        cat.eat("猫薄荷");
    }
}

 

 不难发现他们都有重复的代码段,按道理说所有Animal的类都应该具备name属性以及eat方法。

所以需要继承来简化代码

当类和类之间满足一个类is a另外一个类,—定是存在继承关系,就像

Dog is an Animal,狗是动物
Cat is an Animal,猫是动物
天然的继承,还有

Bird is an Animal
Duck is an Animal

2.继承的表示方法

子类extends父类

例如上面代码可以简化成一行

public class Cat extends Animal {

}
public class Dog extends Animal {

}

当一个类继承了另一个类,另一个类中所有的属性和方法子类就天然具备了。

注意点,Java不允许多重继承

子类无法继承两个父类,下列代码会报错

public class Cat extends Dog, Animal {

}

但是允许多重继承

多重继承

 bird是Animal的子类,sparrow既是bird也是Animal的子类,extends后面只能跟一个父类。

3.隐式继承private

实际上被继承了,但是无法被子类直接使用

public class Animal {
    public String name;
    private int age;//子类无法通过 . 来直接访问这个属性
    public void eat(String food){
        System.out.println(this.name + "正在吃" + food);
    }
}

 可以通过父类提供的方法

public class Animal {
    public String name;
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.name = "小白";
        cat.setAge(3);//此时可直接使用age
        cat.eat("猫薄荷");
    }
}

可见age被cat从Animal继承来了,因为cat类没有定义过任何属性方法,全是extends继承来的。

注意点

静态的属性和方法是归于某个类所有
当一个类继承了另一个类,所有静态属性和方法就继承。
到底能否直接使用,还是要看权限是不是public,如果是private就要通过父类提供的方法使用

总结
a.要能使用继承,前提必须满足类之间的is a关系

b.—个子类只能使用extends继承一个父类。(单继承)
Java中不允许多重继承,extends后面只能跟一个父类,允许多层继承,没法当儿子,可以当孙子。
c.子类会继承父类的所有属性和方法,有两种继承方式

显示继承(public属性和方法可以直接使用)

隐式继承(private属性和方法),子类其实也继承了这个属性和方法,但是无法直接使用。

4.继承的权限

private < default < protected < public

protected访问权限,只在当前类和同包中的不同类中以及不同包中的子类中是可见的

public class Animal {
    //当前类和子类是可见的
    protected String name;
    private int age;
}

不同包中的有继承关系的类可见

package Person;

import Animal.Animal;

public class person extends Animal {
    public void fun(){
        //name属性为protected,不同包中的有继承关系的子类是可见的
        System.out.println(name);
    }
}

注意点

package Person;
public class Test {
    public static void main(String[] args) {
        Person person = new person();
        per.name;
    }

}

 test和Animal没有继承关系,且是person包中,因此name是不可见的

总结

default同包可见 + 继承关系可见 = protected

三、super关键字

类比于this关键字

this关键字∶表示当前对象的引用
修饰属性,表示直接从当前类中找同名属性

super关键字
修饰属性,表示直接从父类中去寻找同名属性
修饰方法,表示直接从父类中去寻找方法

理解

在认识super前要先知道一个知识

public class Animal {
    //当前类和子类是可见的,对于没有继承关系的类是不可见的
    public Animal(){
        System.out.println("产生父类对象,调用父类构造方法");
    }
}



public class person extends Animal {
    public person(){
        System.out.println("产生子类对象,调用子类对象方法");
    }
}


public class Test {
    public static void main(String[] args) {
    person person = new person();
    }

}

当调用new Person无参构造产生子类对象之前,先默认调用父类的构造方法产生父类对象然后才会执行子类的构造方法,产生子类对象。

相关面试题

public class B {
    public B(){
        System.out.println("1.B的构造方法");
    }
    {
        System.out.println("2.B的构造块");
    }
    static{
        System.out.println("3.B的静态方法块");
    }
}



public class C extends B{
    public C(){
        System.out.println("4.C的构造方法");
    }
    {
        System.out.println("5.C的构造块");
    }
    static{
        System.out.println("6.C的静态代码块");
    }

    public static void main(String[] args) {
        System.out.println("7.main开始");
        new C();
        new C();
        System.out.println("8.main结束");
    }
}

执行结果

3.B的静态方法块
6.C的静态代码块
7.main开始
2.B的构造块
1.B的构造方法
5.C的构造块
4.C的构造方法
2.B的构造块
1.B的构造方法
5.C的构造块
4.C的构造方法
8.main结束

解析

一、由于main存在于C子类中,若JVM要调用main,首先要加载主类,一旦加载主类,执行主类的静态块,

二、C继承了B,先加载父类才加载子类

3(父类的静态块)->6(才加载子类的静态块)
类加载结束后,进入主方法,7.main的开始
三、产生子类对象,先要产生父类对象,先调用构造块,接下来才是构造方法,

所以先调用父类的构造块2,然后调用父类构造方法1,父类对象产生完毕,之后子类构造块5,子类构造方法4,最后子类对象产生完毕
四,重复三

最后8.main结束。

1.super修饰属性
public class person {
    protected String name = "person";
}




public class China extends person {
    protected String name = "china";

    public void fun() {
        //在访问成员变量的时候,建议写上this,尤其是有继承的时候,不容易混淆
        System.out.println(name);//这里的name相当于this.name
    }

    public static void main(String[] args) {
        China china = new China();
        china.fun();
    }
}

输出为 China

当有继承关系时
this关键字默认先在当前类中寻找同名属性,若没找到,继续向上寻找父类中是否有同名属性
直接使用name,编译器默认都是this.name

如果非要使用父类的同名属性,使用super关键字,直接从父类寻找

public class person {
    protected String name = "person";
}




public class China extends person {
    protected String name = "china";

    public void fun() {
        //在访问成员变量的时候,建议写上this,尤其是有继承的时候,不容易混淆
        //使用super关键字从父类找寻同名属性
        System.out.println(super.name);
    }

    public static void main(String[] args) {
        China china = new China();
        china.fun();
    }
}

输出为 person

注意点,

一、如果父类被private修饰,是无法用super直接被访问的

二、super中多层继承的情况

如果Animal是Person的父类,Person是China的父类,那么

super先从直接父类中寻找同名属性,若不存在再向上寻找
同样的,this直接从当前类中找同名属性,若不存在再向上搜索。

 当多层继承中出现private,结果会报错

2.super修饰构造方法

super(父类构造方法的参数)
super();/直接父类的无参构造,可写可不写

注:若父类中不存在无参构造,则子类构造方法的首行必须使用super(有参构造)

例子

public class Animal {

    public Animal(){
        System.out.println("Animal的无参构造");
    }

    protected String name = "animal";
}


public class Person extends Animal{

    public Person(){
        System.out.println("Person的无参构造");
    }
    protected String name = "person";
}




public class China extends Person{
    public String name = "china";

    public China(){
        System.out.println("China的无参构造");
    }

    public static void main(String[] args) {
        China china = new China();
    }
}

上述执行结果应该是

Animal的无参构造

Person的无参构造

China的无参构造

这是因为当产生子类对象时,默认先产生父类对象,若父类对象还有父类,继续向上,先产父类对象的父类对象

这是因为在子类的构造方法的第一行中隐藏了一条语句  super(),所以若当父类中没有无参构造时,我们不能省略,并且还要传入参数。

例子

public class Person{
    protected String name = "person";

    public Person(String name){
        this.name = name;
        System.out.println(this.name + "Person的有参构造");
    }
}
public class China extends Person{
    public String name = "china";

    public China(){
        super(name:"父类");//给super传入参数访问父类
        System.out.println("China的无参构造");
    }

    public static void main(String[] args) {
        China china = new China();
    }
}

注意点

在一个构造方法中无法显式使用this()和super()同时出现,但如果父类中存在无参构造,可以单独使用this(), 而super()可以隐藏。

public China(String name){
//下列这样会报错
        super("父类");
        this();
        this.name = name;
        System.out.println("China的有参构造");
public China(String name){
    //此处有隐藏的super()调用的无参构造
    this();
    this.name = name;
    System.out.println("China的有参构造");
}
3.super修饰普通方法和属性
public void test(){
    super.fun();//直接从父类中调用fun方法
}

super关键字类似于一种指示器,告知你到父类中去寻找,而不是引用父类对象,和this有区别

public void test(){
    System.out.println(this);
    System.out.println(super);//不能这样使用
}
4、final

final修饰属性

表示属性值不能变,常量

final修饰类

表示这个类无法被继承

四、多态

理解:一个引用可以表现出多种行为/特性=>多态性
多态的向上转型:

例如

Dog dog = new Dog(); / /最常见的

类名称  类引用= new 该类对象();

但是也可以这样写:
Animal animal = new Dog();//向上转型
父类名称  父类引用= new  子类对象();

子类is a子类     Dog is a dog
但是同样,子类is a父类   Dog is Animal

1.向上转型

条件

只发生在有继承关系的类之间,不一定是直接子类,也可以是子类的子类。

向上转型的意义

最重要的是在于参数统一化,降低使用者的使用难度。

例子

public class Test {
    public static void main(String[] args) {

    }
    
    public static void fun(Animal animal){}
    public static void fun(Bird bird){}
    public static void fun(Duck duck){}

}

 上例代码中

1.作为类的实现者
fun方法接收AnimaL以及其子类的对象作为参数
假设现在没有向上转型,AnimaL有多少子类,就得重载多少次fun方法,大自然Animal动物子类有几百万种,就有几百万种子类,fun就得写上百万次

2.作为类的使用者,程序的使用者
如果没有向上转型,我们要使用fun方法的话,就得了解Animal以及其子类的所有对象才能知道我们到底调用的是谁

使用向上转型后

public class Test {
    public static void main(String[] args) {
        fun(new Animal());
        fun(new Bird());
        fun(new Duck());

    }

    public static void fun(Animal animal){}


}

继承关系最顶层的父类引用就可以指代所有子类对象,

如果多了一个类pig,也只需要写fun(new Pig())即可。

2.多态的方法重写
public class Animal {
    public void eat(){
        System.out.println("Animal 的eat方法");
    }
}
public class Duck extends Animal{
    public void eat(){
        System.out.println("Duck 的eat方法");
    }
}
public class Bird extends Duck{
    public void eat(){
        System.out.println("Bird 的eat方法");
    }
}
public class Pig extends Animal{
    public void eat(){
        System.out.println("pig 的eat方法");
    }
}
public class Test {
    public static void main(String[] args) {
        fun(new Animal());
        fun(new Duck());
        fun(new Bird());
        fun(new Pig());
    }

    public static void fun(Animal animal){
        animal.eat();
    }
}

 执行结果

Animal 的eat方法

Duck 的eat方法

Bird 的eat方法

Pig 的eat方法

fun方法接收的参数是Animal类的引用,却调用了所有类的eat()方法,这种情况就是方法重写,

fun中animal局部变量的引用调用eat方法时,当传入不同的对象时,表现出来了不同的eat方法行为,也叫多态性

简单来说:

同一个引用(变量名称),同一个方法名称根据对象的不同表现出来了不同的行为

方法重载和方法重写区别:

方法重载(overload):发生在同一个类中,定义了若干个方法名称相同,参数列表不同的一组方法。
方法重写(override) :发生在有继承关系的类之间,子类定义了和父类除了权限不同,其他全都相同的方法,这样的一组方法称之为方法重写。

方法重写例子

public class Animal {
    public void eat(){
        System.out.println("Animal 的eat方法");
    }
}
public class Duck extends Animal{
   //此时就是方法重写
    public void eat(){
        System.out.println("Duck 的eat方法");
    }
}

注意点

方法重写的返回值是可以不同,但是返回值类型必须相同

如何知道方法重写后 到底调用的是谁的方法呢

不用去看前半部分,看当前是通过哪个类new的对象,若该类重写了相关方法,则调用的一定是重写后的方法。
只要new的这个对象的类中覆写了同名方法,则调用的一定是覆写后的方法。

若子类没有重写这个方法呢?

就近匹配规则,调用碰到的最接近父类的调用方法,即向上搜寻到的第一个

4.重写权限

子类权限必须 >= 父类权限才可以重写

因为子类是继承父类的,那么父类中有的,子类肯定要有,也就是说子类中继承来的方法在权限上至少应该等于父类的权限

特例

父类方法使用private  子类方法使用public,是不可以方法重写的

private权限不包含在内

但是有种特殊情况,把主方法写在父类中

public class Animal {
    public static void main(String[] args) {
        Animal animal = new Bird();
        Animal animal1 = new Duck();
        fun(new Bird());
        fun(new Duck());
}
    public static void fun(Animal animal){}


}

执行情况

Bird 的eat方法

Duck 的eat方法

主方法定义在父类中时,会直接向上寻找在父类中eat方法,因为父类中的方法是private权限无法被重写,即便是向上转型了,也不会去子类中寻找重写的方法。

Java中有一个注解@Override
使用这个注解写在重写方法之前,帮你校验你的方法重写是否符合规则。

5、向上转型三种发生方式

public static Animal test(){
//方法返回值
    Dog dog = new Dog();
    return dog;
}
       //引用赋值时
        Animal animal = new Bird();
        Animal animal1 = new Duck();
        //方法传参时
        fun(new Bird());
        fun(new Duck());
6.构造方法和多态
public class B {
    public B(){
        fun();
    }
    public void fun(){
        System.out.println("B的fun方法");
    }
}
public class D extends B{
    private int num = 10;

    public void fun(){
        System.out.println("D的fun方法, num = " + num);
    }

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

输出

D.fun(),num = 0;

解析

创建D的对象的时候调用D的无参构造,因为D extends B,就会优先调用B的构造方法,先产生父类对象,

进入B的构造方法执行fun方法,new子类对象,会存在方法覆写,先执行子类中覆写的fun方法,D中的num还没有初始化,输出num = 0,

执行完fun方法之后,回到D的构造方法,最后为num进行显式初始化

7.关于方法的调用

假设此时Dog类中有一个扩展方法play()
这个方法Animal类中不具备,此时还能通过animal.play();进行调用吗?

 解析

这里能否访问该方法,是由类名称说了算的
能访问的这些方法必须都在类中定义过,编译器会先在类中查找是否包含指定方法
至于这个方法到底表现出来是哪个类的样子,由实例所在的方法说了算

关键是要看new的实例是通过哪个子类new的,以及该子类是否重写了fun()方法
到底能.哪些方法前面说了算,到底.之后这个方法长啥样,后面new的说了算

五、向下转型:

子类名称 子类引用=(子类名称 )父类引用

要发生向下转型,首先要发生向上转型。

Animal animal = new Animal();//本身就只是一个Animal对象,和Dog毫无关系

//要发生向下转型首先父类引用就是通过该类向上转型产生的。

//本质上是个dog,披了个Animal的外衣,此时只能调用Animal中定义的方法

Animal animal = new Dog();

Dog dog = (Dog) animal;
毫无关系的两个类之间没法强转(int boolean)

向下转型目的: animal和dog这两个引用都指向同一个对象,而没有创建新的对象,然后通过向下转型之后的引用执行父类中没有子类中有的独有方法

1.向下转型风险

类型转换异常

使用instanceof 关键字辅助检测向下转型是否合理
引用名称instanceof类名->返回布尔值,表示该引用指向的对象是不是该类的对象

例子

引用名称instanceof类=>返回布尔值,表示该引用指向的本质是不是该类的对象

public static void main(String[] args) {
    Animal animal1 = new Animal();
    Animal animal2 = new Dog();
    System.out.println(animal1 instanceof Dog);//false
    System.out.println(animal2 instanceof Dog);//true

使用instanceof关键字的返回值搭配的分支语句进行类型转换


    if(animal1 instanceof Dog){
        Dog dog = (Dog) animal1;
        System.out.println("animal1转型成功");
    }else{
        System.out.println("animal1不是指向Dog类型的引用");
    }
    if(animal2 instanceof Dog){
        Dog dog = (Dog) animal2;
        System.out.println("animal2转型成功");
    }else{
        System.out.println("animal2不是指向Dog类型的引用");
    }
}

结果
animal1不是指向Dog类型的引用
animal2转型成功

啥时候发生向上转型,方法接收一个类和当前类的子类,参数指定为相应的父类引用,发生的就是向上转型
只有某个特殊的情况下,需要使用子类拓展的方法,才需要将原本向上转型的引用向下转型还原为子类引用。

六、抽象类

public class Sharp {
    public void print() {}
}
public class Cycle extends Sharp {
    @Override
    public void print(){
        System.out.println("圆");
    }
}
public class Square extends Sharp {
    @Override
    public void print() {
        System.out.println("方块");
    }
}
public class Triangle extends Sharp {
    @Override
    public void print() {
        System.out.println("三角形");
    }
}
public class Test {
    public static void main(String[] args) {
        fun(new Cycle());
        fun(new Square());
        fun(new Triangle());
    }
    public static void fun(Sharp sharp){
        sharp.print();
    }
}

结果


方块
三角形

这三个子类都是Sharp的子类且都覆写了print()

此时多态非常依赖子类覆写方法!
普通父类没法强制要求子类覆写方法

若需要强制要求子类覆写方法,就要用到抽象类。
其实现实生活中有很多的抽象类,这些类都是概念化的,没法具体到某个实例,描述这·
一类对象共同的属性和行为
人类->抽象,没法对应的具体某个或者某一类人,中国人,日本人,印第安人,智人,
尼安德特人
此时Sharp类,包括Sharp的print()都是抽象概念=>抽象类。

1.Java中定义抽象类规则

1.抽象方法所在的类必须使用abstract声明为抽象类。
抽象方法指的是使用abstract关键字声明,只有函数声明,没有函数实现的方法,称为抽象方法。

2.抽象类是普通类的"超集”,只是比普通类多了一些抽象方法而已~~~[O.….N|

普通类有的抽象类全有! !抽象方法所在的类必须是抽象类,子类若继承了抽象类,必须覆写所有抽象方法(子类是普通类)

3.抽象方法:使用关键字abstract声明只有方法声明没有方法体{}的方法

Java中,没有方法体的方法不等于就是抽象方法。
本地方法也没有方法体,不是抽象方法。

4.若一个类使用abstract声明为抽象类,无法直接通过该类实例化对象,哪怕该类中一个抽象方法都没有。当一个类是抽象类,不管他有没有抽象方法,这个类本身就是一个抽象的概念,没法具体到某个特定的实例。只能通过子类向上转型变为抽象父类的引用。

Sharp sharp = new Sharp(); // error人类抽象
Person per = new Person(); // errorPerson per = new China(); // ok

5.子类继承了抽象类,就必须强制子类覆写抽象类中的所有抽象方法(子类是普通类),也满足单继承局限,一个子类只能extends一个抽象类。

 

6.抽象类是普通类的超集(普通类有的内容,抽象类全都有),只是比普通类多了一些抽象方法而已,抽象类虽然没法直接实例化对象,但是也可以存在构造方法,子类在实例化时,仍然遵从继承的规则,先调用父类(抽象类)的构造方法,而后调用子类构造方法!!!!

abstract class BaseTest{
    public BaseTest(){
        this.print();
    }
    abstract void print();
}

public class Fun extends BaseTest {
    private int num = 10;

    @Override
    void print() {
        System.out.println("num = " + num);
    }

    public static void main(String[] args) {
        new Fun();
    }
}

结果

num = 0

七、接口

抽象类虽然没法直接实例化对象,子类仍然满足is a原则,子类和抽象父类之间仍然是满足"继承树"的关系Person对于China
Sharp 对于Cycle


1.而接口的使用表示两种场景

1.接口表示具备某种能力/行为,子类实现接口时不是is a,而是具备这种行为或者能力
"游泳"->能力或者行为,Person满足游泳接口,Dog也能满足游泳接口,Duck也能满足游泳接口
2接口表示一种规范或者标准。
"USB接口",5G标准

接口中只有全局常量和抽象方法-→>更加纯粹的抽象概念。其他东西统统没有

接口使用关键字interface声明接口,子类使用implements实现接口。

例子

1.USB接口

public interface USB {
    //插入
    public abstract void plugIn();
    //工作
    public abstract void work();
}

2.鼠标,键盘外设都属于USB接口的子类。

//鼠标
public class Mouse implements USB {
    @Override
    public void plugIn(){
        System.out.println("安装鼠标驱动中...");
    }
    @Override
    public void work(){
        System.out.println("鼠标驱动安装完成,现在可正常使用!");
    }
}
//键盘
public class KeyBoard implements USB {
    @Override
    public void plugIn(){
        System.out.println("键盘驱动安装中...");
    }
    @Override
    public void work(){
        System.out.println("键盘驱动安装完成,现在可正常使用!");
    }
}

对于电脑的使用者生产者来说,我根本不关心到底哪个具体设备插入到我的电脑上,只要这个设备满足了USB接口,都能被电脑识别,就可以实现。

一个接口可以接受无数种设备,只要这个设备满足USB接口,都可以插入到电脑且被电脑识别。兼容所有的USB子类对象
fuh(Mouse mouse)=>这个插口只能插鼠标,键盘都无法识别,这是两个毫无关系的类。

public class Computer {
    //fun方法模拟电脑的USB的插口
    public void fun(USB usb){
        usb.plugIn();
        usb.work();
    }
  	
    public static void main(String[] args) {
        Computer computer = new Computer();
        Mouse mouse = new Mouse();
        //插入鼠标
        computer.fun(mouse);
        KeyBoard keyBoard = new KeyBoard();
        //插入键盘
        computer.fun(keyBoard);
        
    }
}

    
2.接口表示能力

接口允许多实现,一个类可能具备多个能力,同时实现多个父接口

若实现多个父接口,子类普通类,需要覆写所有的抽象方法

//三个接口
public interface IRun {
    public abstract void run();
}
public interface ISwim {
    public abstract void swim();
}
public interface IFly {
    public abstract void fly();
}
//定义子类
public class Person implements IRun {
    @Override
    public void run() {
        System.out.println("A person is running ...");
    }
}
//表示子类实现多个父接口
public class Dog implements IRun,ISwim{
    @Override
    public void run() {
        System.out.println("A dog is running ...");
    }

    @Override
    public void swim() {
        System.out.println("A dog is swimming ...");
    }
}
public class Duck implements IRun,ISwim,IFly{
    @Override
    public void run() {
        System.out.println("A duck is running ...");
    }

    @Override
    public void swim() {
        System.out.println("A duck is swimming ...");
    }

    @Override
    public void fly() {
        System.out.println("A duck is flying ...");
    }
}
//测试
public class Test {
    public static void main(String[] args) {
        IRun run1 = new Person();
        IRun run2 = new Dog();
        ISwim swim = new Dog();
        IFly fly = new Duck();
        run1.run();
        run2.run();
        swim.swim();
        fly.fly();
    }
}

由于接口中只有全局常量和抽象方法,因此接口中public abstract =>抽象方法
static final =>常量
全都可以省略!!

在接口声明中,这些关键字都不用写,只保留最核心的方法返回值,方法参数列表,名称即可

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/793304.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存