深入解析Kotlin 泛型

19、Kotlin 泛型与注解:深入解析与应用 本文深入解析了 Kotlin 中的泛型与注解特性。首先介绍了泛型的基础概念、声明与使用,包括泛型类、函数、约束和变体(协变与逆变),并通过示例展示了如何利用泛型提高代码复用性。随后详细讲解了注解的基本用法、内置注解及其在实际开发中的应用场景,并探讨了如何构建和使用自定义注解。最后,结合泛型与注解,展示了它们在复杂项目中的综合应用。通过本文,开发者可以全面掌握 Kotlin 泛型与注解的核心知识及其最佳实践。 阅读详情

以下文章来源于Kotlin ,作者bennyhuo

0. 引子

Kotlin 100% 与 Java 兼容,所以抛开语言表面上面的种种特质之外,背后的语言逻辑或者说“灵魂”与 Java 总是想通的。本文只涉及 Kotlin Jvm,Kotlin Js、Kotlin Native 的具体实现可能有差异。

最近一段时间在网上发了一套 Kotlin 的入门视频,涵盖了基础语法、面向对象、高阶函数、DSL、协程等比较有特色的知识点,不过有朋友提出了疑问:这门课为什么不专门讲讲泛型、反射和注解呢?

我最早听到这个问题的时候,反应比较懵逼,因为我居然没有感觉到 Kotlin 的反射、泛型特别是注解有专门学习的必要,因为他们跟 Java 实在是太像了。

实际上,从社区里面学习 Kotlin 的朋友的反应来看,大家大多对于函数式的写法,DSL,协程这些内容比较困惑,或者说不太适应,这与大家的知识结构是密切相关的,面向对象的东西大家很容易理解,因为就那么点儿内容,你懂了 C++ 的面向对象,Java 的也很容易理解,Kotlin 的也就不在话下了;而你没有接触过 Lua 的状态机,没有接触过 Python 的推导式,自然对于协程也就会觉得比较陌生。

所以我想说的是,泛型这东西,只要你对 Java 泛型有一定的认识,Kotlin 的泛型基本可以直接用。那我们这篇文章要干嘛呢?只是做一个简单的介绍啦,都很好理解的。

1. 真·泛型和伪·泛型

Java 的泛型大家肯定都知道了,1.5 之后才加入的,可以为类和方法分别定义泛型参数,就像下面这样:

 public class Generics<T>{ 
    private T t; 
    ... 

    public <R> R getResult(){ 
        ... 
    } 
 } 

Kotlin 的写法呢?完全一样:

 class Generics<T>{ 
    private val t: T 
    ... 

    fun <R> getResult(): R{ 
        ... 
    } 
 } 

Java/Kotlin 的泛型实现采用了类型擦除的方式,这与 C# 的实现不同,后者是真·泛型,前者是伪·泛型。当然这么说是从运行时的角度来看的,在编译期,Java 的泛型对于语法的约束也是真实存在的,所以你愿意的话,也可以管 Java 的泛型叫做编译期真·泛型。

那么什么是真·泛型呢?我们给大家看一段 C# 的代码:

 using System; 

 public class Program{ 
    public static void Main(String[] args){ 
        testGeneric<string>(); 
    } 

     public static void testGeneric<T>(){ 
         Console.WriteLine(typeof(T)); 
     } 
 } 

testGeneric 的泛型参数 string 可以在运行时获取到,俨然一个真实可用的类型啊。下面是输出的结果:

 System.String 

那伪·泛型呢?如果同样的代码放到 Java 或者 Kotlin 当中,结果会怎样呢?

 public static <T> void testGenerics(){ 
     System.out.println(T.class); 
 } 

这段代码无法编译,因为 T 是个泛型参数,你不能用它去获取 class 对象。为了更清楚地说明问题,我们看下下面的代码:

 public static <T> T testGenerics(){ 
     T t = null; 
     return t; 
 } 

编译后的字节码:

   public static testGenerics()Ljava/lang/Object; 
    L0 
     LINENUMBER 13 L0 
     ACONST_NULL 
     ASTORE 0 
    L1 
     LINENUMBER 14 L1 
     ALOAD 0 
     ARETURN 
    L2 
     LOCALVARIABLE t Ljava/lang/Object; L1 L2 0 
     // signature TT; 
     // declaration: T 
     MAXSTACK = 1 
     MAXLOCALS = 1 

我们看到,编译之后 T 变成了 Object,简单来说就相当于:

 public static Object testGenerics(){ 
     Object t = null; 
     return t; 
 } 

这就是传说中的类型擦除了。而 Kotlin 在 JVM 之上,编译之后也是字节码,机制与 Java 是一样的。也正是因为这个原因,我们在使用 Gson 反序列化对象的时候除了制定泛型参数,还需要传入一个 class :

 public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException { 
    ... 
 } 

显然 Gson 没有办法根据 T 直接去反序列化。

下面我们说一点儿不太一样的。在 Kotlin 当中有一个关键字叫做 reified,还有一个叫做 inline,后者可以将函数定义为内联函数,前者可以将内联函数的泛型参数当做真实类型使用,我们先来看例子:

 inline fun <reified T> Gson.fromJson(json: String): T{ 
     return fromJson(json, T::class.java) 
 } 

这是一个 Gson 的扩展方法,有了这个之后我们就无须在 Kotlin 当中显式的传入一个 class 对象就可以直接反序列化 json 了。

这个会让人感觉到有点儿迷惑,实际上由于是内联的方法调用,T 的类型在编译时就可以确定的:

 class Person(var id: Int, var name: String) 

 fun test(){ 
     val person: Person = Gson().fromJson("""{"id": 0, "name": "Jack" }""") 
 } 

反编译之后:

 public static final void test() { 
   Gson $receiver$iv = new Gson(); 
   String json$iv = "{\"id\": 0, \"name\": \"Jack\" }"; 
   Person person = (Person)$receiver$iv.fromJson(json$iv, Person.class); 
 } 

注意,在这里,inline 是必须的。

2. 型变

2.1 Java 的型变

如果 Parent 是 Child 的父类,那么 List<Parent> 和 List<Child> 的关系是什么呢?对于 Java 来说,没有关系。

也就是说下面的代码是无法编译的:

 List<Number> numbers = new ArrayList<Integer>(); //ERROR! 

不过 numbers 中可以添加 Number 类型的对象,所以我添加个 Integer 可以不呢?可以的:

 numbers.add(1); 

那么我要想添加一堆 Integer 呢?用 addAll 是吧?注意看下 addAll 的签名:

 boolean addAll(Collection<? extends E> c); 

这个泛型参数又是什么鬼?如果我把这个签名写成下面这样:

 boolean addAll(Collection<E> c); 

我想要在 numbers 当中 addAll 一个 ArrayList<Integer>,那就不可能了,因为我们说过,ArrayList<Number> 和 ArrayList<Integer> 是两个不同的类型,毛关系都没有。

? extends E 其实就是使用点协变,允许传入的参数可以是泛型参数类型为 Number 子类的任意类型。

当然,也有 ? super E 的用法,这表示元素类型为 E 及其父类,这个通常也叫作逆变。

2.2 Kotlin 的型变

型变包括协变、逆变、不变三种。

下面我们看看 Kotlin 是怎么支持这个特性的。Kotlin 支持声明点型变,我们直接看 Collection 接口的定义:

 public interface Collection<out E> : Iterable<E> { 
    ... 
 } 

out E 就是型变的定义,表明 Collection 的元素类型是协变的,即 Collection<Number> 也是 Collection<Int> 的父类。

而对于 MutableList 来说,它的元素类型就是不变的:

 public interface MutableCollection<E> : Collection<E>, MutableIterable<E> { 
    ... 
    public fun addAll(elements: Collection<E>): Boolean 
    ... 
 } 

换言之,MutableCollection<Number> 与

MutableCollection<Int> 没有什么关系。

那么请注意看 addAll 的声明,参数是 Collection<E>,而 Collection 是协变的,所以传入的参数可以是任意 E 或者其子类的集合。

逆变的写法也简单一些: Collection<in E>。

那么 Kotlin 是否支持使用点型变呢?当然支持。

我们刚才说 MutableCollection 是不变的,那么如果下面的参数改成这样:

 public fun addAll(elements: MutableCollection<E>): Boolean 

结果就是,当 E 为 Number 时,addAll 无法接类受似 ArrayList<Int> 的参数。而为了接受这样的参数,我们可以修改一下签名:

 public fun addAll(elements: MutableCollection<out E>): Boolean 

这其实就与 Java 的型变完全一致了。

2.3 @UnsafeVariance

型变是一个让人费解的话题,很多人接触这东西的时候一开始都会比较晕,我们来看看下面的例子:

 class MyCollection<out T>{ 
     fun add(t: T){ // ERROR! 
        ... 
     } 
 } 

为什么会报错呢?因为 T 是协变的,所以外部传入的参数类型如果是 T 的话,会出问题,不信你看:

 var myList: MyCollection<Number> = MyCollection<Int>() 
 myList.add(3.0) 

上面的代码毫无疑问可以编译,但运行时就会比较尴尬,因为 MyCollection<Int> 希望接受的是 Int,没想到来了一个 Double。。

对于协变的类型,通常我们是不允许将泛型类型作为传入参数的类型的,或者说,对于协变类型,我们通常是不允许其涉及泛型参数的部分被改变的。这也很容易解释为什么 MutableCollection 是不变的,而 Collection 是协变的,因为在 Kotlin 当中,前者是可被修改的,后者是不可被修改的。

逆变的情形正好相反,即不可以将泛型参数作为方法的返回值。

但实际上有些情况下,我们不得已需要在协变的情况下使用泛型参数类型作为方法参数的类型:

 public interface Collection<out E> : Iterable<E> { 
    ... 
     public operator fun contains(element: @UnsafeVariance E): Boolean 
    ... 
 } 

比如这种情形,为了让编译器放过一马,我们就可以用 @UnsafeVariance 来告诉编译器:“我知道我在干啥,保证不会出错,你不用担心”。

最后再给大家提一个点,现在你们知道为什么 in 表示逆变,out 表示协变了吗?

3. 通配符

在Java 中,当我们不知道泛型具体类型的时候可以用 ?来代替具体的类型来使用,比如下面的写法:

 Class<?> cls = numbers.getClass(); 

Kotlin 也可以有类似的写法:

 val cls: Class<*> = list.javaClass 
 val cls2: Class<*> = List::class.java 

Kotlin 可以根据 * 所指代的泛型参数进行相应的映射,下面是官方的说法:

  • 对于 Foo <out T>,其中 T 是一个具有上界 TUpper 的协变类型参数,Foo <*> 等价于 Foo <out TUpper>。 这意味着当 T 未知时,你可以安全地从 Foo <*> 读取 TUpper 的值。

  • 对于 Foo <in T>,其中 T 是一个逆变类型参数,Foo <*> 等价于 Foo <in Nothing>。 这意味着当 T 未知时,没有什么可以以安全的方式写入 Foo <*>。

  • 对于 Foo <T>,其中 T 是一个具有上界 TUpper 的不型变类型参数,Foo<*> 对于读取值时等价于 Foo<out TUpper> 而对于写值时等价于 Foo<in Nothing>。

那么 * 在哪些场合下可以或者不可以使用呢?

我们来看几个例子:

 val list = ArrayList<*>()// ERROR! 

* 不允许作为函数和变量的类型的泛型参数!

 fun <T> hello(args: Array<T>){ 
     ... 
 } 

 ... 
 hello<*>(args) // ERROR!! 

* 不允许作为函数和变量的类型的泛型参数!

 interface Foo<T> 

 class Bar : Foo<*> // ERROR! 

* 不能直接作为父类的泛型参数传入!

 interface Foo<T> 

 class Bar : Foo<Foo<*>> 

这是正确的。注意,尽管 * 不能直接作为类的泛型参数,Foo<*> 却可以,按照前面官方给出的说法,它在读时等价于Foo<out Any> 写时等价于 Foo<in Nothing>

 fun hello(args: Array<*>){ 
     ... 
 } 

同样,这表示接受的参数的类型在读写时分别等价于Array<out Any> 和 Array<in Nothing>

4. 其他

4.1 Raw 类型

Raw 类型就是对于定义时有泛型参数要求,但在使用时指定泛型参数的情况,这个只在 Java 中有,显然也是为了前向兼容而已。

例如:

 List list = new ArrayList(); 

这类用法在 Kotlin 当中是不被允许的。上面的代码大致相当于:

 val list = ArrayList<Any?>() 

不过,在 Java 中,raw 类型可以有这种写法:

 List<Integer> integers = new ArrayList<>(); 
 List list = new ArrayList(); 
 list = integers; 

但 Kotlin 中,单纯的 ArrayList<Any?> 并不是协变的,所以下面的写法是错误的:

 var list = ArrayList<Any?>() 
 val integers = ArrayList<Int>() 
 list = integers // ERROR! 

Java,你这样做很危险呀。

4.2 泛型边界

在 Java 中,我们同样可以用 extends 为泛型参数指定上限:

 class NumberFormatter<T extends Number>{ 
    ... 
 } 

这表示使用时,泛型参数必须是 Number 及其子类的一种。

而在 Kotlin 中,写法与继承类似:

 class NumberFormatter<T: Number>{ 
    ... 
 } 

如果有多个上界,那么:

 class NumberFormatter<T> where T: Number, T: Cloneable{ 
    ... 
 } 

5. 小结

通过上面的讨论,其实大家会发现 Kotlin 的泛型相比 Java 有了更严格的约束,更简洁的表述,更灵活的配置,但背后的思路和具体的实现总体来说是一致的。

26、Kotlin 泛型、注解与反射全解析 本文深入解析了 Kotlin 中的泛型、注解与反射特性。涵盖泛型中的星投影与类型别名的使用,注解的定义、参数类型、目标与内置注解的作用,以及反射的基本操作与应用场景。通过详细示例帮助开发者更好地理解 Kotlin 的高级特性,并合理运用到实际开发中。 阅读详情

相关推荐

Qi标准无线充学习笔记

负载调制主要通过接收端向后散射调制计数使得功率信号改变,两者通过线圈的电压和电流的变化量来传输信号。下面是要求稳定电流的变化量不得超出8ma,判断稳定的时间至少要在150us稳定电压的变化量不得超出110mv,判断稳定的时间至少要在150us高低电流变化量至少需要15mA,判断稳定的时间至少要在100us,主线圈电流采样的时间是在半桥转换的1/4周期刻测量的高低电压变化量至少需要200mV,判断稳定的时间至少要在100us。

m0_73991989的博客 1010

Kotlin泛型

学习目标: 学习泛型,应用场景,学以致用 学习内容: 1.泛型的基本概念 2.泛型约束 3.泛型的形变 4.UnsafeVariance 5.星投影Start Projection 6.泛型的实原理与内联特化 学习时间: 时间就像海绵里的水,挤一挤总会有的 学习开始: 第一节:泛型的基本概念 1.泛型的概念 泛型是一种类型层面的抽象 泛型通过泛型参数实现构造更加通用的类型的能力 泛型可以让符合继承关系的类型批量实现某些能力 //函数生命泛型 fun &lt...

你的益达啊 2772

JLINK/SWD/STLINK下载选项区别

摘要: 本文对比了JLINK/SWD/STLINK的6种下载模式:Normal(硬件复位)、Hot plug(无复位)、Under reset(持续复位后连接)、Software reset(软件复位)、Hardware reset(全复位)和Core reset(内核复位)。重点分析了各模式的操作逻辑、适用场景及注意事项,其中Under reset模式是解决SWD禁用/程序异常的首选方案。通过对比表归纳了复位范围、NRST操作等核心差异,并给出场景选择建议:排查连接问题优先选Under reset,常规调

亚洲程序员盟主得博客 395

Kotlin泛型 VS Java泛型

Kotlin 泛型也是 Kotlin 语言中较难理解的一个部分。Kotlin 泛型的本质也是参数化类型,并且提供了编译时强类型检查,实际上也是伪泛型,和 Java 泛型类型一样。这篇文章将介绍 Kotlin 泛型里中的重要概念,以及与 Java 泛型的对比。

datian1234的博客 503

OpenAI Codex 国内安装配置全攻略:从零到实战的 AI 编程助手集成指南

AI 编程助手正成为提升开发效率的关键工具,其核心原理是基于大规模语言模型对代码语义进行深度理解与生成。这类技术通过将自然语言指令转化为可执行的代码、自动化重构与调试,为开发者提供了智能化的结对编程体验,其技术价值在于显著降低编码复杂度、加速项目迭代。在实际应用场景中,AI 编程助手可集成于日常开发流,辅助完成代码生成、项目分析与自动化任务。本文聚焦于 OpenAI 的 Codex,针对国内开发者在网络、认证和配置上的常见挑战,提供了涵盖多种安装方式、详细配置步骤及核心使用技巧的实战指南,并特别介绍了如何利

weixin_28715081的博客 415

MuJoCo柔性体仿真实战:从FlexComp建模到自定义模型导入

柔性体仿真是机器人交互研究中不可或缺的一环,MuJoCo作为高精度物理求解器,凭借高效的求解速度与批量并行能力,成为强化学习与软体抓取任务的热门选择。其FlexComp机制将连续材料离散为粒子-约束系统,以较低建模成本模拟布料、软组织等形变行为,相比Gazebo等平台更具实时性与可扩展性。技术价值体现在自定义柔性体建模与导入流程中:通过XML配置网格密度、间距与材料参数,即可生成贴合任务需求的软体垫子或硅胶抓手。在柔性抓取、颗粒抓手、医疗仿真等场景中,该方法能快速构建可训练的环境。围绕环境搭建、FlexCo

weixin_29045585的博客 159

Kotlin 泛型 VS Java 泛型

和 Java 泛型一样,Kotlin 泛型也是 Kotlin 语言中较难理解的一个部分。Kotlin 泛型的本质也是参数化类型,并且提供了编译时强类型检查,实际上也是伪泛型,和 Java ...

qxf865618770的博客 3630

logisim计组实验八 乘法器

原理:点这里 有问题欢迎留言哦~ 文章目录五位阵列乘法器电路图时间延迟分析六位补码阵列乘法器五位无符号乘法流水线原理图电路图原码一位乘法器原理图电路图补码一位乘法器 五位阵列乘法器 电路图 此处注意:全加器FA的cout端是进位端而非输出端 使用硬件控制比循环累加的速度快得多。 但是存在串行进位链 改进版: 时间延迟分析 T是计算相加数的一级门延迟 3n–>2n 性能差别在1.5倍 ...

treblez's blog 2万+

【Kotlin】笔记22-泛型的高级特性

Kotlin笔记22-泛型的高级特性,reified 14.1 泛型的高级特性,reified 对泛型进行实化 reified Kotlin中是可以将内联函数中的泛型进行实化的 声明函数必须是内联函数(inline) 在声明泛型的地方必须加上reified关键字来表示该泛型要进行实化 示例代码如下: inline fun <reified T> getGenericType() = T::class.java 这里实现了个Java中完全不可能实现的功能: geGeneric

weixin_42473228的博客 1599

QMI8658A与QMC5883L(9轴)评估板实战指南:从硬件连接到数据校准

本文提供了QMI8658A与QMC5883L九轴传感器评估板的完整实战指南。详细介绍了从硬件I2C/USART连接到传感器零偏与地磁校准的关键步骤,并利用上位机实现数据可视化,帮助开发者快速上手9轴姿态传感技术,应用于无人机、机器人等领域。

metaverse5vr的博客 478

【Python深度学习】做深度学习训练时,如果数据集太大,无法一次性加载进GPU,应该如何做?

方法核心思想优点缺点适用场景实现复杂度小批量训练(Mini-Batch Training)与数据加载器(DataLoader)将数据集划分为小批量,每次只加载一个小批量到GPU中进行训练。- 易于实现- 是深度学习的标准做法- 支持多进程加载- 内存可能成为瓶颈- 需要调整批量大小避免内存不足适用于大部分场景低数据分片与分布式训练(Data Sharding & Distributed Training)将数据集分片,每个GPU或节点处理其中一部分数据,分布式训练。

若北辰 1143

@Autowired注解和@Resource注解在注入泛型对象时的不同

@Autowired注解和@Resource注解在注入泛型对象时的不同,@Resource注解在注入泛型对象注入失败的问题的探讨

fgba的博客 593

108、AWB 时间滤波器:帧间白平衡平滑,防止色彩跳变与过冲

摘要: 文章探讨了AWB(自动白平衡)时间滤波器的设计与优化,以解决帧间白平衡跳变和过冲问题。通过自适应状态机(STABLE/TRANSITION/JUMP)动态调整平滑系数alpha,结合帧率归一化和过冲保护(方向检测+限幅),实现场景切换快速响应与静态稳定性的平衡。作者分享了工程经验:避免固定阈值、联动AE/AF、真实场景验证,并推荐简化卡尔曼滤波替代IIR。最终方案在旗舰机前置摄像头中成功消除“闪白”现象,强调参数需动态适应光照与色温变化。

sundong_81的博客 63

干货拿走:深入解析Kotlin 泛型

0. 引子 Kotlin 100% 与 Java 兼容,所以抛开语言表面上面的种种特质之外,背后的语言逻辑或者说“灵魂”与 Java 总是想通的。本文只涉及 Kotlin Jvm,Kotlin Js、Kotlin Native 的具体实现可能有差异。 最近一段时间在网上发了一套 Kotlin 的入门视频,涵盖了基础语法、面向对象、高阶函数、DSL、协程等比较有特色的知识点,不过有朋友提出了疑问:这门课为什么不专门讲讲泛型、反射和注解呢? 我最早听到这个问题的时候,反应比较懵逼,因为我居然没有感觉到 K

粉丝交流群:569545109 670

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

[kotlin] Kotlin泛型深度解析:从Java的通配符到Kotlin的优雅型变

Kotlin的泛型系统不是对Java泛型的简单包装,而是一次深刻的重新设计。通过out/in关键字,它让型变变得直观易懂;通过reified,它突破了类型擦除的限制;通过更简洁的语法,它减少了泛型编程的心智负担。从通配符到关键字:用out/in替代?extends/?super从擦除到实化:用reified获取运行时类型信息从复杂到简洁:用更少的代码表达相同的类型约束更重要的是,Kotlin的泛型设计鼓励更安全的编程模式。

2301_77946674的博客 1282

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

再次深入解析Kotlin泛型

在总结了基础用法和重温Java泛型之后,再次深入的研究Kotlin的泛型,看Kotlin是如何解决Java泛型遗留的问题,以及如何更优雅的用in和out来进行协变和逆变。

稀有猿诉 807

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Kotlin泛型形变深度解析

"在开发SDK时,我们使用协变设计返回类型,使接口能返回更具体的实现类;同时用逆变设计处理器接口,使客户端能处理更抽象的参数类型。"Kotlin选择将形变规则显式化,这种设计虽然增加了学习成本,但带来了更可靠的类型系统和更清晰的代码表达。,主要解决泛型类型在作为参数或返回值时的类型兼容性问题。"形变本质是类型参数的继承关系映射到泛型类的继承关系,协变保持方向一致,逆变则反转这个关系。通过更显式的声明,在编译期就保证了类型安全,避免了运行时异常。反转类型参数的继承方向(父类→子类)

斗锋在干嘛的博客 451

Kotlin (四) JSON解析(kotson 解析 data, json泛型)

一、概述 kotlin 解析 json,直接调用 java的json库是没问题的,比如 Gson, fastjson。 但是比如 fatsjson 在解析 data 类时会报错:没有默认构造函数 //使用 compile 'com.alibaba:fastjson:1.1.68.android' 测试结果 com.alibaba.fastjson.JSONException: default...

2万+

Kotlin Moshi 泛型擦除问题实战:如何高效处理 JSON 解析

FromJson// 自定义解析逻辑@ToJson// 自定义序列化逻辑// 注册Adapter.build()基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。架构理解:掌握实时语音应用的完整技术链路(ASR→LLM→TTS)技能提升:学会申请、配置与调用火山引擎AI服务。

2600_94959956的博客 303

Kotlin泛型类型擦除与桥接方法深入解析(72)

泛型是一种编程范式,它允许在定义类、接口和函数时使用类型参数,这些类型参数在使用时会被具体的类型所替代。泛型的主要作用包括:

Android开发领域创作者 1139

Kotlin泛型高级用法全解析,掌握这些才能算真正入门

掌握Kotlin泛型高级用法,解决类型安全与代码复用难题。详解协变、逆变、星投影等核心机制,涵盖集合处理、DSL构建等实际应用场景,在kotlin程序员节提升编程效率。深入理解泛型边界与内联优化,值得收藏。

FuncLens的博客 776

kotlin中Gson解析Json时对于泛型的应用

而在开发过程中,我们也可能遇到这样的Json数据//一个登陆接口返回的数据{"data"{"admin"""}//一个登陆失败的Json{"data""账号密码不匹配!"}和这样的Json数据//一个获取首页banner的Json{"data"[{"desc""我们支持订阅啦~","id""https"我们支持订阅啦~","type""https"desc""https"我们新增了一个常用导航Tab~","type""https"desc"...

张子羽的安卓bug开发日记 2073

android 在 Kotlin 语言下使用GSON 解析数组泛型被擦除的问题

今天在使用kotlin编写项目中的地址选择器的功能中,在json数据解析上卡了好久: 一开始的代码写成了这样: val fromJsons = Gson().fromJson<List<AeraBean>>( FileUtils.getJsonReader(view.context, "aera.json"), Mu...

weixin_33693070的博客 697

Moshi进阶实战:Kotlin多场景JSON解析与泛型处理技巧

本文深入探讨了Moshi在Kotlin开发中的进阶实战技巧。针对JSON解析中的复杂泛型处理,如BaseResp<T>嵌套List的场景,提供了详细的解决方案。同时,文章还介绍了如何利用Moshi处理多态类型、与Retrofit深度集成打造类型安全网络层,以及通过自定义JsonAdapter和性能优化策略来应对各种特殊需求,帮助开发者高效、安全地处理JSON数据。

fun88的博客 963
上一篇: “吹Kotlin协程的,可能吹错了!” 带你真正理解一波
下一篇: 2020 在项目中使用 MVVM正确姿势,你用对了吗?
Python_林一
博客等级 码龄7年 882粉丝 510原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值