当前位置: 首页 > news >正文

Java 中的final:不可变性的魔法之旅

🎏:你只管努力,剩下的交给时间

🏠 :小破站

Java 中的final:不可变性的魔法之旅

  • 前言
  • 第一:了解final变量
  • 第二:final方法
  • 第三:final类
  • 第四:final参数
  • 第五:final引用和对象
  • 第六:final和多线程
  • 第七:final和性能优化

前言

在 Java 编程世界中,final 是一个引人注目的关键字,它赋予了变量、方法、类等各种元素不可变性。有些程序员将其视为一种约束,而另一些则将其视为一种保护措施。在这个博客中,我们将探索final的多种用法,从变量的不可变性到类的终结,了解其妙用。final是你代码的最后一道屏障,让我们一起发现它的力量。

第一:了解final变量

final变量是一种Java中的变量类型,表示一旦被赋值就不能再次修改。final可以用于变量、方法和类,它提供了不可变性和确定性的特性,有助于代码的可靠性和安全性。

以下是关于final变量的声明、初始化以及不可变性的意义和好处的详细信息:

声明和初始化final变量

  1. final变量:在Java中,你可以使用final关键字声明一个不可变的变量。一旦给final变量赋值,它就不能再次被修改。例如:

    final int age = 30;
    
  2. final方法:在方法声明中使用final关键字表示该方法不能被子类覆盖(重写)。这可以用于确保特定方法的行为在子类中不会被改变。

    public final void myFinalMethod() {// 方法内容
    }
    
  3. final:在类声明中使用final关键字表示该类不能被继承。这用于创建不可被继承的最终类。

    public final class MyFinalClass {// 类内容
    }
    

不可变性的意义和好处

  1. 线程安全:不可变对象在多线程环境中是线程安全的,因为它们的状态不会改变。这消除了需要使用同步机制的复杂性。

  2. 简化代码:不可变对象更容易理解,因为它们的状态不会改变。这可以减少代码中的复杂性,提高可维护性。

  3. 缓存:不可变对象适合用作缓存键,因为它们的哈希值在其生命周期内不会改变。

  4. 性能优化:编译器和运行时环境可以对不可变对象进行优化,以提高性能。

  5. 可靠性:不可变对象不容易受到错误的影响,因为它们不会在运行时修改状态。

  6. 可重用性:不可变对象可以被多个线程共享,从而提高了对象的可重用性。

  7. 安全性:不可变对象在安全性上有优势,因为它们不容易受到恶意篡改。

总之,final变量用于创建不可变对象,具有不可变性的对象在多线程环境中更安全,更容易理解,能够提供更好的性能和可维护性。它们在编写高质量Java代码时具有重要的作用。

第二:final方法

final方法是Java中的一种方法修饰符,用于表示该方法不能被子类覆盖(重写)。一旦一个方法被声明为final,它在子类中不能被修改或覆盖。这是为了确保方法的行为不会被改变,增强代码的可靠性和稳定性。

以下是关于final方法的声明以及方法覆盖的规则和限制的详细信息:

声明不可覆盖的方法

在类中声明不可覆盖的方法需要使用final关键字。以下是一个示例:

public class ParentClass {public final void myFinalMethod() {// 方法内容}
}

在上述示例中,myFinalMethod方法被声明为final,表示它不能被子类修改或覆盖。

方法覆盖的规则和限制

在Java中,方法覆盖(也称为方法重写)是一种子类重写父类的方法,以提供自己的实现。以下是有关方法覆盖的规则和限制:

  1. 子类方法必须具有与父类方法相同的名称、参数列表和返回类型。

  2. 子类方法不能缩小父类方法的访问权限。例如,如果父类方法是public,则子类方法不能是private

  3. 子类方法不能抛出比父类方法更多的异常。子类方法可以不抛出异常或抛出父类方法抛出的异常。

  4. final方法不能被覆盖。

  5. 静态方法不能被覆盖,因为它们与类而不是实例相关联。

  6. 构造方法不能被覆盖。

  7. 子类方法的返回类型可以是父类方法返回类型的子类(协变返回类型),但不能是父类方法返回类型的超类。

方法覆盖是面向对象编程中的一个重要概念,它允许子类提供自己的实现以满足特定需求,同时保留了父类的接口。使用final方法可以禁止方法的覆盖,以确保特定的行为不会被改变。

第三:final类

final是Java中的一种类修饰符,用于表示该类不能被继承。一旦一个类被声明为final,它不允许有子类,确保该类的实现不会被修改。这是为了增强类的稳定性和可靠性。

以下是有关final类的声明以及类继承和扩展思考的详细信息:

声明不可继承的类

在Java中,要声明一个不可继承的类,只需在类的声明前加上final关键字。以下是一个示例:

public final class MyFinalClass {// 类内容
}

在上述示例中,MyFinalClass被声明为final,表示它不能有任何子类。

类继承和扩展的思考

在面向对象编程中,类继承和扩展是一个重要的概念,允许你创建新的类,从已有的类继承属性和行为。然而,有时你可能希望限制某个类的继承,或者确保某个类的实现不会被修改。以下是一些考虑类继承和扩展的思考:

  1. 继承的合适性:在考虑是否继承某个类时,你应该考虑是否确实需要继承,是否需要重用父类的行为,以及是否符合面向对象设计原则。

  2. 类的设计:当你设计一个类时,要考虑它是否应该允许继承。有些类被设计为基类,允许其他类继承并扩展它们的功能,而有些类可能被设计为不可继承,以确保其行为的稳定性。

  3. final类的使用final类通常用于表示某个类的实现是最终的,不应该被修改。这对于库类、不可变类或具有特定行为的类非常有用。

  4. 接口的使用:如果你想要提供一种方式来共享某个类的行为而不涉及继承,可以考虑使用接口。接口允许多个类实现共享的行为。

总之,final类用于表示不可继承的类,它可以确保类的实现稳定性和不可修改性。在设计和扩展类时,要仔细考虑继承和扩展的需求,并根据需要使用final类或接口来实现设计目标。

第四:final参数

在方法参数中使用final的主要目的是为了增加参数的不可修改性(immutability)和提高代码的安全性。当你将一个参数声明为final时,它在方法内部不能被修改,这有助于防止意外的更改和提高代码的可维护性。

以下是有关在方法参数中使用final的详细信息以及示例:

为什么在方法参数中使用final

  1. 不可修改性:使用final参数可以确保方法内部不会更改参数的值。这有助于防止在方法中无意间修改参数的值,导致不可预测的行为。

  2. 安全性:不可修改的参数可以提高代码的安全性,特别是在多线程环境中。多线程环境下,共享的可修改参数可能导致竞态条件和数据竞争。通过使用final参数,可以避免这些问题。

  3. 可读性final参数可以增加代码的可读性,因为它明确表明这个参数在方法中是只读的,不会被修改。

示例:在方法中使用final参数的情况

public class Example {public void process(final int number) {// 使用final参数System.out.println("Received number: " + number);// 以下代码会导致编译错误,因为number是final,不能被修改// number = number * 2; // 编译错误}public static void main(String[] args) {Example example = new Example();int value = 42;example.process(value);System.out.println("Value after method call: " + value);}
}

在上述示例中,process方法接受一个final参数number,并在方法内部使用它。由于number被声明为final,任何尝试在方法内部修改它的操作都会导致编译错误。这确保了number的不可修改性和代码的安全性。在方法调用后,value的值仍然保持不变,没有被修改。

通过在方法参数中使用final,你可以增加代码的可读性和安全性,确保参数的不可修改性,减少潜在的错误。这在编写高质量Java代码时是一个有用的实践。

第五:final引用和对象

理解final引用final对象之间的区别是非常重要的,它们涉及到Java中的不可变性和可变性的概念。以下是这两者之间的区别以及不可变对象的优势:

Final引用 vs. Final对象

  1. Final引用:当你将一个引用声明为final时,意味着这个引用不能再指向其他对象。但它并不影响引用所指对象的可变性。你仍然可以通过这个final引用修改对象的内部状态。

    final StringBuilder builder = new StringBuilder("Hello");
    builder.append(", World"); // 合法,修改了builder所指对象的内部状态
    
  2. Final对象:当你将一个对象声明为final时,意味着这个对象自身不能被重新分配(即不允许重新创建对象并将引用指向其他对象),并且它的内部状态(如果有)也不能被修改。这确保了对象的不可变性。

    final String str = "Hello";
    str = "World"; // 编译错误,不能重新分配str的引用
    

Final引用对于集合和数组的影响

当引用是final时,它的不可变性仅限于引用自身,而不限于引用所指向的对象。这意味着,如果引用是final,你仍然可以修改引用所指向的对象的内部状态,包括集合和数组中的元素。例如:

final List<String> list = new ArrayList<>();
list.add("Hello"); // 合法,修改了list所指向的ArrayList对象

为了实现不可变的集合或数组,需要采取其他措施,如使用Collections.unmodifiableList或不提供修改方法的自定义不可变集合。

不可变对象的优势

  1. 线程安全:不可变对象在多线程环境中是线程安全的,因为它们的状态不会改变,无需锁定。

  2. 缓存:不可变对象适合用作缓存键,因为它们的哈希值不会改变。

  3. 可靠性:不可变对象在运行时不会改变,这有助于避免意外的修改和错误。

  4. 性能优化:编译器和运行时环境可以对不可变对象进行优化,提高性能。

  5. 可重用性:不可变对象可以被多个线程共享,从而提高了对象的可重用性。

在Java中,不可变对象具有许多优势,因此在设计和编写代码时,考虑对象的不可变性是一个有益的实践。

第六:final和多线程

final在多线程环境下具有重要的作用,它主要用于确保多线程下的可见性和不可变性。以下是final在多线程环境中的作用、如何避免竞态条件和提高线程安全性以及使用final的最佳实践:

final在多线程环境下的作用

  1. 可见性:当一个线程在构造对象时,如果将字段标记为final,则其他线程在访问该对象时能够立即看到这些final字段的最新值,而不需要额外的同步机制。

  2. 不可变性final字段保证它们的值不会被修改,从而创建了不可变对象。不可变对象是线程安全的,因为它们不会在多线程环境中发生状态变化。

避免竞态条件和线程安全性

  1. 不可变对象:使用final关键字来确保对象的不可变性。不可变对象在多线程环境中是线程安全的,不需要额外的同步。

  2. 保证可见性:在多线程编程中,final字段的值对其他线程可见。这可以帮助避免竞态条件,确保线程之间的协同工作。

  3. 使用final的对象引用:如果你将一个对象引用声明为final,确保在多线程环境中,这个引用不会被修改。这有助于避免引用变量被重分配的问题。

  4. 不可变集合:Java提供了Collections.unmodifiableXXX方法来创建不可变的集合对象。这些不可变集合在多线程环境中提供了线程安全性。

使用final的最佳实践

  1. 尽量将字段声明为final:在可能的情况下,将字段声明为final以提高代码的可读性和线程安全性。

  2. 使用final局部变量:在方法中使用final局部变量,特别是在匿名内部类或Lambda表达式中,以确保它们不会发生意外的变化。

  3. 谨慎使用volatilevolatile字段用于确保字段的可见性,但不一定保证不可变性。在需要不可变性的情况下,使用final字段更为安全。

  4. 避免线程逃逸:确保不会将this引用传递给其他线程,以避免线程逃逸问题。

总之,final关键字在多线程编程中是一个有用的工具,可以帮助确保可见性和不可变性,从而提高线程安全性。它在不可变对象、字段、局部变量等方面都有不可替代的作用,但仍需在设计和编写多线程代码时谨慎使用。

第七:final和性能优化

final关键字与性能优化密切相关,因为它为编译器提供了有关代码优化的信息。以下是final与编译器优化、内联和常量折叠之间的关系,以及final对性能的影响:

编译器优化和final的关系

  1. 不变性保证:当一个字段或变量被声明为final时,编译器知道它的值不会在运行时发生变化。这允许编译器执行一些优化,如不必要的内存访问和计算的消除。

  2. 方法内联:编译器可能会选择将final方法内联到调用它的地方,从而避免了方法调用的开销。

  3. 常量折叠:编译器可以执行常量折叠,将final常量的值在编译时直接替换到使用它的地方。

内联和常量折叠

  1. 内联:内联是一种优化技术,它将方法调用处的代码替换为被调用方法的实际内容,从而减少方法调用的开销。在某些情况下,编译器可能会选择内联final方法,因为它知道这些方法不会在子类中被覆盖。

  2. 常量折叠:常量折叠是指编译器将编译时已知的常量的计算结果直接插入到代码中。final常量通常可以被折叠,因为它们的值在编译时已知并且不可变。

final对性能的影响

  1. 性能提升final常量的使用通常有助于提高性能,因为它们可以被编译器优化,以减少运行时开销。

  2. 减少不必要的内存访问final字段通常不需要被读取多次,因为它们的值不会改变。这可以减少不必要的内存访问,提高代码的效率。

  3. 代码可读性final可以提高代码的可读性,因为它明确表明某个字段或方法是不可变的,不会在运行时改变。

虽然final可以提高性能,但应该根据具体情况来决定是否使用它。在某些情况下,过度使用final可能会导致不必要的复杂性,因此需要谨慎使用。通常情况下,使用final常量和final方法是一种良好的实践,可以提高代码的可读性和性能。

相关文章:

Java 中的final:不可变性的魔法之旅

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 Java 中的final&#xff1a;不可变性的魔法之旅 前言第一&#xff1a;了解final变量第二&#xff1a;final方法第三&#xff1a;final类第四&#xff1a;final参数第五&#…...

Alfred 5 for mac(最好用的苹果mac效率软件)中文最新版

Alfred 5 Mac是一款非常实用的工具&#xff0c;它可以帮助用户更加高效地使用Mac电脑。用户可以学会使用快捷键、全局搜索、快速启动应用程序、使用系统维护工具、快速复制粘贴文本以及自定义设置等功能&#xff0c;以提高工作效率。 Alfred for Mac 的一些主要功能包括&#…...

常见的Python解释器,你了解多少?

Python&#xff0c;作为一种解释型编程语言&#xff0c;它的运行过程也遵循“程序源码—>解释器&#xff08;字节码&#xff09;—>虚拟机&#xff08;可执行文件&#xff09;”的流程。 在编写Python程序时&#xff0c;是在扩展名为.py的文件中进行编写&#xff0c;.py…...

在 Python 中使用 Selenium 按文本查找元素

我们将通过示例介绍在Python中使用selenium通过文本查找元素的方法。 在 Python 中使用 Selenium 按文本查找元素 软件测试是检查应用程序是否满足用户需求的技术。 该技术有助于使应用程序成为无错误的应用程序。 软件测试可以手动完成&#xff0c;也可以通过某些软件完成。…...

【Notepad++】搜索返回窗口(find result)被隐藏或遮挡如何恢复?

Notepad 搜索返回窗口被隐藏或遮挡如何恢复 1&#xff1a;F72&#xff1a;F12恢复之后可以多看一些Notepad中快捷键的使用&#xff0c;以备不时之需。 1&#xff1a;F7 打开任意文件,搜索任意内容,按F7,焦点切换到Find result。 按AltSpace&#xff0c;出现小窗口点击"移动…...

应用软件安全编程--05预防 XML 注入

如果用户有能力使用结构化XML 文档作为输入&#xff0c;那么他能够通过在数据字段中插入 XML 标签来 重写这个 XML 文档的内容。 XML 解析器会将这些标签按照正常标签进行解析。下面是一段在线商 店的 XML 代码&#xff0c;主要用于查询后台数据库。 <item)<descri…...

JavaEE-博客系统3(功能设计)

本部分内容为&#xff1a;实现登录功能&#xff1b;强制要求用户登录&#xff1b;实现显示用户信息&#xff1b;退出登录&#xff1b;发布博客 该部分的后端代码如下&#xff1a; Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws Ser…...

椭圆滤波器

之前的文章 信号去噪 中列出了7种常用的信号去噪算法&#xff0c;对于后两种算法——深度学习和奇异值分解(SVD)&#xff0c;我现在也不太理解&#xff0c;就先不写了。 很多朋友留言又提了一些算法&#xff0c;今天一起来聊聊椭圆滤波器。 椭圆滤波器&#xff08;Elliptic F…...

Mac 下安装golang环境

一、下载安装包 安装包下载地址 下载完成&#xff0c;直接继续----->下一步到结束即可安装成功&#xff1b; 安装成功之后&#xff0c;验证一下&#xff1b; go version二、配置环境变量 终端输入vim ~/.zshrc进入配置文件&#xff0c;输入i进行编辑 打开的不管是空文本…...

前端面试大纲

一、CSS 1.说一下CSS的盒模型。 在HTML页面中的所有元素都可以看成是一个盒子 盒子的组成&#xff1a;内容content、内边距padding、边框border、外边距margin 盒模型的类型&#xff1a; 标准盒模型 margin border padding content IE盒模型 margin content(border padd…...

CAN(Controller Area Network)是一种用于在汽车和工业领域中进行通信的串行总线系统(附加案例)

CAN&#xff08;Controller Area Network&#xff09;是一种用于在汽车和工业领域中进行通信的串行总线系统。它是一种高可靠性、多主机、多节点通信协议&#xff0c;主要用于实时控制和数据传输。 CAN数据是指在CAN总线上通过CAN协议进行通信传输的数据。CAN总线上的数据被分…...

代码随想录day53|1143.最长公共子序列、 1035.不相交的线、 53. 最大子序和

1143.最长公共子序列 dp[i][j]&#xff1a;长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j] 因此是if(nums1[i-1] nums2[j-1]) 1035.不相交的线 和上一题一样 53. 最大子序和 int result dp[0]; 不是0&#xff0c;因为dp[i]有…...

xilinx fpga ddr mig axi

硬件 参考&#xff1a; https://zhuanlan.zhihu.com/p/97491454 https://blog.csdn.net/qq_22222449/article/details/106492469 https://zhuanlan.zhihu.com/p/26327347 https://zhuanlan.zhihu.com/p/582524766 包括野火、正点原子的资料 一片内存是 1Gbit 128MByte 16bit …...

《golang设计模式》第三部分·行为型模式-04-迭代器模式(Iterator)

文章目录 1. 概念1.1 角色1.2 类图 2. 代码示例2.1 需求2.2 代码2.3 类图 1. 概念 迭代器&#xff08;Iterator&#xff09;能够在不暴露聚合体内部表示的情况下&#xff0c;向客户端提供遍历聚合元素的方法。 1.1 角色 InterfaceAggregate&#xff08;抽象聚合&#xff09;…...

python加上ffmpeg实现音频分割

前言: 这是一个系列的文章,主要是使用python加上ffmpeg来对音视频文件进行处理,包括音频播放、音频格式转换、音频文件分割、视频播放等。 系列文章链接: 链接1: python使用ffmpeg来制作音频格式转换工具(优化版) 链接2:<Python>PyQt5+ffmpeg,简单视频播放器的编写(…...

LLM之Prompt(一):5个Prompt高效方法在文心一言3.5的测试对比

在Effective Prompt: 编写高质量Prompt的14个有效方法文中我们了解了14个编写Prompt的方法&#xff08;非常感谢原作者&#xff09;&#xff0c;那么这些Prompt在具体大模型中的效果如何呢&#xff1f;本文以百度文心一言3.5版本大模型在其中5个方法上做个测试对比。 第1条&am…...

TreeBERT:基于树的编程语言预训练模型。

TreeBERT https://arxiv.org/abs/2105.12485 Comments: Accepted by UAI2021 Subjects: Machine Learning (cs.LG); Programming Languages (cs.PL) Cite as: arXiv:2105.12485 [cs.LG] 1 Introduction 现有挑战&#xff1a; 设计适当的机制来学习程序的语法结构 代码是强结…...

生成小程序的二维码的base64码(中间logo可以自定义)

1.生成基础二维码 /*** 生成微信小程序二维码&#xff0c;带参数,最终转成base64* param page 当前小程序相对页面 必须是已经发布的小程序存在的页面(否则报错)&#xff0c;例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里)&#xff0c;如果不…...

【音视频 | Ogg】Ogg封装格式详解——包含Ogg封装过程、数据包(packet)、页(page)、段(segment)等

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…...

ubuntu 22.04 安装ros2 iron

目录 一、镜像 二、ifconfig 三、ssh连接不上 四、安装iron 一、镜像 123云盘直接下载 二、ifconfig sudo apt install net-tools 三、ssh连接不上 sudo apt install openssh-server 四、安装iron Ubuntu (Debian packages) — ROS 2 Documentation: Iron document…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...