2--Gradle入门 - Groovy简介、基本语法

news2024/11/23 19:07:54

2--Gradle入门 - Groovy简介、基本语法

Gradle 需要 Groovy 语言的支持,所以本章节主要来介绍 Groovy 的基本语法。

1.Groovy 简介

在某种程度上,Groovy 可以被视为Java 的一种脚本化改良版,Groovy 也是运行在 JVM 上,它可以很好地与 Java 代码及其相关库进行交互操作。它是一种成熟的面向对象编程语言,既可以面向对象编程,又可以用作纯粹的脚本语言。大多数有效的 Java 代码也可以转换为有效的 Groovy 代码,Groovy 和 Java 语言的主要区别是:完成同样的任务所需的Groovy 代码比 Java 代码更少。其特点为:

  • 功能强大,例如提供了动态类型转换、闭包和元编程(metaprogramming)支持

  • 支持函数式编程,不需要main 函数

  • 默认导入常用的包

  • 类不支持 default 作用域,且默认作用域为public。

  • Groovy 中基本类型也是对象,可以直接调用对象的方法。

  • 支持DSL(Domain Specific Languages 领域特定语言)和其它简洁的语法,让代码变得易于阅读和维护。

  • Groovy 是基于Java 语言的,所以完全兼容Java 语法,所以对于java 程序员学习成本较低。详细了解请参考:http://www.groovy-lang.org/documentation.html

2d2b8eb0d84c11c2a2f0074ed96ec857.png
1685493613971

2. Groovy 安装 SDK

下载Groovy SDK

官网下载地址:https://groovy.apache.org/download.html

dcd07f7115b9372f5fc2d7a21711c724.png

下载后为一个 zip 包,如下:

63c016f994bc0edae8410fd999b52325.png

解压缩 SDK

a4622f57f7c7aa7f69b7b7ac32eacb0a.png

将 SDK 解压之后,下面就可以配置环境变量了。

配置环境变量

变量名:GROOVY_HOME
变量值:解压后的目录
添加path路径中:%GROOVY_HOME%\bin

dcacfbb5f9fa73f89ae6b763e28f8643.png

88dfa7ba6f8eac7192a9759f195492f7.png

测试查询 Groovy 版本

C:\Users\Administrator>groovy -v
Groovy Version: 4.0.3 JVM: 1.8.0_91 Vendor: Oracle Corporation OS: Windows 10

执行如下:

3a1b2e8ffc53453feb3999ea85e374fd.png

查询版本之后,可以配置完成了。

3. Idea 创建 Groovy 项目

Idea创建项目的时候选择Groovy

File - New - Project / Module(本文以建立Project为例) - 选择Groovy - 点击Creater(选择下载的Groovy SDK包) - 下一步命名Project - 点击OK。

此时即建立了Groovy项目。

bdfb3600d262b6f472b65f43a011dfb3.png

484cfa684e2d4cc58cd7570fa63c6a39.png

b06c4379ecb12e29c3b92a06f8b49583.png

f97f53940e748542495391d2717dade1.png

配置项目工程的 out 输出目录

在 Project 工程配置 out 输出目录。

5c2fc835d3f5740ab673bd64fe0dca82.png

在模块的路径设置继承 Project 的 out 路径

d104377d6ee88fa84534b06ed4397370.png

编写 Demo 输出 HelloWorld

创建 Groovy 类

21f3ef74a1b6d3e99e24eb84ee45d983.png

编写 Demo

package test

/**
 * @author Aron.li* @date 2022/7/6 8:57
 */
class demo {
    static void main(String[] args) {
        println("Hello,World!Groovy!");
    }
}

执行代码如下:

747a000f21289a39e270ef565a5fe723.png

查看生成的 demo 执行类

90a56d0b3baf3d80f42c1bcd32618216.png

可以看到实现了 GroovyObject

编写 Demo 脚本

groovy 也可以使用脚本的方式来实现,不用写成类:

9e5824f3257a8f6d9226f690eb0aa6a0.png

1685578418631
package test

def str1 = 'hello world'

printf("message: ${str1}")

查看生成的输出类:

bdb64be97518ed4b9bfdd649361bf754.png

1685578548648

可以看到,如果是脚本的写法,那么生成类则是继承 Script 类。

4. Groovy 基本语法

创建一个以 .groovy 为后缀的文件,我们可以在这文件中像开发java代码一样简单的去使用 groovy,并且 groovy 提供的语法更加简洁。

我们可以完全像开发 Java 代码一样去编写 Groovy,也可以根据 Groovy 的语法来简化编写。

第一个 Hello world 程序

class Example {
   static void main(String[] args) {
      // 使用 println 就可打印输出,并且类和方法默认就是public,可以不用写
      println('Hello World');
   }
}

运行

9be5645aaf4c200b833861a3507458c0.png

Hello World

Groovy 的导入语句

和 Java 一样,都是使用 Import 进行导入

import groovy.xml.MarkupBuilder  // Import 进行导入需要的类
def xml = new MarkupBuilder()   // def 就是动态类型,在Groovy可以不用指定具体的类型,就像js中的var一样

在编译的 Groovy 字节码文件中,Groovy 已经默认帮我们导入了一些jar包,这些 jar 包可以不用再显示的导入

import java.lang.* 
import java.util.* 
import java.io.* 
import java.net.* 

import groovy.lang.* 
import groovy.util.* 

import java.math.BigInteger 
import java.math.BigDecimal

Groovy 的注释

和 Java 一样,支持单行 // 和多行注释 /**/

// Using a simple println statement to print output to the console

/* This program is the first program
      This program shows how to display hello world */

Groovy 的分号

; 分号,可以用来区分不同的代码块。

在 Groovy 编写中可以,可以省略分号符

Groovy 的标识符

和 Java 一样,标识符就是变量名,声明规则和 Java 一样,可以以字母开头,美元或下划线。但不能以数字开头。

Groovy 的关键字

大部分关键字和 Java 中的用法一样

asassertbreakcase
catchclassconstcontinue
defdefaultdoelse
enumextendsFALSEFinally
forgotoifimplements
importininstanceofinterface
newpullpackagereturn
superswitchthisthrow
throwstraitTRUEtry
while

数据类型

Groovy 的内置数据类型和 Java 一样有8种。byte、short、int、long、float、double、char、boolean

字符串:String

并且都有其对应的封装类

变量

变量也和 Java 一样,除了使用基本数据类型和引用类型,还可以使用def动态数据类型来声明变量。

// 和java的区别就是多了,def动态类型
def a = 1; // 在编译时会自动转化为int
def a = 'aa';

运算符

大部分运算符和 Java 一样,如:算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符

范围运算符

与 Java 不同点在于,新增了 范围运算符

def range = 0..5

范围运算符通过..来指定其开始和结束的范围。

上面示例就简单的定义了一个,从0到5的范围。

/**
 * @author Aron.li* @date 2022/7/11 7:59
 */
class RangeDemo {

    public static void main(String[] args) {
        // 定义 5~10 的范围
        def range = 5..10
        // 打印范围
        println(range)
        // 取范围中的数据
        println(range.get(2))
        // 遍历范围数据
        range.forEach( e -> {
            print(e + ', ')
        })
    }

}

运行

e863de80f23ad3a97b2a895881ddf14d.png

可以发现,范围变量,本质就是封装了一层数组。在操作时,通过其下标进行存取。

运算符优先级

运算符名称
++ ,-- ,+ ,-预增/减(自增/减),一元加,一元减
*, /, %乘法,除法,取模
+,-加法,减法(二元)
==,!=, <=>等于,不等于,比较运算符
二进制/位运算符与
^二进制/位异或
``
逻辑非
&&逻辑与
`
=,+=,-=,*=,/=,%=,**=各种赋值运算符

循环

Groovy 中的循环和 Java 中一样,包含循环跳出和结束循环等

while、for、break、continue

while 语句

package test.basicUsage

/**
 * 循环Demo
 *  while、for、break、continue
 *
 * @author Aron.li* @date 2022/7/11 8:17
 */
class CycleDemo {

    public static void main(String[] args) {
        // while demo
        println("while demo .................")
        int i = 0
        while (i < 5){
            if ( i == 4) break
            if ( i == 2) continue

            println("i = " + i)
            i ++
        }
    }
}

运行如下:

86b3befe7a4fb9391e27b568e66141e8.png

image-20220711082239363

for in 语句

在 Java 中我们常常使用foreach来遍历

for(String str : strList){
    ...
}

而在 Groovy 中提供了for in语句,其使用方法和 Java 一样,只是关键字不同

for(def str in strList){
    println(str);
}

示例代码如下:

// for in
println("for in .................")
def strList = ['hello', 'world']
for (def str in strList){
    println(str)
}

运行结果如下:

for in .................
hello
world

for 语句

// for
println("for .................")
for (int j = 0; j < 5; j++) {
    println("j = " + j)
}

运行结果如下:

for .................
j = 0
j = 1
j = 2
j = 3
j = 4

continue

// continue
println("continue .................")
for (int j = 0; j < 5; j++) {
    if (j == 3) continue
    println("j = " + j)
}

运行结果如下:

continue .................
j = 0
j = 1
j = 2
j = 4

break

// break
println("break .................")
for (int j = 0; j < 5; j++) {
    if (j == 3) break
    println("j = " + j)
}

运行结果如下:

break .................
j = 0
j = 1
j = 2

条件语句

Groovy 中的条件语句和 Java 中的一样,其关键字如下

if、else、switch

包括其嵌套使用等

if 语句

package test.basicUsage

/**
 * 条件语句
 */
class ConditionDemo {

    public static void main(String[] args) {
        // if 条件语句
        println("if 条件语句............")

        int a = 20

        if (a < 10){
            println("a < 10, a = " + a)
        } else if (a > 20){
            println("a > 20, a = " + a)
        } else {
            println("else, a = " + a)
        }
    }
}

运行结果如下:

if 条件语句............
else, a = 20

Switch语句

// Switch语句
println("Switch语句 ............")

int b = 2

switch (b){
    case 1:
    println("The value of a is One")
    break
    case 2:
    println("The value of a is Two")
    break
    case 3:
    println("The value of a is Three")
    break
    case 4:
    println("The value of a is Four")
    break
    default:
        println("The value is unknown")
    break
}

运行结果如下:

Switch语句 ............
The value of a is Two

嵌套Switch语句

// 嵌套 Switch 语句
int i = 0
int j = 1

switch(i) {
    case 0:
        switch(j) {
            case 0:
                println("i is 0, j is 0")
                break
            case 1:
                println("i is 0, j is 1")
                break

            default:
                println("nested default case!!")
        }
        break

    default:
        println("No matching case found!!")
}

运行结果如下:

i is 0, j is 1

案例

1.案例1:基本语法

groovy 中使用 def 定义变量、方法,不建议使用具体的类型:

9fd877c69c44110009e9f8e2fcbfbcc2.png

package test.basicUsage

/**
 * def 定义各种变量
 * - groovy 中使用 def 定义变量、方法,不建议使用具体的类型
 *
 * @author Aron.li* @date 2022/7/16 15:38
 */
class defDemo {

    static def msg (str){
        // 如果没有return,则会以最后一行返回消息
        "msg: ${str}"
    }

    static def add(num1, num2){
        return num1 + num2
    }

    static void main(String[] args) {
        // 输出msg方法的返回值
        println(msg("hello world"))

        // Example of an Integer using def
        def a = 100
        println(a)

        // Example of an float using def
        def b = 100.10
        println(b)

        // Example of an Double using def
        def c = 100.101
        println(c)

        // Example of an String using def
        def d = "HelloWorld"
        println(d)

        // Example of an Func return using def
        def sum = add(100, 10)
        println(sum)
    }
}

注意事项案例

为了更加方便理解,下面我定义一个类,然后再写一个 script 脚本来调用该类的属性、方法:

  • Demo1BasicNotice

package test.demo

class Demo1BasicNotice {
/**--------------------------------------------------
 * 1.groovy中使用def 定义属性、方法,def支持动态类型声明
 * 2.单行注释:// 多行注释: /**
 * 3.gradle语句最后的;(分号)是可以省略的
 * 4.groovy可以为属性自动生成getter、setter方法
 * 5.方法声明时:参数类型、返回值类型、return关键字可以省略,方法调用时,再不引起歧义的地方,可以省略()
 * 6.变量应用时:在不引起歧义的前提下{}也可以省略,再容器引起歧义的地方就不能省略{}
 * 7.对象属性赋值时:
 *      方式1: 对象.属性名=
 *      方式2: 对象["属性名"]=
 *      方式3: 对象.属性setter方法()
 *      方式4:  具名构造器的方式
 *   读取属性值:
 *      方式1: 对象.属性名
 *      方式2: 对象["属性名"]
 *      方式3: 对象.属性getter方法
 *
 * --------------------------------------------------
 */

    // 定义属性
    def name = "李小龙"
    def age = 10
    def desc = "描述信息"
    def address = "地址信息"

    // 定义方法
    def sendMessage(msg){
        "msg: $msg"
    }

    def sum(num1, num2){
        "sum = ${num1 + num2}"
    }
}
  • Demo1BasicNoticeScript.groovy

package test.demo

// 获取对象
def notice = new Demo1BasicNotice()

// 设置属性、读取属性
notice.age = 30
println("notice.age = $notice.age")

notice["desc"] = "demo 描述信息"
println("desc = ${notice["desc"]}")

notice.setAddress("深圳市南山区")
println("address = ${notice.getAddress()}")

// 使用方法
def message = notice.sendMessage("发送消息...")
println(message)

def sum = notice.sum(10, 15)
println(sum)

执行如下:

7b3e8ab07e1cce278f7e2ceaa017637d.png

1685669998610

2. 案例 2:引号说明

package test.demo

//---------------------------- 字符串 ------------------------------
def desc="测试"

def str1='单引号, 不支持变量引用 ${desc},不支持换行操作 '
println(str1)

def str2 = "双引号,支持变量应用 ${desc}, 不支持换行操作"
println(str2)

def str3 = """
模板字符串: ${desc}, 支持换行操作\n
换行测试.....
"""
println(str3)

// 基本数据类型也可以作为对象使用,可以调用对象的方法
println(str1.getClass().toString())
println(str2.getClass().toString())
println(str3.getClass().toString())

执行如下:

04ae3e1efdcda3e1b43ad819fb5f5e9e.png

1685766297899

3.案例 3:三个语句结构

Groovy 支持顺序结构从上向下依次解析、分支结构(if..else、if..else if ..else..、switch..case、for、while、do..while)

具体参考官网:http://www.groovy-lang.org/semantics.html#_conditional_structures

4. 案例 3:类型及权限修饰符

Groovy 中的类型有:

  1. 原生数据类型及包装类

6a14382a2095d1e7ded2003a1bc12134.jpeg

img
  1. 类、内部类、抽象类、接口

  2. 注解

  3. Trait: 可以看成是带有方法实现的接口

权限修饰符: public、protected、private

拓展:Groovy 类与 Java 类之间的主要区别是:

  1. 没有可见性修饰符的类或方法自动是公共的(可以使用一个特殊的注释来实现包的私有可见性)。

  2. 没有可见性修饰符的字段将自动转换为属性,不需要显式的 getter 和 setter 方法。

  3. 如果属性声明为 final,则不会生成 setter。

  4. 一个源文件可能包含一个或多个类(但是如果一个文件不包含类定义的代码,则将其视为脚本)。脚本只是具有一些特殊约定的类,它们的名称与源文件相同(所以不要在脚本中包含与脚本源文件名相同的类定义)。

提 示 : 有 关 Groovy 中 各 种 各 样 的 数 据 类 型 和 权 限 修 饰 符 及 Goovy 与 Java 区 别 请 参 考 :

http://www.groovy-lang.org/objectorientation.html#_modifiers_on_a_property

5. 案例 5:集合操作

Groovy 支持List、Map 集合操作,并且拓展了 Java 中的API,具体参考如下方法:

List:

  • add():添加某个元素plus():添加某个list 集合

  • remove():删除指定下标的元素removeElement():删除某个指定的元素removeAll(): 移除某个集合中的元素

  • pop():弹出list 集合中最后一个元素putAt():修改指定下标的元素

  • each():遍历

  • size(): 获取list 列表中元素的个数

  • contains(): 判断列表中是否包含指定的值,则返回 true

Map:

  • put():向map 中添加元素

  • remove():根据某个键做移除,或者移除某个键值对

  • +、-:支持 map 集合的加减操作

  • each():遍历map 集合

请参考官网:http://www.groovy-lang.org/syntax.html#_number_type_suffixes

提示:可以把不同的基本类型添加到同一集合中。

List 增删查改:

package test.demo

//---------------------------list增删查改操作--------------------
//----------------------1.增----------------------
//1.1. 增:在集合中添加元素
println("1.1. 增:在集合中添加元素")
def list = [5, 6, 7, 8]
println(list)

assert list instanceof List

list.add(12)
println(list)
println(list.size())
//1.2. 增:集合与集合相加
println("1.2. 增:集合与集合相加")
def list2 = [1, 2, 3, 4]
def list3 = list.plus(list2)
println(list) // 原来的list集合不改变
println(list3) // 集合相加会生成新的集合

//----------------------2.删-------------------------
//2.1. 删:删除下表为2的元素
println("2.1. 删:删除下表为2的元素")
println("删除之前的list: ${list}")
list.remove(2)
println("删除之后的list: ${list}")

//2.2 删:删除集合中指定的元素
println("2.2 删:删除集合中指定的元素")
println("删除之前的list: ${list}")
list.removeElement(12)
println("删除之后的list: ${list}")

//2.3 删:从list集合中移除list3集合中的元素
println("2.3 删:从list集合中移除list3集合中的元素")
def list4 = [6, 8]
list.removeAll(list4)
println(list)

//---------------------------3.改-----------------------
println("3.list的修改")
list.putAt(2, 10) // 等效于 list[2]=10
println(list)

//---------------------------4.查------------------------
//4.1 遍历list
println("4.1 遍历list")
[1, 2, 3].each { println("Item: {$it}") }

//4.2 获取list的大小
println("4.2 获取list的大小: ${list.size()}")

//4.3 判断list是否包含指定的值
println("4.3 判断list是否包含指定的值: ${[1, 2, 3].contains(2)}")

Map增删查改

//---------------------------map增删查改操作--------------------
// Key 可以不适用引号,可以使用单引号 '',也可以使用双引号 ""
def map = [J: "Java", "K": "Kotlin", 'G': "Groovy"]

//----------------------1.增----------------------
println("----------------------1.增----------------------")
map.put("P", "Python")
println("map: ${map}")

def map2 = [C: "C++"]
map.putAll(map2)
println("map: ${map}")

//----------------------2.删----------------------
println("----------------------2.删----------------------")
map.remove("P") // 根据某个Key做移除
map.remove("J", "Java") // 移除某个键值对
println("map: ${map}")

//----------------------3.改----------------------
println("----------------------3.改----------------------")
// "-" "+" 操作符
map3 = map - ["K": "Kotlin"]
println("map3: ${map3}")

map4 = map + [G: "Gradle"] // key相同则会覆盖
println("map4: ${map4}")

//----------------------4.查----------------------
println("----------------------4.查----------------------")
map.each { key, value ->
    {
        println("key: $key, value: $value")
    }
}

6.案例 6:类导入

Groovy 遵循 Java 允许 import 语句解析类引用的概念。

import groovy.xml.MarkupBuilder 
def xml = new MarkupBuilder() 
assert xml != null

Groovy 语言默认提供的导入

import java.lang.* 
import java.util.* 
import java.io.* 
import java.net.* 
import groovy.lang.* 
import groovy.util.*
import java.math.BigInteger
import java.math.BigDecimal

这样做是因为这些包中的类最常用。通过导入这些样板代码减少了。

参考官网地址:

http://www.groovy-lang.org/structure.html#_imports

7. 案例 7:异常处理

Groovy 中的异常处理和 java 中的异常处理是一样的。

def z 
try {
    def i = 7, j = 0 
    try {
        def k = i / j 
        assert false
    } finally {
        z = 'reached here'
    }
} catch ( e ) {
    assert e in ArithmeticException 
    assert z == 'reached here'
}

参考官网地址:

http://www.groovy-lang.org/semantics.html#_try_catch_finally

8. 案例 8:闭包

闭包:Groovy 中的闭包是一个开放的、匿名的代码块,它可以接受参数、也可以有返回值。闭包可以引用其周围作用域中声明的变量。

语法:{ [closureParameters -> ] statements }

其中[ closureParameters-> ]是一个可选的逗号分隔的参数列表,参数后面是  Groovy 语句。参数类似于方法参数列表, 这些参数可以是类型化的,也可以是非类型化的。当指定参数列表时,需要使用-> 字符,用于将参数与闭包体分离。

参考:http://www.groovy-lang.org/closures.html

//闭包体完成变量自增操作
{ item++ }
//闭包使用 空参数列表 明确规定这是无参的
{ -> item++ }
//闭包中有一个默认的参数[it],写不写无所谓
{ println it }
{ it -> println it }
//如果不想使用默认的闭包参数it,那需要显示自定义参数的名称
{ name -> println name }
//闭包也可以接受多个参数
{ String x, int y ->
    println "hey ${x} the value is ${y}"
}
//闭包参数也可是一个对象
{ reader ->
    def line = reader.readLine() 
    line.trim()
}

闭包调用方式:闭包是 groovy.lang.Closure 的实例。它可以像任何其他变量一样分配给一个变量或字段。

闭包对象(参数)

闭包对象.call(参数)

def isOdd = { int i -> i%2 != 0 } 
assert isOdd(3) == true
assert isOdd.call(2) == false

def isEven = { it%2 == 0 } 
assert isEven(3) == false 
assert isEven.call(2) == true

特殊说明:可以把闭包当作一个对象,作为参数传递给方法使用

package test.demo

/**=================================================
 * 闭包:
 *      定义:是一个开放的、匿名的代码块,它可以接受参数、也可以有返回值。闭包可以引用其周围作用域中声明的变量。
 *      语法:{ [closureParameters -> ] statements }
 *      调用:
 *          第一步:将闭包赋值给一个变量
 *          第二步:变量名()、变量名.call()
 *
 *       闭包在实际开发中的使用:作为方法的参数使用
 =================================================*/

// 1. 有参数的闭包
println("1. 有参数的闭包")
// 定义闭包
def running = { who ->
    println("$who running start .....")
    println("$who running end .....")
}

// 调用闭包
running()
running.call("小明")

// 2. 将闭包作为对象参数,传递给闭包
println("2. 将闭包作为对象参数,传递给闭包")
// 2.1 定义无参闭包
println("2.1 无参闭包")

def run(Closure closure) {
    println("run start....")
    // 执行无参闭包
    closure()
    println("run end....")
}

// 执行闭包
run {
    println("running....")
}

// 2.2 定义有参闭包
println("2.2 有参闭包")

def caculate(Closure closure) {
    def num1 = 1
    def num2 = 3
    println("caculate start....")
    // 执行有参闭包
    closure(num1, num2)
    println("caculate end....")
}

// 执行有参闭包
caculate { x, y -> println("计算结果为: $x + $y = ${x + y}") }

执行如下:

246485f844e116262d2a2ebd8e145352.png

1685770311565

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/644537.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【OpenCV DNN】Flask 视频监控目标检测教程 08

欢迎关注『OpenCV DNN Youcans』系列&#xff0c;持续更新中 【OpenCV DNN】Flask 视频监控目标检测教程 08 3.8 OpenCVFlask实时监控人脸识别控制按钮新建 Flask 项目 cvFlask08cPython程序文件视频流的网页模板程序运行 本系列从零开始&#xff0c;详细讲解使用 Flask 框架构…

Nature子刊:生物合成硝基化蛋白,助力解决药物免疫耐受!

氨基酸是蛋白质的单个构建模块&#xff0c;对生物系统的正常运转至关重要。所有生物系统中的蛋白质都是由20种标准氨基酸组成的&#xff0c;自然界中还发现了超过500种不同类型的其他氨基酸&#xff0c;以及大量的人造氨基酸。其中一些替代氨基酸有助于创造新类型的药物和治疗方…

阿里企业邮箱注册流程(新手指南)

阿里云企业邮箱购买流程&#xff0c;企业邮箱分为免费版、标准版、集团版和尊享版&#xff0c;阿里云百科分享企业邮箱版本区别&#xff0c;企业邮箱收费标准价格表&#xff0c;以及阿里企业邮箱详细购买流程&#xff1a; 目录 阿里云企业邮箱购买流程 一、阿里云账号注册及…

驱动开发:内核ShellCode线程注入

还记得《驱动开发&#xff1a;内核LoadLibrary实现DLL注入》中所使用的注入技术吗&#xff0c;我们通过RtlCreateUserThread函数调用实现了注入DLL到应用层并执行&#xff0c;本章将继续探索一个简单的问题&#xff0c;如何注入ShellCode代码实现反弹Shell&#xff0c;这里需要…

ChatGPT 背后的技术重点:RLHF、IFT、CoT、红蓝对抗

近段时间&#xff0c;ChatGPT 横空出世并获得巨大成功&#xff0c;使得 RLHF、SFT、IFT、CoT 等这些晦涩的缩写开始出现在普罗大众的讨论中。这些晦涩的首字母缩略词究竟是什么意思&#xff1f;为什么它们如此重要&#xff1f;我们调查了相关的所有重要论文&#xff0c;以对这些…

Go1.21 速览:go.mod 的 Go 版本号将会约束 Go 程序构建,要特别注意了!

大家好&#xff0c;我是煎鱼。 之前 Go 核心团队的负责人 Russ Cox 针对 Go 的向前兼容&#xff08;指的是旧版本的 Go 编译新的 Go 代码&#xff09;&#xff0c;进行了进一步的设计。 重点内容如下&#xff1a; 新增 GOTOOLCHAIN 环境变量的设置。改变在工作模块&#xff08;…

阿里云弹性公网EIP收费价格表

阿里云弹性公网EIP怎么收费&#xff1f;EIP地域不同价格不同&#xff0c;EIP计费模式分为包年包月和按量付费&#xff0c;弹性公网IP可以按带宽收费也可以按使用流量收费&#xff0c;阿里云百科分享阿里云弹性公网IP不同地域、不同计费模式、按带宽和按使用流量详细收费价格表&…

cpp新小点1

这里写目录标题 argc argv继承虚继承多态override不加override overload纯虚函数和抽象类虚析构和纯虚析构 static和 constexternself前置 后置默认构造 析构继承构造函数不能是虚函数派⽣类的override虚函数定义必须和⽗类完全⼀致。 有特列何时共享虚函数地址表 智能指针arrm…

【数据库必备知识】上手表设计

目录 &#x1f4d6;前言 1. 基本步骤 1.1 梳理清楚需求中的实体 1.2 梳理清楚实体间的关系 2. 实体间的三种关系 2.1 一对一 2.2 一对多 2.3 多对多 &#x1f389;小结ending &#x1f4d6;前言 本文讲解的是基本的表设计, 设计一般只有在有一定实际项目经验后, 才能…

MAVEN - 使用maven-dependency-plugin的应用场景是什么?

简述 maven-dependency-plugin是MAVEN的一个插件。 作用 该插件主要用于管理项目中的依赖&#xff0c;使用该插件可以方便地查看、下载、复制和解压缩依赖&#xff0c;还支持生成依赖树和依赖报告。 功能 该插件有很多可用的GOAL&#xff0c;大部分与依赖构建、依赖分析和依…

《面试1v1》Map

我是 javapub&#xff0c;一名 Markdown 程序员从&#x1f468;‍&#x1f4bb;&#xff0c;八股文种子选手。 《面试1v1》 连载中… 面试官&#xff1a; 小伙子,又来挑战你了。听说你对Java集合中的Map也很在行? 候选人&#xff1a; 谢谢夸奖,Map这个接口的确非常重要且强大…

SpringMVC原理分析 | JSON、Jackson、FastJson

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; JSON JSON&#xff08;JavaScriptObject Notation&#xff0c;JS对象简谱&#xff09;是一种轻量级的数据交换格式。它基于 ECMAScript&#xff08;European Computer…

无自注意力照样高效!RIFormer开启无需token mixer的Transformer结构新篇章

©PaperWeekly 原创 作者 | 岳廷 研究方向 | 计算机视觉 引言 论文地址&#xff1a; https://openaccess.thecvf.com/content/CVPR2023/papers/Wang_RIFormer_Keep_Your_Vision_Backbone_Effective_but_Removing_Token_Mixer_CVPR_2023_paper.pdf 问题&#xff1a;Vision …

如何将代码中的相关调试信息输出到对应的日志文件中

一、将调试信息输出到屏幕中 1.1 一般写法 我们平常在写代码时&#xff0c;肯定会有一些调试信息的输出&#xff1a; #include <stdio.h> #include <stdlib.h>int main() {char szFileName[] "test.txt";FILE *fp fopen(szFileName, "r")…

R语言 tidyverse系列学习笔记(系列5)dplyr 数据分析之across

成绩单 score install.packages("dplyr") library(dplyr)install.packages("tibble") library(tibble)install.packages("stringr") library(stringr)score tibble(IDc("1222-1","2001-0","3321-1","4898-…

MySQL(八):排序与分页

排序与分页 前言一、排序数据1、排序规则2、单列排序3、多列排序 二、分页1、背景2、实现规则3、拓展 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识&#xff0c;有兴趣的小伙伴可以关注博主&#xff01;也许一个人独行&#xff0c;可以走的很快&…

从零开始Vue项目中使用MapboxGL开发三维地图教程(三)添加全屏,缩放旋转和比例控制面板以及自定义图标、标记点击弹窗、地图平移等功能

文章目录 1、添加各种控制面板1.1、添加全屏1.2、缩放旋转控制1.3、比例尺 2、获取并显示鼠标移动位置的经纬度坐标3、添加图标3.1、添加图片图层的图标3.2、添加带有标记的自定义图标3.3、悬停时显示弹出窗口 1、添加各种控制面板 1.1、添加全屏 //添加全屏控制this.map.addC…

管理类联考——逻辑——知识篇——第一章 性质命题

第一章 性质命题&#xff08;最基础&#xff0c;最难*****&#xff09; 一、性质命题定义&#xff08;必考&#xff09; 判断事物具有或不具有某种性质的命题。 二、性质命题的四种基本形式 全称肯定&#xff1a;①所有的A都是B 全称否定&#xff1a;②所有的A不是B 特称肯…

Nature子刊:光遗传在绒猴执行检测任务中的行为效应

狨猴体型小&#xff0c;具有巨大的基因修饰潜力&#xff0c;并可表现复杂的行为&#xff0c;已经成为神经科学领域的一个关键模型。 德国恩斯特斯特朗格曼神经科学研究所与马克斯普朗克学会的研究人员设计了一种轻质的、3D打印的植入物&#xff0c;利用高密度硅基微电极阵列&am…

Monorepo vs. Microrepo: 选择适合你的代码仓库策略

简介 在软件开发领域&#xff0c;选择合适的代码仓库策略对于优化协作、可扩展性和代码质量至关重要。Monorepo和Microrepo是两种流行的方法&#xff0c;它们提供了各自的优势和考虑因素。本文将探讨这两种策略的特点&#xff0c;解释为何不同的公司选择不同的选项&#xff0c;…