java语法:继承与多态

导言:

在Java中,继承和多态是面向对象编程的两个重要概念,它们允许我们创建更加灵活和可扩展的代码。本文主要对继承和多态的语法和一些细节做一个介绍和解释。

目录

导言:

正文:

一.继承

1. 基本语法

2. 继承的特点

3.子类中访问父类的成员变量

4. 子类中访问父类的成员方法 

5.super关键字

6.代码的执行顺序

二.多态

1.基本概念:

2.重写

 3.向上转型

4.向下转型 

5.多态的优缺点

总结:


正文:

一.继承

继承是面向对象编程中的一种机制,允许一个类(称为子类)继承另一个类(称为父类)的属性和方法。通过继承,子类可以获得父类的所有属性和方法,同时可以在其基础上添加新的属性和方法,或者修改已有的属性和方法。通俗来讲,继承主要就是用来对类和类之间进行共性抽取,从而实现代码复用。

1. 基本语法

在Java中,继承通过使用关键字extends来实现。子类可以继承父类的非私有属性和方法。基本的继承语法如下:

class ParentClass {
        // 父类的属性和方法
    
    }

    class ChildClass extends ParentClass {
        // 子类的属性和方法
     
    }

 需要 注意的是:子类会将父类中的成员变量或者成员方法继承到子类中。 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了 

2. 继承的特点

要知道子类并不能将父类的所有东西都继承下来,需要遵循一定的规则。

对于构造方法而言:

子类无法继承父类的构造方法,但是子类可以可以调用父类的构造方法来帮助父类进行初始化。

对于成员变量而言:

子类可以继承父类的所有成员变量。

对于成员方法而言:

子类可以继承非私有的成员方法,但不能继承私有的成员方法。

下面是一些关于Java中继承的重要特点:

  • 子类可以继承父类的非私有属性和方法,这意味着子类可以直接访问父类的属性和方法。
  • 子类可以重写父类的方法,从而实现对父类方法的覆盖。
  • Java中不支持多继承,一个类只能有一个直接父类。
  • 子类可以调用父类的构造方法来初始化父类的属性。
  • 子类可以在继承父类的基础上添加新的属性和方法,从而实现代码的扩展。
3.子类中访问父类的成员变量
  • 当子类和父类不存在同名变量时:
class ParentClass {
        // 父类的属性和方法
        int a;
        int b;
    }

    class ChildClass extends ParentClass {
        // 子类的属性和方法
        int c;

        public void method() {
            a = 10; // 访问从父类中继承下来的a
            b = 20; // 访问从父类中继承下来的b
            c = 30; // 访问子类自己的c
        }
    }

在Java中,如果子类和父类不存在同名变量,子类可以直接使用父类的成员变量。这是因为子类会继承父类的变量,即使没有同名的变量也可以直接使用父类的变量。

  •  当子类和父类存在成员变量同名时:
public class Base {
        int a;
        int b;
        int c;
    }
    //----------------------------------------------------------------

    public class Derived extends Base{
        int a; // 与父类中成员a同名,且类型相同
        char b; // 与父类中成员b同名,但类型不同
        public void method(){
            a = 100; // 访问的成员变量与父类中成员变量同名,优先访问自己的。
            b = 101; // 访问的成员变量子类中没有,则访问父类继承下来的
            c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
            // d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
        }
    }

通过子类对象访问成员时遵循以下几点:

  • 如果访问的成员变量子类中有,优先访问自己的成员变量。
  • 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
  • 如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
  • 成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。 
4. 子类中访问父类的成员方法 
  • 当子类和父类成员方法名字不同时:
class Parent {
    public void display() {
        System.out.println("This is the display method in the Parent class");
    }
}

class Child extends Parent {
    public void callParentMethod() {
        display(); // 子类直接调用父类的成员方法
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.callParentMethod(); // 输出:This is the display method in the Parent class
    }
}

和成员变量一样,如果子类和父类不存在同名方法,子类可以直接使用父类的成员方法。在子类方法中或者通过子类对象访问方法时,优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。

  • 当子类和父类成员方法名字相同时:
  public class Base {
        public void methodA(){
            System.out.println("Base中的methodA()");
        }
        public void methodB(){
            System.out.println("Base中的methodB()");
        }
    }
    public class Derived extends Base{
        public void methodA(int a) {
            System.out.println("Derived中的method(int)方法");
        }
        public void methodB(){
            System.out.println("Derived中的methodB()方法");
        }
        public void methodC(){
            methodA(); // 没有传参,访问父类中的methodA()
            methodA(20); // 传递int参数,访问子类中的methodA(int)
            methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),基类的无法访问到
        }
    }

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

可见成员方法和变量一致,优先访问子类的,但是我们可以指定其优先访问父类,我们可以通过super关键字来实现。

5.super关键字

super关键字在Java中用于引用对象的直接父类,可以用于调用父类的构造方法,访问父类的成员变量和成员方法,以及在子类中调用父类的构造方法和成员方法。我们可以通过super.的形式访问到父类的成员方法和变量。

 public class Base {
        int a;
      
        public void methodA(){
            System.out.println("Base中的methodA()");
        }
        public void methodB(){
            System.out.println("Base中的methodB()");
        }
    }
    public class Derived extends Base{
        int a;
        
        public void methodB(){
            System.out.println("Derived中的methodB()方法");
        }
        public void methodC(){
            a=10;//直接访问,访问到的都是子类中的变量
            super.a=10;//super调用,访问到了父类的成员变量
            
            methodA(); // 子类没有,访问父类的方法
            methodB(); // 直接访问,访问到的都是子类中的methodB(),基类的无法访问到
            super.methodB();//super调用,访问到了父类的成员方法

        }
    }

在子类中,如果想要明确访问父类中成员时,借助super关键字即可。 

同时我们还可以利用super来调用父类的构造方法:

调用父类的构造方法:在子类的构造方法中使用super()来调用父类的构造方法。可以使用super()来调用父类的无参构造方法,也可以使用super(参数列表)来调用父类的有参构造方法。

public class Child extends Parent {
    public Child() {
        super(); // 调用父类的无参构造方法
    }
}

在构造方法中也存在着一些细节: 

1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。
4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现

 需要注意的是,super与this一样, 只能在非静态方法中使用。

6.代码的执行顺序

在Java中,当涉及到继承体系时,代码的执行顺序遵循以下规则:

  1. 静态代码块和静态变量初始化:首先,会按照继承层次从上到下的顺序依次执行每个类中的静态代码块和静态变量初始化。这意味着父类的静态代码块和静态变量会先被初始化,然后是子类的静态代码块和静态变量。
  2. 父类构造方法:父子父子,先有父再有子,接着,会调用父类的构造方法。如果父类还有父类,那么会依次调用父类的构造方法,直到最顶层的父类。
  3. 父类的实例代码块
  4. 子类成员变量和实例代码块初始化:接下来,会初始化子类的成员变量和实例代码块,按照声明的顺序执行。
  5. 子类构造方法:最后,会调用子类的构造方法。

代码验证:

class Person {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Person:构造方法执行");
    }

    {
        System.out.println("Person:实例代码块执行");
    }

    static {
        System.out.println("Person:静态代码块执行");
    }
}

class Student extends Person {
    public Student(String name, int age) {
        super(name, age);
        System.out.println("Student:构造方法执行");
    }

    {
        System.out.println("Student:实例代码块执行");
    }

    static {
        System.out.println("Student:静态代码块执行");
    }
}

public class test {
    public static void main(String[] args) {
        Student student1 = new Student("张三", 19);
        System.out.println("===========================");
        Student student2 = new Student("gaobo", 20);
    }


}

 结果如下:

通过分析执行结果,得出以下结论:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

二.多态

1.基本概念:

多态,是指一个引用通过不同的对象的调用,呈现出不同的状态。通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。多态的一种体现,就是在代码运行时,当传递不同类对象时,会调用对应类中的方法。

多态的一种表现形式是:

父类类型 对象名称 = 子类对象;

例如:

class Person {
    
}

class Student extends Person {
   
}

public class test {
    public static void main(String[] args) {
      Person p = new Student();
    }


}

在java中要实现多态,必须要满足如下几个条件,缺一不可: 

1. 必须在继承体系下
2. 子类必须要对父类中方法进行重写
3. 通过父类的引用调用重写的方法

下面是一个多态的实例:

// 定义一个动物类
class Animal {
    public void makeSound() {
        System.out.println("动物发出叫声");
    }
}

// 定义一个狗类,继承自动物类
class Dog extends Animal {
    public void makeSound() {
        System.out.println("狗发出汪汪的叫声");
    }
}

// 定义一个猫类,继承自动物类
class Cat extends Animal {
    public void makeSound() {
        System.out.println("猫发出喵喵的叫声");
    }
}

public class PolymorphismExample {
    public static void main(String[] args) {
        Animal animal1 = new Dog(); // 使用父类引用指向子类对象
        Animal animal2 = new Cat(); // 同样使用父类引用指向另一个子类对象

        animal1.makeSound(); // 输出:狗发出汪汪的叫声
        animal2.makeSound(); // 输出:猫发出喵喵的叫声
    }
}

当类的调用者在编写 makeSound 这个方法的时候, 参数类型为 Animal (父类), 此时在该方法内部并不知道, 也不关注当前的引用指向的是哪个类型(哪个子类)的实例. 此时 这个引用调用 makeSound方法可能会有多种不同的表现(和 a 引用的实例相关), 这种行为就称为 多态. 

2.重写

Java中,方法重写(Override)是指子类重新定义父类中已有的方法,以实现特定的功能。方法重写是实现多态性的一种方式,它允许子类提供对继承的方法的自定义实现。当子类重写父类的方法时,子类对象调用该方法时将执行子类中的实现,而不是父类中的实现。

以下是方法重写的一些重要规则和注意事项:

  • 子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致
  • 被重写的方法返回值类型可以不同,但是必须是具有父子关系的
  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected
  • 父类被static、private修饰的方法、构造方法都不能被重写。
  • 重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写.

下面是一个重写的案例:

// 父类
class Animal {
    public void makeSound() {
        System.out.println("动物发出叫声");
    }

}

// 子类
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("狗发出汪汪的叫声");
    }
}

public class OverrideExample {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 使用父类引用指向子类对象
        animal.makeSound(); // 输出:狗发出汪汪的叫声
    }
}

重写和重载有很多类似的地方,为了防止混淆,这里做一个总结。 

重写和重载的区别:

  1. 重载方法是在同一个类中定义多个方法,而重写方法是子类重新定义父类中已有的方法。
  2. 重载方法的方法名相同,但参数列表不同,而重写方法的方法名、参数列表和必须与父类中被重写的方法完全一致。
  3. 重载方法的调用是根据参数列表的类型和数量来确定的,而重写方法的调用是根据对象的实际类型来确定的。
  4. 重载可以修改访问限定符,但重写的访问限定符子类必须大于父类。
 3.向上转型

向上转型是指将子类的实例赋给父类引用的过程。在向上转型中,子类的实例可以赋给父类的引用变量,这样就可以通过父类的引用变量来访问子类对象的方法和属性。向上转型是安全的,因为子类对象具有父类对象的所有属性和方法,但不能访问子类特有的方法和属性。

实例代码:

class Animal {
    public void makeSound() {
        System.out.println("动物发出叫声");
    }
}

class Dog extends Animal {
    public void makeSound() {
        System.out.println("狗发出汪汪的叫声");
    }

    public void wagTail() {
        System.out.println("狗摇尾巴");
    }
}

public class UpcastingExample {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型
        animal.makeSound(); // 输出:狗发出汪汪的叫声
        // animal.wagTail(); // 编译错误,无法访问子类特有的方法
    }
}

在这个例子中,子类Dog的实例被赋给了父类Animal的引用变量,这就是向上转型。通过父类引用变量animal可以调用子类重写的方法makeSound,但无法访问子类特有的方法wagTail。

4.向下转型 

向下转型是指将父类引用转换为子类引用的过程。在向下转型中,需要使用强制类型转换将父类引用转换为子类引用,以便访问子类特有的属性和方法。向下转型是不安全的,因为父类引用指向的对象可能不是子类的实例,如果强制类型转换失败会抛出ClassCastException异常。

向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。Java中为了提高向下转型的安全性,引入了instanceof ,instanceof 的作用是判断 object 是否是 class 的实例或者子类的实例,如果是则返回 true,否则返回 false。如果 object 为 null,则返回 false。的作用是判断 object 是否是 class 的实例或者子类的实例,如果是则返回 true,否则返回 false。如果 object 为 null,则返回 false。如果该表达式为true,则可以安全转换。

实例代码:

public class DowncastingExample {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal; // 向下转型
            dog.makeSound(); // 输出:狗发出汪汪的叫声
            dog.wagTail(); // 输出:狗摇尾巴
        }
    }
}

在这个例子中,animal instanceof Animal 返回 true,因为 animal 是 Animal 类的实例;animal instanceof Dog 也返回 true,因为 animal 是 Dog 类的实例。 

5.多态的优缺点

优点:

  1. 灵活性:多态使得代码更加灵活,能够适应不同的对象和场景。通过多态,可以使用父类类型的引用变量来引用子类对象,从而实现统一的接口访问不同的子类对象,简化了代码的设计和实现。

  2. 可扩展性:多态使得代码更易于扩展。当需要添加新的子类时,无需修改现有的代码,只需要创建新的子类并实现父类的抽象方法,就可以直接在现有代码中使用新的子类对象。

  3. 维护性:多态提高了代码的可维护性。通过多态,可以将代码模块化,降低了代码之间的耦合度,便于单独修改和维护各个模块。

  4. 能够降低代码的 "圈复杂度", 避免使用大量的 if - else
     

缺点:

  1. 性能损失:多态会带来一定的性能损失。由于多态需要在运行时动态确定对象的类型,因此需要额外的运行时开销,可能会导致一定的性能损失。

  2. 可读性降低:过度使用多态可能会降低代码的可读性。如果在代码中过度使用多态,可能会导致代码难以理解和维护,降低代码的可读性。

  3. 不适合所有场景:多态并不适合所有的场景。有些情况下,需要明确地知道对象的具体类型,而不是使用多态。过度使用多态可能会导致代码的复杂性增加,不利于理解和维护。

总结:

继承:一个类可以继承另一个类的属性和方法,这样可以避免重复编写相似的代码,并且可以实现多层次的类组织管理。

多态:允许不同的对象对同一消息作出不同的响应,通过动态绑定的方式,可以根据对象的实际类型来确定调用的方法,从而实现代码的灵活性和可扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/128826.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

补坑:Java的字符串String类(1)

常用方法 字符串构造 来看看源码里面String的构造方法 普通字符串 //"hello" 是字符串常量,没有\0标记结尾String str "hello";System.out.println(str);//helloString str2 new String();System.out.println(str2);//没有输出String str3…

“三位一体”超级混沌工程主要特点及功能

“三位一体”超级混沌工程X-Chaos主要包括基础故障编排、业务场景故障编排、演练场景编排、故障库管理、演练场景管理、演练计划管理、演练观测和演练报告等模块,支持对传统架构、云环境以及国产化基础环境的IT系统进行故障演练。本文将介绍混沌工程主要特点及主要功…

归并分治 笔记

归并分治 前置知识:讲解021-归并排序 原理: (1)思考一个问题在大范围上的答案,是否等于,左部分的答案 右部分的答案 跨越左右产生的答案(2)计算“跨越左右产生的答案”时,如果加上左、右各自…

GeoGebra:数学动画制作工具重磅来袭

【线性代数】线性代数可视化工具:manim manim是之前我跟大家分享的一个线性代数动画制作工具。 但我之前的描述有些许偏差,这里要更正一下,manim不仅限于制作线性代数动画,也可以制作数学其他学科的动画,例如微积分&…

Selenium是什么,带你了解自动化测试的神奇之处

一、使用测试工具 工欲善其事,必先利其器。在开始具体的自动化测试之前,我们需要做好更多的准备,包括以下几个方面: 认识自动化测试 准备自动化测试工具 使用有效的方式 针对具体的测试对象 接下来的第一部分内容,我…

JavaScript如何实现钟表效果,时分秒针指向当前时间,并显示当前年月日,及2024春节倒计时,源码奉上

本篇有运用jQuery&#xff0c;记得引入jQuery库&#xff0c;否则不会执行的喔~ <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></title> <meta name"chenc" content"Runoob"> <met…

人工智能中的基础之一——Python

Python作为一种简洁、易学、功能丰富的高级编程语言&#xff0c;被广泛应用于数据分析、人工智能、Web开发等各个领域。本文将介绍Python的基础语法和使用&#xff0c;帮助读者快速上手Python编程。 一、Python基础语法 1. 变量和数据类型 在Python中&#xff0c;可以使用变…

C#,Python实践,用CodeFormer实现人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色

无论是自己、家人或是朋友、客户的照片&#xff0c;免不了有些是黑白的、被污损的、模糊的&#xff0c;总想着修复一下。作为一个程序员 或者 程序员的家属&#xff0c;当然都有责任满足他们的需求、实现他们的想法。除了这个&#xff0c;学习了本文的成果&#xff0c;或许你还…

【Unity程序小技巧】如何消除多次Destory带来的性能消耗

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

Linux学习第36天:Linux RTC 驱动实验:时间是一条流淌的河

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 RTC就是实时时钟。 本笔记主要学习Linux RTC驱动试验&#xff0c;主要内容包括Linux内核RTC驱动简介、I.MX6U内部RTC分析、RTC时间查看与设置。因为Linux内核已经…

Docker - 常用命令

Docker - 常用命令 帮助命令 docker version # 查看docker版本信息 docker info # 显示docker的系统信息&#xff0c;包括镜像和容器的数量 docker 命令 --help # 帮助命令官网帮助文档&#xff1a;https://docs.docker.com/engine/reference/commandline/cli/ 镜像…

接口测试及常用接口测试工具

首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能给你…

【算法与数据结构】77、LeetCode组合

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;如果k是固定的&#xff0c;最直接的方法就是建立k个for循环&#xff0c;将结果全部压入result容器中。…

联合阿里在职测开工程师耗时一个星期写的 【接口测试+自动化接口接口测试详解]

1&#xff1a;json模块的使用  2&#xff1a;接口自动化测试概叙 3&#xff1a;swagger工具能导出接口文档的 4:前端页面: 5:后端: 6:前端和后端的数据交互&#xff08;接口&#xff09;通过接口 7&#xff1a;接口的概念 8&#xff1a;常用的接口方式&#xff08;协议…

自动化测试中的失败截图和存log

如果我们在执行自动化测试的时候&#xff0c;希望能在失败的时候保存现场&#xff0c;方便事后分析。 对于UI自动化&#xff0c;我们希望截图在测试报告中。 对于api自动化&#xff0c;我们希望截取出错的log在测试报告中。 我开始自己蛮干&#xff0c;写了两个出错截图的方法。…

Essential Math for AI:高效的人工智能数学原理晋级读物

今天给大家介绍一本人工智能数学原理书籍&#xff1a;Essential Math for AI。作者是Hala Nelson&#xff0c;一位应用数学领域的美女博士&#xff0c;James Madison University (JMU) 大学的助理教授。 关注微信公众号&#xff1a;人工智能大讲堂&#xff0c;后台回复【ema】获…

【Android】Debug时禁用主线程ANR限制

ANR全称Application Not Response&#xff0c;指主线程超过5s无响应&#xff0c;应用会自动退出 由于这个线程&#xff0c;如果我们给主线程加了断点&#xff0c;就会触发ANR&#xff0c;导致调试时应用退出 这样调试起来会非常麻烦&#xff0c;其实对于Debug应用&#xff0c…

JVM虚拟机-虚拟机性能监控、故障处理工具

1基础故障处理工具 jps&#xff08;JVM Process Status Tool&#xff09;是&#xff1a;虚拟机进程状况工具 作用&#xff1a;可以列出正在运行的虚拟机进程&#xff0c;并显示虚拟机执行主类&#xff08;Main Class&#xff0c;main()函数所在的类&#xff09;名称以及这些进…

人工智能基础——python:Pandas与数据处理

人工智能的学习之路非常漫长&#xff0c;不少人因为学习路线不对或者学习内容不够专业而举步难行。不过别担心&#xff0c;我为大家整理了一份600多G的学习资源&#xff0c;基本上涵盖了人工智能学习的所有内容。点击下方链接,0元进群领取学习资源,让你的学习之路更加顺畅!记得…

CSS基础:你必须要知道的行高属性 line-height

作者:WangMin 格言:努力做好自己喜欢的每一件事 CSDN原创文章 博客地址 &#x1f449; WangMin 对于初学CSS的同学来说&#xff0c;会有很多属性相关的疑问&#xff0c;行高属性 line-height一定是其中一个&#xff0c;因为它是CSS中非常重要的一个属性&#xff0c;这个属性改变…