java怎样实现对象的克隆与比较 java对象克隆比较的详细操作指南​

java对象克隆中,浅拷贝仅复制字段值,对引用类型只复制引用地址,导致新旧对象共享同一引用对象;深拷贝则递归复制所有引用对象,使新旧对象完全独立。2. 重写equals()需遵循自反性、对称性、传递性、一致性及与null比较的规范,通常比较关键字段;重写hashcode()必须与equals()保持一致,使用objects.hash()生成相同哈希值以确保集合操作正确。3. comparable接口用于定义类的自然排序,需实现compareto()方法,具有侵入性且只能定义一种排序;comparator接口提供外部比较逻辑,可定义多种排序规则,支持lambda表达式,适用于无法修改源码或需多排序策略的场景。正确实现克隆与比较机制是构建可靠java应用的基础。

java怎样实现对象的克隆与比较 java对象克隆比较的详细操作指南​

Java中实现对象的克隆,通常涉及

Cloneable

接口和

clone()

方法,但这背后隐藏着深浅拷贝的考量。而对象的比较,则主要围绕着

equals()

hashCode()

方法的重写,以及

Comparable

Comparator

接口来定义逻辑上的等同性或排序规则。理解这些,是构建健壮Java应用的基础。

要实现Java对象的克隆与比较,我们得从它们各自的核心机制入手。

对象的克隆:

Cloneable

clone()

的实践

立即学习“Java免费学习笔记(深入)”;

在Java里,如果你想复制一个对象,最直接的方式就是实现

Cloneable

接口并重写

Object

类的

clone()

方法。说实话,

Cloneable

这个接口,它只是一个标记接口,并没有定义任何方法,但它告诉JVM,这个类的对象是可以被克隆的。

class Person implements Cloneable {    private String name;    private int age;    private Address address; // 假设Address也是一个自定义对象    public Person(String name, int age, Address address) {        this.name = name;        this.age = age;        this.address = address;    }    // Getters and Setters    @Override    public Object clone() throws CloneNotSupportedException {        // 默认的Object.clone()实现的是浅拷贝        // 对于基本类型和String,浅拷贝没问题        // 对于引用类型(如address),浅拷贝只复制引用,不复制对象本身        Person clonedPerson = (Person) super.clone();        // 如果需要深拷贝Address对象,则需要手动克隆        if (this.address != null) {            clonedPerson.address = (Address) this.address.clone(); // 假设Address也实现了Cloneable        }        return clonedPerson;    }    // 内部类或单独的Address类    static class Address implements Cloneable {        private String city;        private String street;        public Address(String city, String street) {            this.city = city;            this.street = street;        }        // Getters and Setters        @Override        public Object clone() throws CloneNotSupportedException {            return super.clone(); // Address这里可以只进行浅拷贝,因为其内部没有复杂的引用类型        }    }}

当你调用

super.clone()

时,它会执行一个字段对字段的复制,这通常被称为“浅拷贝”。这意味着,如果你的对象内部有引用类型的字段(比如上面的

Address

对象),那么新旧对象会共享同一个

Address

实例。一旦你修改了其中一个对象的

Address

,另一个也会跟着变。这在很多场景下都不是我们想要的。要解决这个问题,就得实现“深拷贝”,即手动复制所有引用类型的字段,就像上面

Person

类中对

Address

字段的处理一样。

对象的比较:

equals()

hashCode()

Comparable

Comparator

对象的比较,在Java中是个很有意思的话题,因为它不仅仅是判断两个引用是否指向同一个内存地址(这是

==

操作符做的事情),更多时候我们关心的是它们逻辑上的等同性。

import java.util.Objects;class Product {    private String id;    private String name;    private double price;    public Product(String id, String name, double price) {        this.id = id;        this.name = name;        this.price = price;    }    // Getters    @Override    public boolean equals(Object o) {        // 1. 引用相等性检查:如果是同一个对象,直接返回true        if (this == o) return true;        // 2. 类型检查:如果传入对象为null或类型不匹配,返回false        if (o == null || getClass() != o.getClass()) return false;        // 3. 类型转换        Product product = (Product) o;        // 4. 字段比较:根据业务逻辑判断哪些字段决定相等性        return Double.compare(product.price, price) == 0 &&               Objects.equals(id, product.id) &&               Objects.equals(name, product.name);    }    @Override    public int hashCode() {        // 必须与equals方法保持一致:如果两个对象equals返回true,那么它们的hashCode必须相同        return Objects.hash(id, name, price);    }}

equals()

方法定义了两个对象在逻辑上是否相等。

Object

类默认的

equals()

实现和

==

一样,比较的是内存地址。但通常我们希望根据对象的属性来判断。重写

equals()

时,务必遵循它的约定:自反性、对称性、传递性、一致性,以及与

null

的比较。

hashCode()

方法则与

equals()

方法紧密相连。如果你重写了

equals()

,就必须重写

hashCode()

。这是Java集合框架(如

HashMap

HashSet

)正常工作的基本要求。如果两个对象通过

equals()

判断为相等,那么它们的

hashCode()

值必须相同。反之则不一定。

Objects.hash()

是一个非常方便的工具方法,可以帮助我们快速生成哈希码。

除了相等性,我们还经常需要对对象进行排序。这时

Comparable

Comparator

就派上用场了。

Comparable

接口定义了对象的“自然排序”。如果一个类实现了

Comparable

,它就能够与自身类型的其他对象进行比较。比如

String

和包装类都实现了它。

Comparator

接口则提供了一种外部的、可插拔的排序方式。当你不能修改类的源代码,或者需要多种不同的排序规则时,

Comparator

就显得尤为灵活。

import java.util.Comparator;// Product类实现Comparable,定义自然排序(按ID)class ProductComparable implements Comparable {    private String id;    private String name;    private double price;    public ProductComparable(String id, String name, double price) {        this.id = id;        this.name = name;        this.price = price;    }    // Getters and Setters    @Override    public int compareTo(ProductComparable other) {        return this.id.compareTo(other.id); // 按ID自然排序    }    // equals and hashCode omitted for brevity, but should be present}// 使用Comparator定义按价格排序class ProductPriceComparator implements Comparator {    @Override    public int compare(Product p1, Product p2) {        return Double.compare(p1.getPrice(), p2.getPrice());    }}// 或者使用Lambda表达式创建Comparator// Comparator nameComparator = (p1, p2) -> p1.getName().compareTo(p2.getName());

Java对象克隆的深拷贝与浅拷贝有何区别

理解深拷贝和浅拷贝是Java对象克隆中的一个核心痛点。简单来说,它们决定了复制出来的对象和原对象之间的数据共享程度。

浅拷贝(Shallow Copy)

当执行浅拷贝时,新对象会复制原对象的所有字段值。如果字段是基本数据类型(如

int

,

double

,

boolean

等),那么它们的值会被直接复制。但如果字段是引用类型(如另一个对象、数组等),那么复制的不是引用类型对象本身,而是它的引用地址。这意味着新旧对象会指向内存中的同一个引用类型实例。

举个例子,如果你的

Person

对象里有一个

Address

对象,浅拷贝后,新

Person

和旧

Person

Address

字段都指向同一个

Address

对象。你修改其中任何一个

Person

Address

字段,另一个

Person

Address

也会跟着变,因为它们实际上操作的是同一个

Address

实例。这就像你复制了一份文件的快捷方式,而不是文件本身。

深拷贝(Deep Copy)

深拷贝则不同。它不仅复制了原对象的所有基本类型字段,还会递归地复制所有引用类型的字段所指向的对象本身。这意味着,深拷贝后的新对象与原对象在内存中是完全独立的,它们拥有各自的引用类型实例。修改新对象的任何字段,都不会影响到原对象,反之亦然。这就像你真的复制了一份文件,新文件和旧文件是独立的。

实现深拷贝通常需要更多的工作量:

FineVoice语音克隆 FineVoice语音克隆

免费在线语音克隆,1 分钟克隆你的声音,保留口音和所有细微差别。

FineVoice语音克隆 61 查看详情 FineVoice语音克隆 手动递归克隆: 在重写

clone()

方法时,对每一个引用类型字段,都需要手动调用其

clone()

方法(前提是该引用类型也实现了

Cloneable

并重写了

clone()

),直到所有嵌套对象都被独立复制。这是最常见也最直接的方式。序列化与反序列化: 另一种实现深拷贝的常用方法是利用Java的序列化机制。将对象序列化到字节流,然后再从字节流反序列化回来,就能得到一个完全独立的新对象。这种方法简单粗暴,但前提是所有涉及到的类都必须实现

Serializable

接口。它的缺点是性能可能不如手动克隆,且不适用于所有场景(例如,如果对象中包含不可序列化的资源)。

选择深拷贝还是浅拷贝,完全取决于你的业务需求。如果你只是想复制对象的基本值,且不关心引用类型字段的独立性,浅拷贝就足够了。但如果对象内部的引用类型字段也需要独立存在,互不影响,那么深拷贝是必不可少的。在我的经验里,大部分时候,我们想要的都是深拷贝,因为浅拷贝带来的数据共享问题往往难以察觉,容易引入难以调试的bug。

如何正确重写Java对象的equals()和hashCode()方法?

正确重写

equals()

hashCode()

是Java编程中一个非常重要的实践,尤其当你需要将对象放入

HashMap

HashSet

等基于哈希值的集合时。如果它们没有正确配对,你的程序行为可能会变得非常诡异。

重写

equals()

方法的规范

equals()

方法定义了两个对象在逻辑上是否相等。它的实现必须遵循以下五个约定:

自反性 (Reflexive): 对于任何非

null

的引用值

x

x.equals(x)

必须返回

true

对称性 (Symmetric): 对于任何非

null

的引用值

x

y

,当且仅当

y.equals(x)

返回

true

时,

x.equals(y)

也必须返回

true

传递性 (Transitive): 对于任何非

null

的引用值

x

y

z

,如果

x.equals(y)

返回

true

,并且

y.equals(z)

返回

true

,那么

x.equals(z)

也必须返回

true

一致性 (Consistent): 对于任何非

null

的引用值

x

y

,只要在

equals

比较中所用的信息没有被修改,多次调用

x.equals(y)

始终返回

true

或始终返回

false

null

的比较: 对于任何非

null

的引用值

x

x.equals(null)

必须返回

false

一个典型的

equals()

重写模板如下:

class User {    private Long id;    private String username;    private String email;    // Constructor, getters, setters    @Override    public boolean equals(Object o) {        // 1. 引用相等性检查:如果两者是同一个对象,直接返回true,这是最快的路径。        if (this == o) return true;        // 2. 类型检查及null检查:        //    - 如果传入对象为null,或者它们的运行时类型不一致,则它们不可能逻辑相等。        //    - 使用getClass() != o.getClass()比instanceof更严格,避免子类与父类之间的equals问题。        //      如果希望子类实例可以与父类实例相等(Liskov替换原则),可以使用instanceof。        //      但在大多数情况下,我们希望只有同类型的对象才能相等。        if (o == null || getClass() != o.getClass()) return false;        // 3. 类型转换:将Object转换为当前类型,以便访问其字段。        User user = (User) o;        // 4. 字段比较:根据业务逻辑,哪些字段的相等性决定了整个对象的相等性。        //    - 对于基本类型,直接使用==。        //    - 对于引用类型,使用Objects.equals(),它能处理null值。        //    - 注意浮点数比较的特殊性,使用Double.compare或Float.compare。        return Objects.equals(id, user.id) &&               Objects.equals(username, user.username) &&               Objects.equals(email, user.email);    }}

重写

hashCode()

方法的规范

hashCode()

方法返回对象的哈希码。它与

equals()

方法有以下两个关键约定:

一致性: 在Java应用程序的执行期间,只要对象中用作

equals

比较的字段没有被修改,那么对同一对象多次调用

hashCode

方法都必须返回相同的整数。

equals

的配对: 如果两个对象根据

equals(Object)

方法比较是相等的,那么对这两个对象中的每个对象调用

hashCode

方法都必须产生相同的整数结果。

反之则不要求:如果两个对象

hashCode

相同,它们不一定

equals

一个典型的

hashCode()

重写模板如下:

import java.util.Objects;class User {    // ... fields, constructor, getters, setters ...    @Override    public boolean equals(Object o) {        // ... as above ...    }    @Override    public int hashCode() {        // 使用Objects.hash()是最佳实践,它会自动处理null并高效地组合哈希值。        // 传入所有在equals方法中用于比较的字段。        return Objects.hash(id, username, email);    }}

为什么

equals()

hashCode()

必须同时重写?

如果你只重写了

equals()

而没有重写

hashCode()

,那么当两个逻辑上相等的对象(根据你重写的

equals()

)被放入

HashSet

或用作

HashMap

的键时,它们可能会被视为不同的对象。因为这些集合首先会根据对象的

hashCode()

来确定存储位置。如果两个逻辑相等的对象的

hashCode()

不同,它们会被放在不同的“桶”里,导致

contains()

get()

方法无法找到它们,从而出现意想不到的行为。

简单来说,

equals()

定义了“相等”,而

hashCode()

则用于“快速定位”。它们是相辅相成的。

Java中如何为对象定义排序规则:Comparable与Comparator的选择?

在Java中,为对象定义排序规则是常见的需求。我们主要有两种方式:实现

Comparable

接口或者使用

Comparator

接口。它们各自适用于不同的场景,理解它们的区别能帮助你做出更明智的选择。

1.

Comparable

接口:定义对象的“自然排序”

当一个类实现了

Comparable

接口,它就定义了其对象的“自然排序”方式。这意味着,该类的实例可以与同类型的其他实例进行比较,并根据预设的规则进行排序。

特点:侵入性:

Comparable

接口需要被排序的类自身去实现,这意味着你需要修改类的源代码。单一性: 一个类只能实现一个

compareTo()

方法,因此只能定义一种“自然排序”规则。方法: 核心方法是

int compareTo(T o)

。如果当前对象小于

o

,返回负整数。如果当前对象等于

o

,返回零。如果当前对象大于

o

,返回正整数。使用场景: 当你的对象有一个明确的、唯一的、普遍认同的排序标准时,例如,

String

按字典顺序排序,

Integer

按数值大小排序。

import java.util.ArrayList;import java.util.Collections;import java.util.List;class Book implements Comparable {    private String title;    private String author;    private double price;    public Book(String title, String author, double price) {        this.title = title;        this.author = author;        this.price = price;    }    // Getters    @Override    public int compareTo(Book other) {        // 默认按书名(title)进行自然排序        return this.title.compareTo(other.title);    }    @Override    public String toString() {        return "Book{" + "title='" + title + ''' + ", author='" + author + ''' + ", price=" + price + '}';    }    public static void main(String[] args) {        List books = new ArrayList();        books.add(new Book("Effective Java", "Joshua Bloch", 45.0));        books.add(new Book("Clean Code", "Robert C. Martin", 38.0));        books.add(new Book("Design Patterns", "Erich Gamma", 50.0));        Collections.sort(books); // 使用Book的compareTo方法进行排序        System.out.println("按书名排序:n" + books);    }}

2.

Comparator

接口:定义外部的、可插拔的排序规则

Comparator

接口定义了一个比较器,它可以独立于被比较的类存在。它允许你为同一类对象定义多种不同的排序规则,而无需修改类的源代码。

特点:非侵入性: 你不需要修改被排序的类。这在处理第三方库中的类,或者你不想在类中定义唯一自然排序时非常有用。多重排序: 可以创建多个

Comparator

实例,每个实例定义一种不同的排序规则。方法: 核心方法是

int compare(T o1, T o2)

。如果

o1

小于

o2

,返回负整数。如果

o1

等于

o2

,返回零。如果

o1

大于

o2

,返回正整数。使用场景:需要为同一个类定义多种排序方式(例如,按价格排序、按作者排序、按出版日期排序)。无法修改类的源代码(例如,JDK内置类或第三方库的类)。当类的“自然排序”不明确或不存在时。在Java 8及以后,可以使用Lambda表达式和方法引用更简洁地创建

Comparator

import

以上就是java怎样实现对象的克隆与比较 java对象克隆比较的详细操作指南​的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/233798.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月3日 22:16:46
下一篇 2025年11月3日 22:21:21

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 为什么使用 inline-block 元素时会错位?

    inline-block 元素错位成因剖析 在使用 inline-block 元素时,可能会遇到它们错位显示的问题。如代码 demo 所示,当设置了 overflow 属性时,a 标签就会错位下沉,而未设置时却不会。 问题根源: overflow:hidden 属性影响了 inline-block …

    2025年12月24日
    000
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 为什么我的 CSS 元素放大效果无法正常生效?

    css 设置元素放大效果的疑问解答 原提问者在尝试给元素添加 10em 字体大小和过渡效果后,未能在进入页面时看到放大效果。探究发现,原提问者将 CSS 代码直接写在页面中,导致放大效果无法触发。 解决办法如下: 将 CSS 样式写在一个单独的文件中,并使用 标签引入该样式文件。这个操作与原提问者观…

    2025年12月24日
    000
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 为什么我的 em 和 transition 设置后元素没有放大?

    元素设置 em 和 transition 后不放大 一个 youtube 视频中展示了设置 em 和 transition 的元素在页面加载后会放大,但同样的代码在提问者电脑上没有达到预期效果。 可能原因: 问题在于 css 代码的位置。在视频中,css 被放置在单独的文件中并通过 link 标签引…

    2025年12月24日
    100
  • 为什么我的 Safari 自定义样式表在百度页面上失效了?

    为什么在 Safari 中自定义样式表未能正常工作? 在 Safari 的偏好设置中设置自定义样式表后,您对其进行测试却发现效果不同。在您自己的网页中,样式有效,而在百度页面中却失效。 造成这种情况的原因是,第一个访问的项目使用了文件协议,可以访问本地目录中的图片文件。而第二个访问的百度使用了 ht…

    2025年12月24日
    000

发表回复

登录后才能评论
关注微信