什么是延迟加载?前面的测试结论已经给出了答案。使用 Hibernate 获取数据时,有时,Hibernate 并不急着去数据库,而是等到开发者真正需要数据时才会跑一趟数据库。load() 方法 和 get() 方法的基础区别:load() 支持延迟加载(Lazy);意思是,别急,你需要时我再去拿数据。如果没有拿到数据,则会抛出异常。get() 方法不支持延迟加载,而是(Fetch),如果没有拿到数据,则返回 null 。什么时候使用 get(),什么时候使用 load()。只有需求才能告诉你如何权衡,没有绝对的忠告。
顾名思义,注意力机制,“Attention”,就是模仿人的注意力来进行网络模型的设计与实现。我们每个人在日常生活之中,无时无刻不在使用着注意力,比如:我们在看电视的时候会忽略掉电视周围的环境;我们在学习的时候会对书本的注意力集中度较高;我们在听音乐的时候对音乐本身的注意力较高,反而对周围的噪音注意力较小。在神经网络之中采用注意力可以机制可以通过模仿人类的注意力行为,来对数据之中的重要的细节赋予更高的权重,反而对于一些不重要的细节来赋予较低的权重。举个例子,如下图所示,有一只手拿着一朵花在以堆草丛之前,那么我们人在观察这种图片的时候,一般会将更多的注意力集中在这朵花和这只手上,而不是将注意力放在背景的草丛中。因此我们要让我们的网络模型学会如何使用注意力机制,从而其实将注意力更多地放在花和手上。
首先,Boosting 是机器学习中的集成学习的一种。那么什么是集成学习呢?简单来说,集成学习就是使用多个模型来一同学习,最后在每个模型都得到预测结果后再经过进一步的集成处理得到最终预测结果的一种学习方法。值得注意的是,不同的集成学习方法有着不同的集成方法,常见的包括 Bagging、Boosting 等集成方法。下面我们可以简单的了解一下这两种集成方法(我们的重点在集成,因此省略掉了相应的采样工作)。Bagging 集成方法:这种集成方法的思想比较简单,在每个模型都得到一个结果之后,我们会采用一种更加民主的方式进行:对于回归问题,我们使用的是取均值操作;对于分类问题,我们采用的是投票方法,也就是选取出现次数最多的那个。在 Bagging 之中,每个模型的重要性是相同的。Boosting 集成方法:这种集成方法就是我们这节课要采用的,相对复杂一些:我们首先采用加法线性组合对各个模型进行处理;然后我们得到每个模型的错误率;最后对于错误率小的模型,我们会减少它的权重(话语权),反而提升一些错误率高的模型的权重(话语权)。在 Boosting 之中,每个模型的重要性是不同的。既然了解了什么是 Boosting 方法,那么我们便要简单学习一下提升树的基础模型:决策树。
关于“什么是 Gradle Wrapper?”这个问题在官网是这么定义的:The recommended way to execute any Gradle build is with the help of the Gradle Wrapper (in short just “Wrapper”). The Wrapper is a script that invokes a declared version of Gradle, downloading it beforehand if necessary. As a result, developers can get up and running with a Gradle project quickly without having to follow manual installation processes saving your company time and money.—官方我们翻译过来大致意思就是:官方建议任何 Gradle 构建方法在 Gradle Wrapper 帮助下运行。Gradle Wrapper 它是一个脚本,调用了已经声明的 Gradle 版本,并且我们编译时需要事先下载它。所以,开发者能够快速的启动并且运行 Gradle 项目,不用再手动安装,从而节省了时间成本。我们可以称 Gradle Wrapper 为 Gradle 包装器,是将 Gradle 再次包装。让所有的 Gradle 构建方法在 Gradle 包装器的帮助下运行。
在说 Sass 之前不得不说到 CSS,相信你在看这篇文章之时一定是了解 CSS 的,以前的前端开发中我们一般是通过 CSS 来编写样式,而在现代化的前端开发中我们大多数企业中都在使用 Sass 来编写样式。那什么是 Sass 呢?我们引用 Sass 官网的一段话:Sass is the most mature, stable, and powerful professional grade CSS extension language in the world. — 官网这段话中最关键的一处 CSS extension language , 翻译过来就是 CSS 扩展语言,这段话的总体意思就是说 Sass 是一个稳定的、强大的、专业级的 CSS 扩展语言。所以说,它是基于 CSS 扩展出来的,也有另一个叫法,Sass 是一个 CSS 预处理器,所以说 Sass 是需要编译后转换为 CSS 的,它一定是在你的项目编译时去做处理,而不是在运行时,了解这一点很重要!
Java 注解(Annotation)又称为 Java 标注,是 Java5开始支持加入源代码的特殊语法元数据。Java 语言中的类、方法、变量、参数和包等都可以被标注。Java 标注可以通过反射获取标注的内容。在编译器生成class文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容。注解是一种用于做标注的“元数据”,什么意思呢?你可以将注解理解为一个标签,这个标签可以标记类、方法、变量、参数和包。回想我们学习继承时,子类若重写了父类的方法,可以在子类重写的方法上使用@Override注解:将@Override 注解标注在子类重写的方法上,可检查该方法是否正确地重写了父类的方法,如有错误将会编译报错。
我们要系统性地学习 Shell 脚本,首先需要知道什么是 Shell,Shell 翻译过来为壳,例如大家常见的壳牌石油的图标上面的贝壳,顾名思义其就是一个套在操作系统外层的壳,用户可以通过与这层壳的交互,将自己的需求利用这层 Shell 来执行来实现对服务器的操作。我们可以认为 Shell 是将用户的命令解析为内核可以执行的命令,起到命令解释的作用,是用户与操作系统直接的一个桥梁纽带。
我们已经了解过如何简单地去声明一个类型 typealias 以及为什么需要 typealias,那么接下来会一起研究 typealias 原理是什么。当处理类型别名的时候,我们有两个类型需要去思考:别名 (alias) 底层类型 (underlying type)可以把上述例子理解为本身是一个别名 (如 UserId), 或者包含别名 (如 List) 的缩写类型,当 Kotlin 编译器编译代码时,所有使用到的相应缩写类型将会扩展成原来的全类型。一起看个完整的例子class UniqueIdentifier(val value: Int)typealias UserId = UniqueIdentifierval firstUserId: UserId = UserId(0)当编译器处理上述代码时,所有对 UserId 的引用都会扩展成 UniqueIdentifier,换句话说,在编译期间,编译器大部分是做了类似于在代码中搜索别名 (UserId) 所有用到的地方,然后将代码中用到的地方逐字地将其别名替换成全称类型名 (UniqueIdentifier) 的工作。可能已经注意到我说的是大部分场景。 这是因为除了逐字替换原理,有一些特殊情况下 Kotlin 不完全是通过逐字替换原理来实现。但是大部分场景下,我们只需记住 typealias 是基于逐字替换原理即可。顺便说一下,IntelliJ IDEA 和 AndroidStudio 已经很智能了,它门会对类型别名有一些很好的支持。例如,可以在代码中看到别名和底层类型:并且能够给出很好文档和代码提示总结下,实际上 typealias 别名并不会去真的创建一个新的类型,而仅仅是取了一个别名,然后在编译器编译期间,把别名又类似逐字替换原理换回实际的类型,这样就能保证编译正常也不会产生新的类型。
有人问在大部分的工作场景下我们都用不到算法,那么我们为什么还要学习算法呢?首先,需要明确以下几个问题:工作中用不到并不代表工作中没有用到;工作中不常用并不代表面试不常考;学 Java 的同学几乎天天都在用 HashMap 吧?但是大家有思考过存储在 HashMap 中 key 和 value 值是究竟用什么数据结构存储的?当使用 get() 方法查找 value 时用的什么算法?但是我们一般是不会考虑这种问题的,因为这些工作都由编程语言给我们已经封装好了,我们只需要调用,调用,再调用!那么对于 Python 也是一样的,我们用的 dict 等类型,它背后都是 Python 解释器给我们做了大量工作,实现了各种各样复杂的算法,给我们的使用带来了极大的方便,也导致我们大部分程序员似乎在工作中几乎看不到算法的应用?但是,不要忘了,我们是要追求进步的,如果你只是满足于调用各种 API 和方法来完成工作的话这个教程对你的意义不大。不过总会有现有的方法满足不了的业务场景,到那时候你该怎么办呢?此外,算法同样是大厂最喜欢拿来考察候选人员能力的一个方式。社招中最喜欢考察算法编程能力公司的当属今日头条,许多国外的互联网公司如微软、Facebook 等甚至会让你直接手写代码。除此以外,掌握一定的算法基础有以下几个好处:锻炼自己的思维和编程能力:保持解决问题的能力,这在工作中也是非常重要的一项技能;在面试中存在一定竞争力:优秀的编程者往往都是被大厂争夺的对象;在学习一些编程语言源码或者操作系统源码时会有深刻体会;
Java 的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为 Java 语言的反射机制。反射被视为动态语言的关键。通常情况下,我们想调用一个类内部的属性或方法,需要先实例化这个类,然后通过对象去调用类内部的属性和方法;通过 Java 的反射机制,我们就可以在程序的运行状态中,动态获取类的信息,注入类内部的属性和方法,完成对象的实例化等操作。概念可能比较抽象,我们来看一下结合示意图看一下:图中解释了两个问题:程序运行状态中指的是什么时刻:Hello.java 源代码文件经过编译得到 Hello.class 字节码文件,想要运行这个程序,就要通过 JVM 的 ClassLoader (类加载器)加载 Hello.class,然后 JVM 来运行 Hello.class,程序的运行期间指的就是此刻;什么是反射,它有哪些功能:在程序运行期间,可以动态获得 Hello 类中的属性和方法、动态完成 Hello 类的对象实例化等操作,这个功能就称为反射。说到这里,大家可能觉得,在编写代码时直接通过 new 的方式就可以实例化一个对象,访问其属性和方法,为什么偏偏要绕个弯子,通过反射机制来进行这些操作呢?下面我们就来看一下反射的使用场景。
Ruby 的语法非常的简洁,所有的语法已经达到最简洁,没有多余的语法糖,没有像 Java 那么多的条条框框,可以把更多的精力关注于要干的事情上。优秀的语法让您的工作更加轻松,更喜爱您的开发工作。举一个例子,在 Java 中,我们输出一个 Hello World 需要这样写:public class Hello { public static void main(String[] args) { System.out.println("Hello, world!"); }}对于从没接触过编程的人,看到上面的代码肯定会非常困惑,这些代码这什么要这么写? 怎么这么复杂?更有意思的是,越是资深的程序员越会赞成这种想法。而 Ruby 输出 Hello World 只需要这么一行:p 'Hello World'最常见的,它可以与 Rails(一种流行的 Ruby 框架,简称:ROR)结合使用,用于开发 Web 应用程序。Rails 能做到15分钟搭建一个网站。 这个是其他语言无法做到的。它是一门用于文本处理和中间件程序的优秀脚本语言,许多开发人员将 Ruby 用作 Perl 的替代品。Ruby 的资源丰富。它拥有大量的文档、书籍、视频、在线课程、开发论坛(Ruby China 等)等等,并且拥有超过 60000 个库和多种框架可供选择。RubyGems 就是为 Ruby 用来管理该语言构建的众多框架和库创建的。
雪碧图乍一听可能不知所然,因为雪碧是一种汽水,和图片又有什么关系呢?那我们就来讲一讲它到底是个什么?它其实就是把很多小图片集合在一起放到了一张大图片里面,就像下面这样:可以看到通常都是一些图标类的图片,这是因为图标一般比较符合“小”图片的定义:然后用到哪个图的时候就用背景图定位来定位到具体的位置:当然了,黑框只是个示意,实际上既不会让用户看见黑框,也不会让用户看到其他的图片,就像这样:
什么是 KeepAlived 组件呢?我们先来看一下 KeepAlived 这一名词本身的组成所表示的含义。KeepAlived 由 Keep 和 Alived 两个单词组成,Keep 翻译过来具有保持的含义,而 Alived 翻译过来具有或者的含义,我们把这两个含义组合起来,就是保持活着的意思。那在计算机专业领域中,什么叫做保持活着?要想理解这一概念,我们需要先来理解什么是‘活着’,活着一词,我们可以理解为某一状态的持续,对于我们人类来讲,我们所说的活着,其实就是我们一直在重复执行某些具体的动作,比如吃饭、睡觉、上班等行为,如果哪一天这些行为我们都不能再做了,那就说明我们已经不是‘活着’的状态了。在计算机专业领域中,我们所说的‘活着’,其实指的就是某一具体服务状态的一个持续,即存在于计算机中的一些服务,永远保持着一种状态, 无论外界条件对其造成哪些方面的影响,这一服务状态永远会持续,不会被中断。在 KeepAlived 中,这一状态指的就是计算机服务集群中的,一种可以持续提供服务状态的一种保障状态,当我们在集群中配置了 KeepAlived 时,我们就可以将我们的集群服务状态称之为‘活着’。从专业角度来讲,KeepAlived 组件其实就是一种可以提供计算机服务集群间的服务状态不间断运行的一种辅助软件,或者叫做工具组件。 通过在集群中引入 KeepAlived 组件,再结合一定的配置,可以保证集群持续稳定的对外提供服务,不受外界环境的影响。(特殊因素除外)。
一个应用程序,当功能越来越庞大、逻辑越来越复杂、代码越来越多时,必然会采用分而治之的方案。分,容易,如何分才能分得清晰、便于维护,这是一个与管理有关的学问。MVC 提出了一种分离的策略,这种想法或思想一问世,便让世人茅塞顿开。MVC 的分离思想:把整个应用程序中和用户进行交互的功能代码归纳在一起,这部分代码整体称为 V (View 或叫视图层);把专门用来进行数据传递或数据逻辑处理的功能代码归纳在一起,称其为 M(Model 或叫l模型层)。C 指的是哪一部分功能代码呢?因为V 和 M 是要经常交流、沟通的,V 需要展示 M 处理过的数据,同时,M 也可能需要 V 提供的用户交互时输入的数据。虽然分了,但两者之间存在依赖关系。我们不让 V 和 M 直接交流,而是在两者之间引入了一个叫做 C(控制器)的对象,所以说 C 就是 V 和 M 之间的桥梁!这个 C(控制器)对象感觉在硬生生的拆散别人,不过这种拆分是善意且友好的。为什么这么说?满足 OOP 中的低耦合性原则,解耦 V 和 M 之间的关系;M 需要用户交互时输入的数据时,可以不用管 V 是谁,只要有控制器传数据就可以;同时,V 也不用关心 M 在哪里,只要有数据提供给自己就可以。如果现在要编写一个 WEB 视图和 Swing 视图的双客户端应用程序时,只需要换一个 C 就可以,M 可以重用。
相信搞前端的大多数都听过雪碧图这么一个神奇的名字,有些人知道它是做什么的,但是有些人不知道它为什么叫雪碧图,今天我就带领大家来重新认识一下雪碧图: (鼠标点击可以互动)
接下来,我们针对上述 Swagger Editor 配置源文件中的属性来为大家介绍每个属性都代表什么意思,都用来做什么,以及在使用 Swagger Editor 时的一些使用技巧和注意事项。
说起 AMQP 协议,我们可能会感到有点陌生,那么为什么还要了解 AMQP 协议呢? 因为了解什么是 AMQP 协议可以为我们学习 RabbitMQ 打下知识基础,让我们很清楚的知道 RabbitMQ 是用来做什么的。AMQP 协议,即 Advanced Message Queuing Protocol,直译为高级消息队列协议,我们只要知道 AMQP 协议就是一个高级消息队列协议就行了。
什么是 HaProxy 组件呢?我们可以像理解 KeepAlived 组件那样,去理解 HaProxy 组件。HaProxy 这一名词和 KeepAlived 名词一样,也是一个组合词,我们拆开来看,Ha 其实是 High Availability 简称,取的是两个单词的首字符,即 HA ,中文含义就是我们常说的高可用。而 proxy 就比较简单了,proxy 翻译过来具有代理的含义,代理我们可以理解为我们平常生活中的第三方办事机构,就是我们自己的事情交给第三方去做,等第三方完成我们交代的任务后,会给我们一个通知,HaProxy 中的 proxy 就是这个意思。在清楚了 HaProxy 各组成名词之后,我们就不难理解到底什么是 HaProxy 了。HaProxy 翻译过来其实指的就是一种高可用的代理工具,或者可以叫做一种软件。即 HaProxy 就是一种为集群提供高可用支持与服务的,一种高可用代理工具,其可以管理集群间的通信方式,可以对集群进行健康检查,甚至也可以对集群进行全方位的监控,说白了,HaProxy 就是一种辅助集群实现高可用、对集群进行监控、对集群进行健康检查的一种组件或软件。而实现这种高可用,以及集群监控和集群健康检查的手段,则是通过 HaProxy 中的 Proxy 代理实现的,我们可以配置采用 tcp 还是 http 代理的方式,这点同学们简单了解即可。
有时候我们希望接口允许有任意的属性,语法是用 [] 将属性包裹起来:// 语法interface Clothes { color?: string; size: string; readonly price: number; [propName: string]: any;}// 任意属性 activitylet myClothes: Clothes = { size: 'XL', price: 98, activity: 'coupon'}代码解释: 这里的接口 Clothes 可以有任意数量的属性,并且只要它们不是 color size 和 price,那么就无所谓它们的类型是什么。项目案例:使用 axios 库发起 HTTP 传输的时候,可以写入一个自定义的属性,就是因为源码中定义了一个任意属性:this.$axios({ method: 'put', url: '/cms/user', data: { nickname: this.nickname, }, showBackend: true,})
Spring MVC 是什么?答案很简单,它是一个 WEB MVC 框架。
上一节课《Django 框架简介》我们简单地认识了下 Django 框架,在正式开始学习它之前,我还要跟你说下 Web 框架到底是个什么东西?为什么市面上会有各种各样形形色色的 Web 开发框架?以及使用 Web 框架进行开发的优势在哪里?这些问题在这节课里面你都可以找到答案。
学习 Netty 的好处是什么呢?掌握 Netty 及其原理,可以为自己找工作、面试时加分。并且让自己的技能得到进阶,是初中级迈向高级的门槛;有助于学习和理解主流中间件的架构思想,很多的中间件都是基于 Netty 去开发的,比如:Dubbo;Netty 用来系统网络通信功能,是系统的基石,往往决定一个系统的性能,能否扛得住并发;对于学习和理解分布式架构会有很大的帮助,分布式架构下最核心环节就是应用之间的通讯。
说这么多,那么什么是 Ajax 呢?简单来讲,Ajax 就是 JavaScript 基于 XMLHttpRequest 对象与服务端进行交互,向服务端发送一个请求,并且获取和处理服务器返回的内容。在这个过程中,我们可以使用 XML ,HTML 和 JSON 等格式的数据进行交互。并且,Ajax 拥有异步特质,我们可以在不刷新页面的情况下,通过交互数据,在页面上做局部的刷新等数据处理。
Shell 变量是什么呢,顾名思义,就是可以变化的量,如果有编程基础的读者知道任何程序中都有变量,从我们小时候做数学题,定义的 x 变量,最终给定值,用值替换 x 变量,这就是我们最初接触的变量,它和我们在 Shell 中接触的变量本质上是一致的。变量在 Shell 中是存储计算器内存的单元,其中存放的值可以改变,当我们在编写 Shell 脚本中,如果一些经常用的字符串或数字我们就可以定义一个变量,将具体的值赋给这个变量,然后在具体的函数或脚本中引用这个变量,就相当于拿到了这个值。
并发编程本身的学习曲线比较陡峭,尤其是对初学者而言,理解并发编程需要一个过程,在没有完全参透并发编程的原理之前,可以先把目光集中在基本的并发工具应用上面来,先做到会熟练使用,再逐步深入理解其底层的核心原理。所以对于初学者而言,重点在于理解常见并发工具的种类、应用场景、以及使用方法。对于每一个常见的并发工具,需反复琢磨,要举一反三,多加练习,万不可心急而浮于表面。在熟练掌握了这些基本知识之后,就可以深入到各类工具的底层实现,进一步了解其背后的原理和编程思想。进而可以做到灵活构建适合各类特殊需求的并发控制工具。
那么我们为什么要使用 Swagger 呢?
要搞清楚页面栈概念,我们首先要了解“栈”是什么意思,在学习数据结构的时候,我们应该都了解过,栈是一种连续储存的数据结构,具有先进后出的性质。在古代,存储货物或供旅客住宿的地方叫做栈。引申到计算机领域中,就是暂时存储数据的地方,这样进栈、出栈的说法也比较容易理解了,进栈就是将数据添加到栈顶部,出栈就是将数据从栈顶部删除。但这样说还是有点抽象,我们可以将栈想象成一个开口的盒子,将书一本一本的放进盒子中,先放进去的书总是会被后放进去的书压在下面,这就是进栈的过程。那如果想拿出底部的书,需要先将顶部的书(也就是后放进的书)一本一本的拿出来,这是出栈的过程。这样解释栈的先进后出的性质就比容易理解了。页面栈就是用来储存页面的栈,也有栈的特性。uni-app 是通过页面栈来管理所有的页面,我们可以将页面栈理解为一个放页面的容器。每次跳转页面,都会从这个容器中添加或者删除页面。为了便于大家理解,我们来看一下示意图:
那么我们为什么要使用 Gradle 呢?
什么是 Swagger Validator 呢?在 Swagger 官网中是这么介绍的:Swagger Validator 是一个 Swagger 验证器,用于验证你的 Swagger 文档。 —官网我们来看一下 Swagger Validator 官方提供的一款在线体验平台(https://validator.swagger.io/):从图中我们可以看到,Swagger Validator 的显示界面非常类似于 Swagger-UI 的显示界面,风格和排版都很相似,那么我们应该怎么来用呢 ?
什么是 Gradle 呢?在 Gradle 官网中是这么介绍的:Gradle is an open-source build automation tool focused on flexibility and performance. Gradle build scripts are written using a Groovy or Kotlin DSL. —官网翻译成中文就是,Gradle 是专注于灵活性和性能的开源构建自动化工具。Gradle 构建脚本是使用 Groovy 或 Kotlin DSL 编写的。我们看到了这里有个 DSL,下面我们看下什么是 DSL:DSL 的全称是 Domain Specific Language,即领域特定语言,或者我们可以翻译成“特定领域的语言”。它的特性就是 “ A specialized computer language designed for a specific task.”翻译为:为解决某一类任务而专门设计的语言。 再通俗点来说,其实就是这个语言不通用,只能用于特定的某个领域,俗称“小语言”。因此 DSL 也是语言。通过上面的介绍,说白了,Gradle 就是一个自动化的项目构建工具,用来帮助我们自动构建项目。