新用户注册入口 老用户登录入口

[转载]java中访问不可视字段_Kotlin与Java的不同之处

文章作者:转载 更新时间:2023-06-23 23:56:14 阅读数量:469
文章标签:Kotlin静态成员模拟
本文摘要:本文详细阐述了 Kotlin 中的伴生对象如何模拟 Java 静态成员,并介绍了在 Java 代码中调用 Kotlin 伴生对象的方法,通过 @JvmField 和 @JvmStatic 注解实现与 Java 静态成员调用方式一致。同时,文章探讨了 Kotlin 扩展函数和扩展属性的定义与使用,以及它们如何方便地对已有类进行功能扩展。此外,还深入解析了 Kotlin 内部类、匿名内部类、数据类、枚举类等特性,并展示了委托模式在 Kotlin 中的应用,包括委托属性及标准库提供的内联函数、延迟属性、可观察属性等实用委托实现。
转载文章

本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_39611037/article/details/109984124。

该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。

作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。

如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。

code小生,一个专注 Android 领域的技术平台

公众号回复 Android 加入我的安卓技术群

作者:小村医

链接:https://www.jianshu.com/p/f7deb4fe6427

声明:本文已获小村医授权发表,转发等请联系原作者授权

伴生对象

在 Kotlin 中并不没有 static 这个关键字,该如何处理呢?这里需要用到 Kotlin 的伴生对象来处理。

类内部的对象声明可以用 companion 关键字标记:

class MyClass {

该伴生对象的成员可通过只使用类名作为限定符来调用:

val instance = MyClass.create()

可以省略伴生对象的名称,在这种情况下将使用名称 Companion:

class MyClass {

伴生对象的作用

类似于 Java 中使用类访问静态成员的语法。因为 Kotlin 取消了 static 关键字,所以 Kotlin 引入伴生对象来弥补没有静态成员的不足。可见,伴生对象的主要作用就是为其所在的外部类模拟静态成员。

在 Java 代码中调用伴生对象

如何在 Java 代码中调用 Kotlin 的伴生对象呢?

public static void main(String[] args) {
  • 如果声明伴生对象有名称,则使用:

类名.伴生对象名.方法名()
类名.半生对象名.属性的setter,getter方法
  • 如果声明伴生对象无名称,则采用 Companion 关键字调用:

.Companion.方法名()

@JvmField 和 @JvmStatic 的使用

在上面的例子中,我们知道了可以在 Java 代码中调用 Kotlin 中伴生对象的成员,类似于 Java 类中的静态成员。但是看上去和 Java 中的还是略有区别,因为类名和方法名/属性setter,getter方法名之间多了个伴生对象的名称或者 Companion 关键字。如何使其在调用的时候与 Java 中的调用看上去一样呢?

Kotlin 为我们提供了 @JvmField 和 @JvmStatic 两个注解。@JvmField 使用在属性上,@JvmStatic 使用在方法上。如:

class Test {

这样我们在 Java 代码中调用的时候就和 Java 类调用静态成员的形式一致了,Kotlin 代码调用方式不变:

System.out.println(Test.flag);
System.out.println(Test.add(1, 2));

const 关键字

在伴生对象中,我们可能需要声明一个常量,目的是等同于 Java 中的静态常量。有两种方式,一种是上面所提到的使用 @JvmField 注解,另一种则是使用 const 关键字修饰。这两种声明方式都等同于 Java 中 static final 所修饰的变量。如下代码:

companion 

扩展属性和扩展方法

扩展函数

Kotlin的扩展函数可以让你作为一个类成员进行调用的函数,但是是定义在这个类的外部。这样可以很方便的扩展一个已经存在的类,为它添加额外的方法

下面我们为String添加一个toInt的方法

package com.binzi.kotlin

在这个扩展函数中,你可以直接访问你扩展的类的函数和属性,就像定义在这个类中的方法一样,但是扩展函数并不允许你打破封装。跟定义在类中方法不同,它不能访问那些私有的、受保护的方法和属性。

扩展函数的导入

我们直接在包里定义扩展函数。这样我们就可以在整个包里面使用这些扩展,如果我们要使用其他包的扩展,我们就需要导入它。导入扩展函数跟导入类是一样的方式。

import 

有时候,可能你引入的第三方包都对同一个类型进行了相同函数名扩展,为了解决冲突问题,你可以使用下面的方式对扩展函数进行改名

import com.binzi.kotlin.toInt as toInteger

扩展函数不可覆盖

扩展方法的原理

Kotlin 中类的扩展方法并不是在原类的内部进行拓展,通过反编译为Java代码,可以发现,其原理是使用装饰模式,对源类实例的操作和包装,其实际相当于我们在 Java中定义的工具类方法,并且该工具类方法是使用调用者为第一个参数的,然后在工具方法中操作该调用者

如:

fun String?.toInt(): 

反编译为对应的Java代码:

public 

扩展属性

类的扩展属性原理其实与扩展方法是一样的,只是定义的形式不同,扩展属性必须定义get和set方法

为MutableList扩展一个firstElement属性:

var 

反编译后的java代码如下:

public static final Object getFirstElement(@NotNull List $this$firstElement) {

内部类

kotlin的内部类与java的内部类有点不同java的内部类可以直接访问外部类的成员,kotlin的内部类不能直接访问外部类的成员,必须用inner标记之后才能访问外部类的成员

  • 没有使用inner标记的内部类

class A{

反编译后的java代码

public 
  • 用inner标记的内部类

class A{

反编译后的java代码

public 

从上面可以看出,没有使用inner标记的内部类最后生成的是静态内部类,而使用inner标记的生成的是非静态内部类

匿名内部类

匿名内部类主要是针对那些获取抽象类或者接口对象而来的。最常见的匿名内部类View点击事件:

//java,匿名内部类的写法

上面这个是java匿名内部类的写法,kotlin没有new关键字,那么kotlin的匿名内部类该怎么写呢?

object : View.OnClickListener{

方法的参数是一个匿名内部类,先写object:,然后写你的参数类型View.OnClickListener{}

kotlin还有一个写法lambda 表达式,非常之方便:

print(

数据类

在Java中没有专门的数据类,常常是通过JavaBean来作为数据类,但在Kotlin中提供了专门的数据类。

  • Java

public 

从上面的例子中可以看到,如果要使用数据类,需要手动写相应的setter/getter方法(尽管IDE也可以批量生成),但是从代码阅读的角度来说,在属性较多的情况下,诸多的seeter/getter方法还是不利于代码的阅读和维护。

  • Kotlin
    在Kotlin中,可以通过关键字data来生成数据类:

data 

即在class关键字之前添加data关键字即可。编译器会根据主构造函数中的参数生成相应的数据类。自动生成setter/getter、toString、hashCode等方法

要声明一个数据类,需要满足:

  • 主构造函数中至少有一个参数

  • 主构造函数中所有参数需要标记为val或var

  • 数据类不能是抽象、开发、密封和内部的

枚举类

枚举类是一种特殊的类,kotlin可以通过enum class关键字定义枚举类。

枚举类可以实现0~N个接口;

  • 枚举类默认继承于kotlin.Enum类(其他类最终父类都是Any),因此kotlin枚举类不能继承类;

  • 非抽象枚举类不能用open修饰符修饰,因此非抽象枚举类不能派生子类;

  • 抽象枚举类不能使用abstract关键字修饰enum class,抽象方法和抽象属性需要使用;

  • 枚举类构造器只能使用private修饰符修饰,若不指定,则默认为private;

  • 枚举类所有实例在第一行显式列出,每个实例之间用逗号隔开,整个声明以分号结尾;

  • 枚举类是特殊的类,也可以定义属性、方法、构造器;

  • 枚举类应该设置成不可变类,即属性值不允许改变,这样更安全;

  • 枚举属性设置成只读属性后,最好在构造器中为枚举类指定初始值,如果在声明时为枚举指定初始值,会导致所有枚举值(或者说枚举对象)的该属性都一样。

定义枚举类

/**
 * 定义一个枚举类
 */

枚举类实现接口

  1. 枚举值分别实现接口的抽象成员

enum 
  1. 枚举类统一实现接口的抽象成员

enum 
  1. 分别实现抽象枚举类抽象成员

enum 

委托

委托模式 是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式。委托模式使得我们可以用聚合来替代继承。

Java中委托:

interface Printer {

Kotlin:

interface Printer {

by表示 p 将会在 PrintImpl 中内部存储, 并且编译器将自动生成转发给 p 的所有 Printer 的方法。

委托属性

有一些常见的属性类型,虽然我们可以在每次需要的时候手动实现它们, 但是如果能够为大家把他们只实现一次并放入一个库会更好。例如包括:

  • 延迟属性(lazy properties): 其值只在首次访问时计算;

  • 可观察属性(observable properties): 监听器会收到有关此属性变更的通知;

  • 把多个属性储存在一个映射(map)中,而不是每个存在单独的字段中。

为了涵盖这些(以及其他)情况,Kotlin 支持 委托属性 。

委托属性的语法是:

var : 

在 by 后面的表达式是该 委托, 因为属性对应的 get()(和 set())会被委托给它的 getValue() 和 setValue() 方法。

标准委托:

Kotlin 标准库为几种有用的委托提供了工厂方法。

  1. 延迟属性 Lazy
    lazy() 接受一个 lambda 并返回一个 Lazy

    实例的函数,返回的实例可以作为实现延迟属性的委托:第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。例如:
val lazyValue: String 
  1. 可观察属性 Observable
    Delegates.observable() 接受两个参数:初始值和修改时处理程序(handler)。每当我们给属性赋值时会调用该处理程序(在赋值后执行)。它有三个参数:被赋值的属性、旧值和新值:

class User {

如果想拦截赋的新值,并根据你是不是想要这个值来决定是否给属性赋新值,可以使用 vetoable() 取代 observable(),接收的参数和 observable 一样,不过处理程序 返回值是 Boolean 来决定是否采用新值,即在属性被赋新值生效之前 会调用传递给 vetoable 的处理程序。例如:

class User {
  1. 把属性存在map 中
    一个常见的用例是在一个映射(map)里存储属性的值。这经常出现在像解析 JSON 或者做其他“动态”事情的应用中。在这种情况下,你可以使用映射实例自身作为委托来实现委托属性。

例如:

class User(map: Map

在上例中,委托属性会从构造函数传入的map中取值(通过字符串键——属性的名称),如果遇到声明的属性名在map 中找不到对应的key 名,或者key 对应的value 值的类型与声明的属性的类型不一致,会抛出异常。

内联函数

当一个函数被声明为inline时,它的函数体是内联的,也就是说,函数体会被直接替换到函数被调用地方

inline函数(内联函数)从概念上讲是编译器使用函数实现的真实代码来替换每一次的函数调用,带来的最直接的好处就是节省了函数调用的开销,而缺点就是增加了所生成字节码的尺寸。基于此,在代码量不是很大的情况下,我们是否有必要将所有的函数定义为内联?让我们分两种情况进行说明:

  1. 将普通函数定义为内联:众所周知,JVM内部已经实现了内联优化,它会在任何可以通过内联来提升性能的地方将函数调用内联化,并且相对于手动将普通函数定义为内联,通过JVM内联优化所生成的字节码,每个函数的实现只会出现一次,这样在保证减少运行时开销的同时,也没有增加字节码的尺寸;所以我们可以得出结论,对于普通函数,我们没有必要将其声明为内联函数,而是交给JVM自行优化。

  2. 将带有lambda参数的函数定义为内联:是的,这种情况下确实可以提高性能;但在使用的过程中,我们会发现它是有诸多限制的,让我们从下面的例子开始展开说明:

inline 

假如我们这样调用doSomething:

fun main(args: Array<String>) {

上面的调用会被编译成:

fun main(args: Array<String>) {

从上面编译的结果可以看出,无论doSomething函数还是action参数都被内联了,很棒,那让我们换一种调用方式:

fun main(args: Array<String>) {

上面的调用会被编译成:

fun main(args: Array<String>) {

doSomething函数被内联,而action参数没有被内联,这是因为以函数型变量的形式传递给doSomething的lambda在函数的调用点是不可用的,只有等到doSomething被内联后,该lambda才可以正常使用。

通过上面的例子,我们对lambda表达式何时被内联做一下简单的总结:

  1. 当lambda表达式以参数的形式直接传递给内联函数,那么lambda表达式的代码会被直接替换到最终生成的代码中。

  2. 当lambda表达式在某个地方被保存起来,然后以变量形式传递给内联函数,那么此时的lambda表达式的代码将不会被内联。

上面对lambda的内联时机进行了讨论,消化片刻后让我们再看最后一个例子:

inline 

上面的例子是否有问题?是的,编译器会抛出“Illegal usage of inline-parameter”的错误,这是因为Kotlin规定内联函数中的lambda参数只能被直接调用或者传递给另外一个内联函数,除此之外不能作为他用;那我们如果确实想要将某一个lambda传递给一个非内联函数怎么办?我们只需将上述代码这样改造即可:

inline 

很简单,在不需要内联的lambda参数前加上noinline修饰符就可以了。

以上便是我对内联函数的全部理解,通过掌握该特性的运行机制,相信大家可以做到在正确的时机使用该特性,而非滥用或因恐惧弃而不用。

Kotlin下单例模式

饿汉式实现

//Java实现

懒汉式

//Java实现

上述代码中,我们可以发现在Kotlin实现中,我们让其主构造函数私有化并自定义了其属性访问器,其余内容大同小异。

  • 如果有小伙伴不清楚Kotlin构造函数的使用方式。请点击 - - - 构造函数

  • 不清楚Kotlin的属性与访问器,请点击 - - -属性和字段

线程安全的懒汉式

//Java实现

大家都知道在使用懒汉式会出现线程安全的问题,需要使用使用同步锁,在Kotlin中,如果你需要将方法声明为同步,需要添加@Synchronized注解。

双重校验锁式

//Java实现

哇!小伙伴们惊喜不,感不感动啊。我们居然几行代码就实现了多行的Java代码。其中我们运用到了Kotlin的延迟属性 Lazy。

Lazy内部实现

public 

观察上述代码,因为我们传入的mode = LazyThreadSafetyMode.SYNCHRONIZED,
那么会直接走 SynchronizedLazyImpl,我们继续观察SynchronizedLazyImpl。

Lazy接口

SynchronizedLazyImpl实现了Lazy接口,Lazy具体接口如下:

public 

继续查看SynchronizedLazyImpl,具体实现如下:

SynchronizedLazyImpl内部实现

private 

通过上述代码,我们发现 SynchronizedLazyImpl 覆盖了Lazy接口的value属性,并且重新了其属性访问器。其具体逻辑与Java的双重检验是类似的。

到里这里其实大家还是肯定有疑问,我这里只是实例化了SynchronizedLazyImpl对象,并没有进行值的获取,它是怎么拿到高阶函数的返回值呢?。这里又涉及到了委托属性

委托属性语法是:val/var : by 。在 by 后面的表达式是该 委托, 因为属性对应的 get()(和 set())会被委托给它的 getValue() 和 setValue() 方法。属性的委托不必实现任何的接口,但是需要提供一个 getValue() 函数(和 setValue()——对于 var 属性)。

而Lazy.kt文件中,声明了Lazy接口的getValue扩展函数。故在最终赋值的时候会调用该方法。

internal.InlineOnly

静态内部类式

//Java实现

静态内部类的实现方式,也没有什么好说的。Kotlin与Java实现基本雷同。

补充

在该篇文章结束后,有很多小伙伴咨询,如何在Kotlin版的Double Check,给单例添加一个属性,这里我给大家提供了一个实现的方式。(不好意思,最近才抽出时间来解决这个问题)

class SingletonDemo private constructor(

其中关于?:操作符,如果 ?: 左侧表达式非空,就返回其左侧表达式,否则返回右侧表达式。请注意,当且仅当左侧为空时,才会对右侧表达式求值。

Kotlin 智能类型转换

对于子父类之间的类型转换

  • 先看这样一段 Java 代码

public 
  • 尽管在 main 函数中,对 person 这个对象进行了类型判断,但是在使用的时候还是需要强制转换成 Student 类型,这样是不是很不智能?

  • 同样的情况在 Kotlin 中就变得简单多了

fun main(args: Array<String>) {
  • 在 Kotlin 中,只要对类型进行了判断,就可以直接通过父类的对象去调用子类的函数了

安全的类型转换

  • 还是上面的那个例子,如果我们没有进行类型判断,并且直接进行强转,会怎么样呢?

public static void main(String[] args) {
  • 结果就只能是 Exception in thread "main" java.lang.ClassCastException

  • 那么在 Kotlin 中是不是会有更好的解决方法呢?

val person: Person = Person()
  • 在转换操作符后面添加一个 ?,就不会把程序 crash 掉了,当转化失败的时候,就会返回一个 null

在空类型中的智能转换

  • 需要提前了解 Kotlin 类型安全的相关知识(Kotlin 中的类型安全(对空指针的优化处理))

String? = 
  • aString 在定义的时候定义成了有可能为 null,按照之前的写法,我们需要这样写

String? = 
  • 但是已经进行了是否为 String 类型的判断,所以就一定 不是 空类型了,也就可以直接输出它的长度了

T.()->Unit 、 ()->Unit

在做kotlin开发中,经常看到一些系统函数里,用函数作为参数

public 

.()-Unit与()->Unit的区别是我们调用时,在代码块里面写this,的时候,两个this代表的含义不一样,T.()->Unit里的this代表的是自身实例,而()->Unit里,this代表的是外部类的实例

推荐阅读
对 Kotlin 与 Java 编程语言的思考
使用 Kotlin 做开发一个月后的感想

b9abe230b2e0da516a5a5fb8d04349c6.png

扫一扫 关注我的公众号如果你想要跟大家分享你的文章,欢迎投稿~

本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_39611037/article/details/109984124。

该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。

作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。

如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。

相关阅读
文章标题:[转载][洛谷P1082]同余方程

更新时间:2023-02-18
[转载][洛谷P1082]同余方程
文章标题:[转载]webpack优化之HappyPack实战

更新时间:2023-08-07
[转载]webpack优化之HappyPack实战
文章标题:[转载]oracle 同时更新多表,在Oracle数据库中同时更新两张表的简单方法

更新时间:2023-09-10
[转载]oracle 同时更新多表,在Oracle数据库中同时更新两张表的简单方法
文章标题:[转载][Unity] 包括场景互动与射击要素的俯视角闯关游戏Demo

更新时间:2024-03-11
[转载][Unity] 包括场景互动与射击要素的俯视角闯关游戏Demo
文章标题:[转载]程序员也分三六九等?等级差异,一个看不起一个!

更新时间:2024-05-10
[转载]程序员也分三六九等?等级差异,一个看不起一个!
文章标题:[转载]海贼王 动漫 全集目录 分章节 精彩打斗剧集

更新时间:2024-01-12
[转载]海贼王 动漫 全集目录 分章节 精彩打斗剧集
名词解释
作为当前文章的名词解释,仅对当前文章有效。
伴生对象 (Companion Object)在 Kotlin 编程语言中,伴生对象是一个与类关联的单例对象,它模拟了 Java 中的静态成员功能。通过在类内部使用 `companion` 关键字声明,伴生对象的成员可以像 Java 中调用静态方法和字段一样,仅通过类名进行访问。其作用在于提供一个共享存储空间,用于存放类相关的全局变量或全局函数,弥补 Kotlin 没有静态关键字的不足。
扩展函数 (Extension Function)Kotlin 提供的一种强大特性,允许开发者在已有类的基础上,在类外部为其定义新的函数,而无需继承或实现接口。扩展函数通过接收一个隐式的 this 参数指向被扩展的对象实例,并可以直接在该类型上调用。这种机制不仅增强了代码的可读性和简洁性,还能够在不修改原有类源码的情况下增加额外功能。
委托属性 (Delegated Property)在 Kotlin 中,委托属性是一种特殊的属性实现方式,它的 getter 和 setter 方法并不是直接由属性本身来执行,而是委托给另一个对象(称为委托)处理。通过使用 `by` 关键字将属性委托给指定的对象,每次对委托属性的访问或修改都将转发给相应的委托对象的方法。例如,Kotlin 标准库提供了 Lazy、Observable 等委托,使得属性可以在首次访问时计算值(延迟初始化),或者在属性值改变时触发通知事件等功能。委托属性是 Kotlin 为简化常见属性模式实现以及支持响应式编程等场景提供的便捷工具。
延伸阅读
作为当前文章的延伸阅读,仅对当前文章有效。
在深入理解了 Kotlin 中伴生对象、扩展函数、内部类等核心特性和委托模式的运用之后,读者可以进一步关注以下最新技术和实践动态:
1. Kotlin 1.6 新特性:Kotlin 官方团队持续优化和增强语言功能,例如在 Kotlin 1.6 版本中引入了对协程构建器的新改进,以及对类型别名(typealiases)更灵活的支持。此外,对空安全性的强化也是新版中的亮点之一,这将有助于开发者编写出更为健壮的应用代码。
2. Kotlin Multiplatform:随着跨平台开发需求的增长,Kotlin Multiplatform 成为越来越多开发者关注的焦点。它允许开发者使用 Kotlin 编写一次代码并运行在多个平台上,包括 Android、iOS、Web、后端服务器等多个环境,这对于充分利用 Kotlin 的优势,尤其是其简洁高效的语法和强大的类型系统具有重要意义。
3. JetBrains KotlinConf 2023:作为 Kotlin 官方举办的年度技术大会,KotlinConf 汇集了全球顶尖的 Kotlin 技术专家与社区成员。今年的主题围绕着 Kotlin 在现代软件架构中的应用,尤其强调了如何利用 Kotlin 的高级特性,如委托、内联函数等进行高效且易于维护的系统设计。通过收看 KotlinConf 的直播或回放,读者能够掌握最新的最佳实践,并从实际案例中深化对 Kotlin 各项特性的理解。
4. Android 开发者文档更新:鉴于 Google 对 Kotlin 的大力支持,Android 官方开发者文档也不断更新关于 Kotlin 最佳实践的内容。其中包含了如何在 Android 应用中更好地利用 Kotlin 的伴生对象实现单例模式,以及如何通过扩展函数优化 UI 组件操作等方面的具体指导。紧跟官方文档的步伐,可确保开发者能够及时了解和应用最新的 Kotlin 技术趋势。
综上所述,对于热衷于 Kotlin 技术探索的开发者而言,跟踪 Kotlin 的最新版本特性、多平台开发趋势以及行业会议动态,结合阅读官方文档以加深对 Kotlin 各种特性的实战运用,是持续提升自身技术水平的重要途径。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
pkill process_name - 结束与指定名称匹配的进程。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
js实用表单模糊搜索和自动提示插件 10-05 简单的jQuery响应式手风琴特效 01-27 发布站点前如何为站点质量做进一步优化,几个不能不知道的小工具 01-26 HessianRPC中IllegalArgumentException异常解析:方法签名与参数类型匹配在分布式系统中的实践误区与解决方案 01-16 AI助手的工作原理与限制:无法按特定要求撰写的原因及信息处理分析 12-27 Gallerybox-全屏响应式jQuery图片画廊插件 12-17 关于金融理财公司网站模板下载 11-01 SparkContext停止与未初始化错误排查:从初始化到集群通信与生命周期管理实践 09-22 jQuery和CSS3超酷3D拉窗帘式滚动导航特效 09-02 本次刷新还10个文章未展示,点击 更多查看。
简约蓝色农村电线线路安装网站模板 08-01 Tomcat性能瓶颈问题识别与解决:利用VisualVM和JProfiler分析工具进行代码优化与系统参数调整 07-31 图文经典商务外贸求职招聘企业网站模板 07-14 SeaTunnel中创建与应用自定义Transform插件:实现数据转换与业务逻辑处理,配置文件参数设置及插件打包发布 07-07 响应式精密光学仪器设备类企业前端CMS模板下载 06-12 vue口诀 04-23 宽屏蓝色海洋主题设计网站模板 04-21 美食自媒体博客类网页模板源码 04-14 公式计算 html 代码 04-01 [转载]C/C++劫持技术(函数劫持、dll注入、动态库注入、HOOK) 01-23 jQuery高仿真移动手机滑动侧边栏布局插件 01-21
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"