首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何用更少的代码(或使用一些Kotlin的扩展函数)来实现相同的功能

使用Kotlin的扩展函数可以帮助我们用更少的代码来实现相同的功能。扩展函数是一种特殊的函数,它可以在已有的类上添加新的函数,而无需修改原始类的代码。

下面是一个示例,展示如何使用Kotlin的扩展函数来实现相同的功能:

代码语言:txt
复制
// 假设我们有一个字符串类
class MyString(val value: String)

// 使用扩展函数为字符串类添加一个反转函数
fun MyString.reverse(): MyString {
    val reversedValue = value.reversed()
    return MyString(reversedValue)
}

// 使用扩展函数为字符串类添加一个统计字符数的函数
fun MyString.countCharacters(): Int {
    return value.length
}

// 使用扩展函数为字符串类添加一个转换为大写的函数
fun MyString.toUpperCase(): MyString {
    val upperCaseValue = value.toUpperCase()
    return MyString(upperCaseValue)
}

// 使用扩展函数为字符串类添加一个判断是否为空的函数
fun MyString.isEmpty(): Boolean {
    return value.isEmpty()
}

// 使用扩展函数为字符串类添加一个判断是否包含指定字符的函数
fun MyString.contains(char: Char): Boolean {
    return value.contains(char)
}

// 使用扩展函数为字符串类添加一个判断是否以指定前缀开头的函数
fun MyString.startsWith(prefix: String): Boolean {
    return value.startsWith(prefix)
}

// 使用扩展函数为字符串类添加一个判断是否以指定后缀结尾的函数
fun MyString.endsWith(suffix: String): Boolean {
    return value.endsWith(suffix)
}

// 使用扩展函数为字符串类添加一个判断是否为数字的函数
fun MyString.isNumber(): Boolean {
    return value.matches(Regex("-?\\d+(\\.\\d+)?"))
}

// 使用扩展函数为字符串类添加一个判断是否为邮箱地址的函数
fun MyString.isEmail(): Boolean {
    return value.matches(Regex("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"))
}

// 使用扩展函数为字符串类添加一个判断是否为URL的函数
fun MyString.isUrl(): Boolean {
    return value.matches(Regex("^(http|https)://[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}(/\\S*)?$"))
}

// 使用扩展函数为字符串类添加一个判断是否为手机号码的函数
fun MyString.isPhoneNumber(): Boolean {
    return value.matches(Regex("^1[3456789]\\d{9}$"))
}

// 使用扩展函数为字符串类添加一个判断是否为身份证号码的函数
fun MyString.isIdCardNumber(): Boolean {
    return value.matches(Regex("(^\\d{15}$)|(^\\d{17}([0-9]|X)$)"))
}

// 使用扩展函数为字符串类添加一个判断是否为IP地址的函数
fun MyString.isIpAddress(): Boolean {
    return value.matches(Regex("^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$"))
}

// 使用扩展函数为字符串类添加一个判断是否为日期的函数
fun MyString.isDate(): Boolean {
    return try {
        LocalDate.parse(value)
        true
    } catch (e: DateTimeParseException) {
        false
    }
}

// 使用扩展函数为字符串类添加一个判断是否为时间的函数
fun MyString.isTime(): Boolean {
    return try {
        LocalTime.parse(value)
        true
    } catch (e: DateTimeParseException) {
        false
    }
}

// 使用扩展函数为字符串类添加一个判断是否为日期时间的函数
fun MyString.isDateTime(): Boolean {
    return try {
        LocalDateTime.parse(value)
        true
    } catch (e: DateTimeParseException) {
        false
    }
}

在上述示例中,我们定义了一个MyString类,并使用扩展函数为该类添加了多个功能,包括字符串反转、字符数统计、转换为大写、判断是否为空、判断是否包含指定字符、判断是否以指定前缀开头、判断是否以指定后缀结尾、判断是否为数字、判断是否为邮箱地址、判断是否为URL、判断是否为手机号码、判断是否为身份证号码、判断是否为IP地址、判断是否为日期、判断是否为时间、判断是否为日期时间等。

使用这些扩展函数,我们可以通过以下方式调用它们:

代码语言:txt
复制
val myString = MyString("Hello, World!")

val reversedString = myString.reverse()
println(reversedString.value) // 输出: !dlroW ,olleH

val characterCount = myString.countCharacters()
println(characterCount) // 输出: 13

val upperCaseString = myString.toUpperCase()
println(upperCaseString.value) // 输出: HELLO, WORLD!

val isEmpty = myString.isEmpty()
println(isEmpty) // 输出: false

val containsChar = myString.contains('o')
println(containsChar) // 输出: true

val startsWithPrefix = myString.startsWith("Hello")
println(startsWithPrefix) // 输出: true

val endsWithSuffix = myString.endsWith("World!")
println(endsWithSuffix) // 输出: true

val isNumber = myString.isNumber()
println(isNumber) // 输出: false

val isEmail = myString.isEmail()
println(isEmail) // 输出: false

val isUrl = myString.isUrl()
println(isUrl) // 输出: false

val isPhoneNumber = myString.isPhoneNumber()
println(isPhoneNumber) // 输出: false

val isIdCardNumber = myString.isIdCardNumber()
println(isIdCardNumber) // 输出: false

val isIpAddress = myString.isIpAddress()
println(isIpAddress) // 输出: false

val isDate = myString.isDate()
println(isDate) // 输出: false

val isTime = myString.isTime()
println(isTime) // 输出: false

val isDateTime = myString.isDateTime()
println(isDateTime) // 输出: false

通过使用Kotlin的扩展函数,我们可以在不修改原始类代码的情况下,为现有类添加新的功能,从而实现相同的功能,同时减少了代码量。这种方式可以提高代码的可读性和可维护性,并且可以更好地组织和重用代码。

腾讯云相关产品和产品介绍链接地址:

请注意,以上仅为腾讯云的一些相关产品,其他云计算品牌商也提供类似的产品和服务。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

如何优雅地使用策略模式实现更灵活、可扩展和易于维护代码

策略模式是一种常见设计模式,用于封装不同算法,并使其可以相互替换。在这篇文章中,我们将介绍如何优雅地使用策略模式实现更灵活、可扩展和易于维护代码。什么是策略模式?...ConcreteStrategy(具体策略):包含了具体算法实现。为什么要使用策略模式?策略模式有以下几个优点:算法实现使用相互分离,使得算法变化不会影响客户端代码。...可以通过组合多个策略对象实现复杂功能,从而提高代码可复用性和可扩展性。使用继承通常会导致高耦合、低灵活性和难以维护代码,而策略模式使得代码更加简洁、清晰和易于维护。如何使用策略模式?...,我们使用了构造函数来设置默认支付策略,并使用setPayment方法动态地更改当前支付方式。...通过使用策略模式,可以使代码更加灵活、可扩展和易于维护。在实际开发中,我们可以使用策略模式解决各种不同问题,例如支付、排序、搜索等。

46340

Kotlin概述与Java比较

允许我们扩展现有类功能,而不继承它们。...意味着Kotlin提供了扩展具有新功能能力,而无需继承类。这是通过扩展功能完成。要声明一个扩展功能,我们需要用一个接收器类型,即被扩展类型加上它名字。...以下为MutableList 添加交换函数扩展功能“this”关键字对应于接收者对象,即在点之前传递对象。...增量构建 但是我们知道,大多数时候我们需要增量构建,就像我们在现有代码中进行一些修改,然后构建它们并进行连续部署 所以在这个角度来看,Kotlin与Java相比需要相同时间编译,甚至比Java要快一些...具有更多声明,更少代码,混合语言数据库,比Java更具表现力,使Kotlin成为企业应用和移动未来发展方向。

3K10
  • 基于Spring Boot及Kotlinddd领域驱动实现

    Kotlin优势带来结果就是: • 代码更少,更简洁,更优雅 • Kotlin提供了很多函数语法,你不会想错过它 • 更易于维护,质量更可靠 实现思路 我并没有重新写一个myddd-kotlin...所谓,实践才能出真知,在意识到这一点后,我就尝试了基于myddd-java实现一个Spring Boot + Kotlin组合。 经过一些时间尝试之后,我认为这是个非常好组合。...我在这里仅贴一些代码展示它简洁与优雅性。...user.phone = phone user.email = email return user } Kotlin中有扩展语法功能,这种实现相比通过继承组合扩展已有类功能,更简洁优雅...而myddd-spring-boot一些扩展支持通用模块,权限,媒体,组织等也在开发完善中。 值得考虑选择 对于大多数公司架构师来说,使用Vert.x这样小众异步式框架,可能是很难

    1.2K20

    使用 Kotlin 提高生产力

    在接下来内容中,我会分享一些 Kotlin 帮助我们合作伙伴工程师们提高生产力方式,并为您介绍有助于此 Kotlin 功能。...——Flipkart Kotlin 功能与生产力 由于 Kotlin 简洁与高可读性,大多数 Kotlin 功能都可以提高生产力。下面让我们来看一些最常用功能。...在使用 Kotlin 时,由于默认参数功能存在,您无需使用这两种方法。默认参数使您无需额外样板代码便能实现函数重载。...总结 Kotlin 使得阅读和编写代码变得简单,它内建了诸如 单例 和 委托 这类模式实现,从而可以帮助我们移除那些可能导致 bug 增加维护成本代码。...而像 字符串模板、lambda 表达式、扩展函数、操作符重载 这类功能则可以使代码更加简洁明了。

    35320

    Kotlin】为什么要优先使用 Kotlin 进行 Android 开发?

    那么,为什么要优先使用Kotlin进行Android开发呢? 1. **现代化和安全性**: Kotlin是一种现代化静态类型编程语言,设计初衷是为了解决Java语言一些痛点和不足。...它引入了许多现代编程语言特性,空安全(null safety)、lambda表达式、扩展函数等,这些特性能显著提升开发效率和代码质量。 2....**开发效率**: Kotlin代码通常比Java更简洁和易于维护,这意味着开发者可以用更少代码实现相同功能。...此外,许多流行Android开发工具Android Studio都已经对Kotlin提供了很好支持,这使得使用Kotlin进行开发更加便捷。...谁在使用 KotlinKotlin作为一门现代化编程语言,已经被广泛采纳和应用于各个领域和公司。以下是一些正在使用Kotlin知名公司和组织: 1.

    11510

    kotlin相比于java好处和坏处_kotlin和java

    提供快速编译 Kotlin 无需对代码做任何改动即可支持多种扩展功能 您可以使用 IDE 使用命令行界面编写 Kotlin 代码 Java特点 以下是 Java 重要特性。...Java 使用静态成员。 原始类型变量是对象 原始类型变量不是对象 在 Kotlin 中,我们可以有一个多个二级构造函数。 在 Java 中,我们不能有二级构造函数。...它支持现代编程概念,委托、扩展、高阶函数。 Java 支持 OOPS 编程概念。...帮助开发者创建扩展功能 提供了一种非常简单且几乎自动化方式创建数据类 Kotlin 是一种静态类型语言,因此非常易于阅读和编写。 这种语言允许以各种方式交换和使用来自 Java 信息。...在 Kotlin 中编写新代码将花费更少时间。 部署 kotlin 代码并大规模维护它非常容易。 Java优势 在这里,是 Java 优点/好处 改进错误检测和解决检查异常 提供详细文档。

    6.2K10

    Java与Kotlin, 哪个是开发安卓应用首选语言?

    IDEA)开发者所设计,它为 Java 添加了一些现代功能,这对移动开发很有帮助。...Kotlin 是一种基于 Java 虚拟机(JVM)开源、静态类型语言,但您也可以将其编译为 JavaScript Native,以构建可在 iOS 上运行代码。...Gradle 构建文件中,然后单击 “转换” 就好了; 包含智能扩展功能,帮助开发者构建干净 API; 在其类型系统中设有 null – null 问题是 Java 开发中一个常见问题,由于 Android...经常使用 null 表示值不存在,因此 Kotlin 通过将 null 直接设置在类型系统中解决该问题; 它比 Java 简洁得多,这意味着代码写错几率大大下降了; 与 Java 可互操作 –...结语 无论你喜欢使用Java还是Kotlin,对于开发者,在熟练掌握了某种语言基础上,学习新语言,有肋提升个人竞争力。不妨像文中提到那些开发者那样,尝试用这些语言开发一些项目。

    4K30

    Kotlin简单问

    kotlin为什么被设计出来 kotlin被设计出来并被Google推广,主要有以下优势: 完全兼容Java 更少空指针异常 更少代码量,更快开发速度(lambda表达式,扩展函数kotlin...get和set方法,可以直接省略,直接使用属性名即可,会根据表达式实际功能来添加对应set或者get方法。...扩展属性原理 kotlin这个扩展功能确实设计很巧妙,那就一起研究下它原理: 按照上面的方法,也就是Tools -> Kotlin -> Show Kotlin Bytecode -> Decomplie..., 我们得到showToast扩展函数使用代码所对应java代码: //扩展函数 public final class UtilsKt { public static final void...然后使用时候就跟我们使用工具类一样调用工具类方法即可。 拜拜 今天就聊这么多了,kotlin东西还是挺多,也有一些考点,下次继续聊。 ?

    86930

    Java 已老,Kotlin 将取而代之?

    但在Kotlin中更简单,甚至对于非builder类也一样。 Kotlin还提供了apply这个扩展函数,能够实现相同功能。...Delegationdecorator模式无须再使用样板代码 为了使用组合代替继承,我们通常采用delegationdecorator模式,但wrapper类必须重复被代理每个方法。...与Scala不同,Kotlin没有自己集合库,它只是扩展了JDK集合。因此在Java和Kotlin集合类型之间转换无需使用胶水代码。...还可以通过实现rangeTo和contains方法重载 .. 和 in 运算符。 扩展现有的JDK类很容易 Kotlin可以通过非常简单方式给现有的类增加扩展函数。...这是个很强大功能,利用它可以轻松扩展语言核心API。 ▌为什么应该使用Kotlin

    1.7K30

    Kotlin 1.2 新特性

    跨平台 跨平台项目是 Kotlin 1.2 中一个新实验性功能,它允许开发者从相同代码库构建应用程序多个层——后端、前端和Android应用程序,在这个跨平台方案中,主要包含三个模块。...请注意,目前跨平台项目只是一个实验性功能,这意味着该功能已经可以使用,但可能需要在后续版本中更改设计 编译性能 在1.2开发过程中,团队花了很多精力优化编译系统,据官方提供资料显示,与Kotlin...但是,如果构造函数调用参数中存在这样表达式时,一些字节码处理工具不能很好地处理这些代码。...在Kotlin 1.2中,会出现一个错误,因此需要使用JVM target 1.8编译这些代码。...内联扩展空修复 在以前版本中,在平台类型空值上调用内联扩展函数没有检查接收器是否为null,并因此允许null转义到其他代码中。

    1.7K100

    从 Java 到 Kotlin,再从 Kotlin 回归 Java

    当您Kotlin代码必须与Java代码一起使用时,事情就变得很糟糕了(库是用Java编写,所以我猜它经常发生)。然后,第三种类型就跳出来了——T!它被称为平台类型,它意思是TT?...我们研究一下这个问题。 通常,在使用 Optional 时,你会先进行一系列空安全转换,最后来处理空值。 比如在 Java 中: ? 在 Kotlin 中也没问题,使用 let 功能: ?...在实现简单DTO时它非常有用。但请记住,数据类带有严重局限性 - 它们是final。你无法扩展Data类将其抽象化。所以很可能,你不会在核心领域模型中使用它们。...Spring 使用一些库(cglib、jassist)为 Java Bean 生成动态代理。Hibernate 会扩展实体类实现懒加载。 如果使用 Spring,你有两个选择。...Java代码是正确Groovy代码,因此你可以从将.java文件扩展名更改为.groovy扩展名开始。每次你学习新Groovy功能时,你都可以做出决定。你喜欢它还是喜欢用Java方式?

    1.8K40

    【翻译】Kotlin致简代码之路

    在这篇文章里,我会通过讲解一些关于简洁代码方面的建议和原则,求证 Kotlin 是否有助于达成这样目的。另外,我也会指出一些我们应该谨慎注意限制之处。...Kotlin 可以帮我们做到这点吗?不行,因为这些规则是无关于语言。这仍然取决于开发者自己创建小函数。 然而,使用 Java 有时候很难写出小而富有表达力函数。让我举个例子。...尽管如此,这些代码很冗繁并且包含有语法噪点。作为比较,看一下在 Kotlin 中同样功能实现代码。 // Kotlin fun parseProduct(response: Response?)...不需要了解每一个特性就能看懂代码,意味着这些代码非常符合直觉。那就是所谓致简代码使用 Kotlin ,我们可以用更少代码( 15 行对比 6 行)最少形式主义前提下达到业务逻辑实现。...总之, Kotlin空值处理体系使得我们代码既安全而又少出错。这仅仅只需要添加一些语法结构就能实现(比方说在类型后面的 ? )。对于我来说,这种安全类型方式非常好。

    1.4K30

    Kotlin 1.2 新增特性

    弃用:数据类覆写性拷贝 当从已经具有相同签名拷贝函数类型派生数据类时,为数据类生成 copy 实现使用父类型默认函数,会导致出现与预期相反行为,如果父类型没有默认参数,则在运行时失败 导致复制冲突继承已经被...新 artifacts 中声明从 Kotlin 角度来看在相同包名下可见,但是对 Java 而言它们有不同包名。因此,切换到新 artifacts 不需要对源代码进行任何更改。...不幸是,当构造函数调用参数中存在这样表达式时,一些字节码处理工具不能很好地处理这些代码。...在 Kotlin 1.2 中,这将会报错,因此需要使用 JVM 1.8 编译这些代码。 破坏性变更:平台类型 x.equals(null) 一致行为 在映射到 Java 原语 (Int!...工具 将警告视为错误 编译器现在提供了将所有警告视为错误选项。在命令行中使用 -Werror,使用以下 Gradle 代码

    2.8K70

    Kotlin 1.2 新增了哪些特性?

    actual 声明或是 API 平台相关实现,或是在外部库中 API 现有实现别名引用。下面是一个示例: 在通用代码中: ? 在 JVM 平台中,代码如下所示: ?...弃用:数据类覆写性拷贝 当从已经具有相同签名拷贝函数类型派生数据类时,为数据类生成 copy 实现使用父类型默认函数,会导致出现与预期相反行为,如果父类型没有默认参数,则在运行时失败 导致复制冲突继承已经被...不幸是,当构造函数调用参数中存在这样表达式时,一些字节码处理工具不能很好地处理这些代码。...在 Kotlin 1.2 中,这将会报错,因此需要使用 JVM 1.8 编译这些代码。 破坏性变更:平台类型 x.equals(null) 一致行为 在映射到 Java 原语 (Int!...工具 将警告视为错误 编译器现在提供了将所有警告视为错误选项。在命令行中使用 -Werror,使用以下 Gradle 代码: ?

    2.8K10

    31 天,从浅到深轻松学习 Kotlin

    像 Path,Range SpannableStrings 这样对象允许像加法减法这样操作。通过 Kotlin,您可以实现自己操作符。 Day 21:顶级方法和参数 类实用方法?...第三周学习小结: 本周主要讨论一些基本 Kotlin 特性,运算符重载,内联,运算符重载,懒加载,以及非常强大 inLine,并展示了使用 Android KTX 处理内容值,捆绑包和回调时如何编写更简洁代码...Day 26:延期方法 没有更多 Util 类。通过使用扩展功能扩展功能。把您要扩展名字放在您添加方法名字前面。...扩展功能一些特性: 不是成员函数 不要以任何方式修改原始类 通过静态类型信息解决编译时间 会被编译为静态函数 不要多态性 例如:String.toUri() Day 27...Day 29:更简单 Spans 功能强大但很难使用 - 这就是 Spans API 感觉文本样式。 Android KTX 为一些最常见 span 添加了扩展功能,并使 API 更易于使用

    2.2K30

    Kotlin 1.4 版本正式发布:新功能一覽

    此次版本更新花费了很多精力提高 Kotlin 及其工具性能和质量,例如高亮显示速度提高了 1.5-4 倍,支持多种新语言功能,例如 Kotlin 接口 SAM 转换。...新编译器 新编译器实现目标是变得更快速、统一 Kotlin 支持所有平台,并提供用于编译器扩展 API。...有些功能也已经发布了; 例如,如果您尝试了用于类型推理新算法,它是新编译器一部分。其他部分处理方法相同。...我们可以直接访问平台API以及现有的代码库,同时仍然享受和使用 Kotlin 所有强大现代语言功能。...3.扩展函数 Kotlin 类似于 C# 和 Gosu, 它提供了为现有类提供新功能扩展能力,而不必从该类继承使用任何类型设计模式 (装饰器模式)。

    1.2K10

    Kotlin 能取代 Java 吗?

    Kotlin 优点 效率极高 Kotlin 语法简洁直观,编写和部署程序所需代码更少,时间也更短,大大提高了开发团队开发效率。因此,开发者可以快速开发出 Android 应用。...能够调用 Java 代码功能不仅让开发者受益,对于拥有大量 Java 代码公司来说也是利好。...Android Studio 支持 Android Studio 提供多种扩展工具有力支持,开发人员可以同时使用这两种语言。...笨重 和其他语言相比,如果要实现相同功能,Java 所需代码量更多。这不仅耗费更多开发时间,也更容易出现Bug。...Java 与 Kotlin 对比 Java Kotlin 静态成员 字符串模板 非类原始类型 单例 非私有域 空安全 通配符类型 扩展函数 检查异常 智能 Casts 毫无疑问,Java 仍然是 Android

    1.1K20

    Kotlin 开发者角度看 Java 缺失特性

    虽然 Kotlin 也被编译为 JVM 字节码,但有时候我还是不得不写一些  Java 代码。每次写 Java 代码时,我都不禁想,为什么 Java 代码看起来没有 Kotlin 那么好。...= computeNullableString() 扩展函数 在 Java 中,扩展一哥类是通过继承实现: 继承类有两个主要问题。第一个问题是有些类不允许继承:它们使用了 final 修饰符。...,不考虑极端情况; String 类型不提供首字母大写转换函数使用辅助类实现这种行为。...Kotlin 提供了扩展函数来解决同样问题。 Kotlin 提供了不通过类继承使用装饰器等设计模式实现扩展接口能力。这可以通过一种叫作扩展特殊声明来实现。 ...Kotlin 仍然需要遵循 JVM 规范,并与 Java 编译器生成字节码兼容。它可以通过内联实现:编译器用函数体替换内联方法调用。

    78320

    介绍Kotlin第二部分(翻译篇)

    Kotlin系列编程除了默认不变性外,还来自于Kotlin stdlib扩展功能。如果您熟悉函数式编程,那么您将熟悉大部分功能。它们是一组辅助函数和更高级辅助函数,可以为您集合提供常用操作。...Kotlin标准库collection扩展功能优点来自于易使用lambdas表达式,只需使用足够类型推理保证编程安全。在Kotlin中有几种方法定义lambdas函数。...第三个介绍了一个扩展功能,我们可以用它调用let。如果我们想从我们函数返回一些东西,我们可以使用elvis作为默认值,以防我们碰到一个null。...3、扩展功能(Apply, Let, Run, and With) Kotlin推出了一些扩展功能,可以帮助我们处理。我们看到第一个let是一个扩展,它将一个lambda作为参数。...使用运行某些东西,当且仅当它被调用对象不是null(使用它类似于let上面的几行,但在run这种情况下this作为范围对象)使用调用我们函数调用并保护我们lambdas。

    97840

    Gradle Kotlin DSL指南

    下面的示例显示了来自原始示例构建脚本sourceSets{}和java{}块,你可以使用configure()函数和相应类型实现: apply(plugin = "java-library"...您可以通过查看应用插件文档运行gradle kotlinDslAccessorsReport发现可用扩展和约定,该报告打印了访问所有应用插件提供模型元素所必需Kotlin代码。...在我们示例构建脚本中,我们想要在源集容器中配置一个名为main源集,我们可以通过使用named()方法代替访问器实现,如下所示: 作为容器项目扩展元素 apply(plugin = "java-library...作为最后手段,你可以查看插件代码来了解它功能,但在大多数情况下这是不必要。 Tasks 任务不是通过基于容器项目扩展管理,但它们是以类似方式运行容器一部分。...要从Kotlin调用Groovy扩展方法,可以采用相同方法:将其作为静态函数调用,将接收方作为第一个参数传递。

    10.2K20
    领券