Groovy初学者指南

本文已收录至Github,推荐阅读 ? Java随想录

微信公众号:Java随想录

目录
  • 摘要
  • Groovy与Java的联系和区别
  • Groovy的语法
    • 动态类型
    • 元编程
    • 处理集合的便捷方法
    • 闭包
    • 运算符重载
    • 控制流
      • 条件语句
      • 循环语句
    • 字符串处理
      • 字符串插值
      • 多行字符串
    • 集合与迭代
      • 列表(List)
      • 映射(Map)
      • 迭代器
    • 异常处理
  • 在Java中使用GroovyShell运行Groovy
    • 添加Maven依赖
    • Binding
    • CompilationCustomizer
    • GroovyClassLoader
  • Groovy生态系统
    • 构建工具 - Gradle
    • Web开发框架 - Grails
    • 测试框架 - Spock
  • 总结

摘要

Groovy是一种基于Java平台的动态编程语言,它结合了Python、Ruby和Smalltalk等语言的特性,同时与Java无缝集成。在本篇博客中,我们将探讨Groovy与Java之间的联系与区别,深入了解Groovy的语法,并展示如何在Java中使用GroovyShell来运行Groovy脚本。

Groovy与Java的联系和区别

Groovy与Java之间有着紧密的联系,同时也存在一些重要的区别。首先,Groovy是一种动态语言,它允许在运行时动态修改代码。这使得Groovy在处理反射、元编程和脚本化任务时更加灵活。与此相反,Java是一种静态类型的编程语言,它要求在编译时就要确定类型和结构。

另一个联系和区别在于Groovy与Java代码的互操作性。Groovy可以直接调用Java类和库。这意味着可以在Groovy中使用Java类,也可以在Java中使用Groovy类。这种无缝集成使得Groovy成为Java开发人员的有力补充

Groovy与Java相比,提供了一些额外的功能和简化的语法。例如,Groovy支持动态类型、闭包、运算符重载等特性,使得代码更加简洁易读。下面我们将介绍Groovy的语法。

Groovy的语法

Groovy的语法与Java有许多相似之处,但也有一些重要的区别。下面是一些Groovy语法的关键要点:

动态类型

Groovy是一种动态类型语言,它允许变量的类型在运行时进行推断和修改。这意味着你可以在不声明变量类型的情况下直接使用它们,从而简化了代码的编写。例如:

def name = "Alice"  // 动态类型的变量声明
name = 42  // 可以将不同类型的值赋给同一个变量

元编程

Groovy支持元编程,这意味着你可以在运行时动态修改类、对象和方法的行为。通过使用Groovy的元编程特性,你可以更加灵活地编写代码,并且可以根据需要动态添加、修改或删除类的属性和方法。例如:

class Person {
    String name
    int age
}

def person = new Person()
person.name = "Alice"

Person.metaClass.sayHello = {
    "Hello, ${delegate.name}!"
}

println(person.sayHello())  // 输出: Hello, Alice!

处理集合的便捷方法

Groovy提供了丰富的集合操作方法,使得处理集合变得更加便捷。它支持链式调用,可以通过一条语句完成多个集合操作,如过滤、映射、排序等。例如:

def numbers = [1, 2, 3, 4, 5]
def result = numbers.findAll { it % 2 == 0 }.collect { it * 2 }.sum()
println(result)

在这个示例中,我们对列表中的偶数进行过滤、乘以2并求和。

闭包

闭包是Groovy中一个强大而有用的特性,它可以简化代码并实现更灵活的编程。闭包是一个可以作为参数传递给方法或存储在变量中的代码块。下面是一个使用闭包的示例:

def calculate = { x, y -> x + y }
def result = calculate(3, 5)
println(result)  // 输出:8

在这个例子中,我们定义了一个名为calculate的闭包,它接受两个参数并返回它们的和。然后,我们通过将参数传递给闭包来调用它,并将结果存储在result变量中。

运算符重载

Groovy允许重载许多运算符,以便根据需要自定义操作。例如,可以重载+运算符来实现自定义的加法操作。下面是一个使用运算符重载的示例:

class Vector {
    double x, y
    
    Vector(double x, double y) {
        this.x = x
        this.y = y
    }
    
    Vector operator+(Vector other) {
        return new Vector(this.x + other.x, this.y + other.y)
    }
}

def v1 = new Vector(2, 3)
def v2 = new Vector(4, 5)
def sum = v1 + v2
println(sum.x)  // 输出:6
println(sum.y)  // 输出:8

在这个例子中,我们定义了一个名为Vector的类,并重载了+运算符,以实现两个向量的加法操作。通过使用运算符重载,我们可以像操作基本类型一样简单地对自定义类型进行操作。

控制流

条件语句

Groovy支持传统的if-else条件语句,也可以使用switch语句进行多路分支判断。下面是一个示例:

def score = 85

if (score >= 90) {
    println("优秀")
} else if (score >= 80) {
    println("良好")
} else if (score >= 60) {
    println("及格")
} else {
    println("不及格")
}

在这个示例中,根据分数的不同范围,打印出相应的等级。

循环语句

Groovy提供了多种循环语句,包括for循环、while循环和each循环。下面是一个使用for循环输出数组元素的示例:

def numbers = [1, 2, 3, 4, 5]
for (number in numbers) {
    println(number)
}

这段代码将依次输出数组中的每个元素。

字符串处理

字符串插值

Groovy中的字符串可以使用插值语法,方便地将变量的值嵌入到字符串中。示例如下:

def name = "Alice"
def age = 30
def message = "My name is $name and I am $age years old."
println(message)

在这个示例中,我们使用$name$age将变量的值插入到字符串中。

多行字符串

Groovy支持使用三引号(""")来创建多行字符串。这对于包含换行符和格式化文本非常有用。示例如下:

def message = """
    Hello, Groovy!
    Welcome to the world of Groovy programming.
    Enjoy your coding journey!
"""
println(message)

在这个示例中,我们使用三引号创建了一个包含多行文本的字符串,并打印出来。

集合与迭代

列表(List)

Groovy中的列表是一种有序的集合,可以存储多个元素。下面是一个使用列表的示例:

def fruits = ["apple", "banana", "orange"]
println(fruits[0])  // 输出: apple
println(fruits.size())  // 输出: 3

在这个示例中,我们定义了一个包含三个元素的列表fruits。我们可以使用索引访问列表中的元素,并使用size()方法获取列表的大小。

映射(Map)

Groovy中的映射是一种键值对的集合。它类似于Java中的HashMap。下面是一个使用映射的示例:

def person = [name: "Alice", age: 30, city: "New York"]
println(person.name)  // 输出: Alice
println(person.age)  // 输出: 30

在这个示例中,我们定义了一个包含姓名、年龄和城市信息的映射person。我们可以使用点号语法访问映射中的值。

迭代器

Groovy提供了方便的迭代器来遍历集合中的元素。下面是一个使用迭代器的示例:

def numbers = [1, 2, 3, 4, 5]
numbers.each { number ->
    println(number)
}

在这个示例中,我们使用each方法和闭包来遍历列表numbers中的每个元素,并打印出来。

异常处理

在Groovy中,我们可以使用try-catch块来捕获和处理异常。下面是一个异常处理的示例:

def divide(a, b) {
    try {
        return a / b
    } catch (ArithmeticException e) {
        println("除数不能为0")
    } finally {
        println("执行finally块")
    }
}

divide(10, 2)
divide(10, 0)

在这个示例中,我们定义了一个名为divide的方法,它尝试计算两个数的除法。如果除数为0,将捕获ArithmeticException异常并打印出错误信息。无论是否发生异常,finally块中的代码都会执行。

在Java中使用GroovyShell运行Groovy

添加Maven依赖

首先,我们需要在项目中添加Groovy的Maven依赖。在pom.xml文件中,添加以下依赖项:

<dependencies>
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy</artifactId>
        <version>3.0.9</version>
    </dependency>
</dependencies>

这将确保我们可以在Java项目中使用GroovyShell类。

在Java代码中,我们可以通过创建GroovyShell实例来执行Groovy代码。下面是一个简单的示例:

import groovy.lang.GroovyShell;

public class GroovyRunner {
    public static void main(String[] args) {
        GroovyShell shell = new GroovyShell();

        String script = "println 'Hello, Groovy!'";

        shell.evaluate(script);
    }
}

在这个例子中,我们创建了一个GroovyShell实例,并将Groovy代码存储在一个字符串变量script中。然后,我们使用evaluate方法来执行Groovy代码。在这里,我们的Groovy代码只是简单地打印出一条消息。

除了直接在Java代码中定义Groovy代码,我们还可以将Groovy代码保存在独立的脚本文件中,并通过GroovyShell来执行该脚本。下面是一个示例:

import groovy.lang.GroovyShell;
import java.io.File;
import java.io.IOException;

public class GroovyScriptRunner {
    public static void main(String[] args) {
        GroovyShell shell = new GroovyShell();

        try {
            File scriptFile = new File("script.groovy");
            shell.evaluate(scriptFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个例子中,我们创建了一个File对象来表示Groovy脚本文件。然后,我们使用evaluate方法来执行该脚本。

Binding

Binding类是GroovyShell的一个关键组件,它提供了变量绑定和上下文环境。通过Binding,我们可以在GroovyShell中定义变量,以及在Groovy代码中访问这些变量。下面是一个示例:

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

public class GroovyBindingExample {
    public static void main(String[] args) {
        Binding binding = new Binding();
        GroovyShell shell = new GroovyShell(binding);

        binding.setVariable("name", "John");
        String script = "println 'Hello, ' + name";
        shell.evaluate(script);  // 输出:Hello, John
    }
}

在这个例子中,我们创建了一个Binding实例,并将其传递给GroovyShell的构造函数。然后,我们使用setVariable方法在Binding中设置变量name的值。在Groovy脚本中,我们可以通过变量name来访问绑定的值。

Binding还可以在Groovy脚本中定义和访问方法、属性等。它提供了一种强大的机制来构建丰富的动态环境。

CompilationCustomizer

CompilationCustomizer是一个接口,用于自定义GroovyShell的编译行为。通过实现CompilationCustomizer接口,我们可以在编译Groovy代码之前或之后对代码进行修改、添加额外的功能或验证。以下是一个示例:

import groovy.lang.GroovyShell;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.CompilationCustomizer;
import org.codehaus.groovy.control.customizers.ImportCustomizer;

public class GroovyCustomizationExample {
    public static void main(String[] args) {
        ImportCustomizer importCustomizer = new ImportCustomizer();
        importCustomizer.addStarImports("java.util");

        CompilationCustomizer customizer = new CompilationCustomizer() {
            @Override
            public void call(CompilerConfiguration configuration, GroovyShell shell) {
                configuration.addCompilationCustomizers(importCustomizer);
            }
        };

        CompilerConfiguration configuration = new CompilerConfiguration();
        configuration.addCompilationCustomizers(customizer);

        GroovyShell shell = new GroovyShell(configuration);

        String script = "List<String> list = new ArrayList<String>(); list.add('Hello'); println list";
        shell.evaluate(script);  // 输出:[Hello]
    }
}

在这个例子中,我们创建了一个ImportCustomizer,用于添加java.util包下的所有类的导入。然后,我们创建了一个CompilationCustomizer的实例,并在call方法中将ImportCustomizer添加到编译配置中。最后,我们通过传递自定义的编译配置来创建GroovyShell实例。

通过使用CompilationCustomizer,我们可以在编译过程中自定义Groovy代码的行为,并添加自定义的功能和验证。

GroovyClassLoader

GroovyClassLoader是Groovy的类加载器,它允许我们在运行时动态加载和执行Groovy类。通过GroovyClassLoader,我们可以加载Groovy脚本或Groovy类,并使用其实例来调用方法和访问属性。以下是一个示例:

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;

public class GroovyClassLoaderExample {
    public static void main(String[] args) throws Exception {
        GroovyClassLoader classLoader = new GroovyClassLoader();

        String script = "class Greeting {\n" +
                "  String message\n" +
                "  def sayHello() {\n" +
                "    println 'Hello, ' + message\n" +
                "  }\n" +
                "}\n" +
                "return new Greeting()";

        Class<?> clazz = classLoader.parseClass(script);
        GroovyObject greeting = (GroovyObject) clazz.newInstance();

        greeting.setProperty("message", "John");
        greeting.invokeMethod("sayHello", null);  // 输出:Hello, John
    }
}

在这个例子中,我们使用GroovyClassLoaderparseClass方法来解析Groovy脚本并生成相应的类。然后,我们通过实例化该类来获得一个GroovyObject,并使用setProperty方法设置属性的值。最后,我们通过invokeMethod方法调用方法并执行Groovy代码。

GroovyClassLoader提供了一种灵活的方式来在运行

Groovy生态系统

Groovy不仅是一种语言,还拥有一个丰富的生态系统,包括各种工具、框架和库,为开发人员提供了丰富的选择和支持。

构建工具 - Gradle

Gradle是一种强大的构建工具,它使用Groovy作为其构建脚本语言。通过使用Gradle,您可以轻松地定义和管理项目的构建过程,包括编译、测试、打包、部署等。Groovy的灵活语法使得编写Gradle构建脚本变得简单和可读。

Web开发框架 - Grails

Grails是一个基于Groovy的全栈Web应用程序开发框架,它建立在Spring Boot和Groovy语言之上。Grails提供了简洁、高效的方式来构建现代化的Web应用程序,包括支持RESTful API、数据库访问、安全性等。

测试框架 - Spock

Spock是一个基于Groovy的测试框架,它结合了JUnit和其他传统测试框架的优点。Spock使用Groovy的语法和特性,提供了一种优雅和简洁的方式来编写测试代码。它支持行为驱动开发(BDD)风格的测试,并提供丰富的断言和交互式的测试报告。

除了以上提到的工具和框架,Groovy还有许多其他的库和扩展,涵盖了各种领域和用途,如数据库访问、JSON处理、并发编程等。以下是一些常用的Groovy库和扩展:

  • Groovy SQL: Groovy SQL是一个简化数据库访问的库,它提供了简洁的API来执行SQL查询、更新和事务操作。
  • JSON处理: Groovy提供了内置的JSON处理功能,使得解析和生成JSON数据变得简单。您可以使用JsonSlurper来解析JSON数据,使用JsonOutput来生成JSON数据。
  • Groovy GDK: Groovy GDK(Groovy Development Kit)是一组扩展类和方法,为Groovy提供了许多额外的功能和便利方法,如日期时间处理、字符串操作、集合处理等。
  • Groovy并发编程: Groovy提供了一些方便的并发编程工具和库,如@ThreadSafe注解、java.util.concurrent包的扩展等,使得编写多线程应用程序变得更加简单和安全。
  • Groovy Swing: Groovy提供了对Swing GUI库的支持,使得构建图形界面应用程序更加简单和直观。

除了上述库和扩展,Groovy还与许多其他Java库和框架紧密集成,包括Spring Framework、Hibernate、Apache Camel等。这些集成使得在Groovy中使用这些库和框架变得更加方便和优雅。

总之,Groovy不仅是一种功能强大的动态编程语言,还拥有丰富的生态系统和强大的元编程能力。通过与Java紧密结合,Groovy为开发人员提供了更灵活、简洁的语法和丰富的工具、框架支持,使得开发高效、可维护的应用程序变得更加容易。

总结

Groovy是一种强大的动态编程语言,与Java完美结合,为开发人员提供了更灵活和简洁的语法。它与Java具有紧密的联系,可以无缝地与Java代码互操作。Groovy支持动态类型、闭包、运算符重载等特性,使得代码更易读、简洁。通过使用GroovyShell,您可以在Java项目中动态执行Groovy代码,利用Groovy的动态性和灵活性。


本篇文章就到这里,感谢阅读,如果本篇博客有任何错误和建议,欢迎给我留言指正。文章持续更新,可以关注公众号第一时间阅读。

本文转载于网络 如有侵权请联系删除

相关文章

  • 快速上手 ClickHouse

    本篇来自数月前对外分享的文稿整理,并进行了一些扩展。希望通过简单的方式,来介绍新手如何一步一步上手ClickHouse,如果你有潜在的数据分析的需求,但是不知道从哪里开始,那么希望本文能够帮助到你。写在前面关于ClickHouse在追求性能的场景下的溢美之词,我觉得没有必要再重复了。以过往经验来看,你可以使用极其低的成本来完成以往RDBMS(比如MySQL)做不到的准实时级别的数据分析,也可以用它来做远程多个数据库实例的数据迁移或者归档存储。感谢两年前一位好朋友对我进行的技术选型推荐,使用ClickHouse可以简化非常多的不必要的基础设施搭建和维护。我们曾搭建过一台比较奢华的机器(256核心512GB内存)来进行准实时的数据分析(花费万分之几秒从海量数据中查结果),以及支持每秒落地几十万条以上数据,而丝毫不影响服务器查询性能;也曾实践过从两千块的NUC上跑边缘计算任务,相对快速的拿到需要分析的结果(花费千分之一到百分之一秒),以及在16核心64GB内存的普通笔记本上,跑超过十亿数据集的复杂计算的尝试(分钟级)。之前使用过的“豪华”配置所以,如果你有以下需求,ClickHouse可能也

  • 告别加班:一个让你不再重复工作的技能

    996一直是互联网老生常谈的话题了,但抛开其他只谈工作本身,你有没有想过,下班晚、加班,有时候可能是因为自己工作比较低效? 前阵子领导层打算引进一个大项目,要林晓做份详细报告作决策依据。这时她遇到了这么一个难题:一张表记录了1000个不同产品的销售情况,领导现在需要将同一类产品归到一个Excel。这样一来林晓就要拆分成1000张表。Q林晓该怎么解决这个问题呢?如果用传统的方法:第一步,筛选 使用Excel的筛选功能,可以对相应的列进行筛选。从而得到这一列的唯一值。第二步,复制 选中筛选出来的部分复制。第三步,新建 新建一个空的Excel重命名。第三步,粘贴 选中筛选出来的部分复制。这差不多就是一个完整的工作流,有多少产品就要重复多少次操作。林晓发现,这里有1000个产品,就算自己特别熟练,一个操作只要6秒钟,操作1000次,也要6000秒,100分钟,自己得差不多操作1多小时。如果是5000个产品,10000个产品,那可怎么办啊?!林晓想想就要奔溃,无奈下只得央求职场上春风得意的闺蜜,让其传授些经验。闺蜜得知林晓的难题后,说“这个简单,给你看看我的方法”就是这么几行简单的代码。读取原数

  • ​使用 KeyCloak 对 Kubernetes 进行统一用户管理

    众所周知,K8s的权限管理体系(不熟悉的盆友可以跳转至《Kubernetes安全机制解读》)中,可以将RoleBinding绑定到ServiceAccount、User、Group上来实现权限分配。 其中ServiceAccount我们经常用到,用来限制某个pod的权限;对于User和Group,除了一些特殊的系统group,并没有具体的资源与之对应,这对于传统项目中的用户管理十分不友好。上一篇文章中讲到了OIDC协议在K8s集群中如何工作,这篇文章来具体讲讲如何在K8s集群中进行统一用户管理。准备工作首先我们需要有一个IdentityProvider来统一管理K8s中的用户,并且提供OIDC协议服务,本文采用了KeyCloak作为IdentityProvider。KeyCloak中的配置要想实现用户管理,我们需要利用K8s中group的概念,来对一组用户分配权限,这需要利用OIDC协议中的Claim概念,来实现K8s中用户的分组。Claim是IDToken中携带的信息,指的是客户端请求的信息范围,如用户名、邮箱等,而这些可以进行扩展用来携带一些用户所属group的信息等等。那么第一步

  • Linux Mint 20 与 Debian 版本 LMDE 4 新特性

    LinuxMint20将基于Ubuntu20.04LTS,同时,其 LMDE(LinuxMintDebianEdition,Debian版本)4也将到来,LMDE版本基于DebianGNU/Linux,提供滚动发布,而不是像常规的LinuxMint基于Ubuntu。日前LinuxMint官方博客释出了关于LinuxMint20与LMDE4的新特性信息。LMDE4LMDE4将首先发布,基于改进的Debian10软件包,它将带来在LinuxMint19.3上的所有改进,包括HDT、引导修复、系统报告、语言设置、HiDPI和、新的引导菜单、Celluloid、Gnote、Cinnamon4.4与XApp状态图标等。LMDE3中缺少的某些功能也从LinuxMint移植而来。LMDE4还将支持Btrfs子模块和主目录加密:引导菜单中的NVIDIA驱动一直以来在某些NVIDIA卡上存在Nouveau(开源驱动程序)兼容性问题,在大多数情况下,人们不得不使用nomodeset,但是当Nouveau根本无法识别芯片组时,完全没有图形显示。LMDE4中,在启动菜单中添加了一个新条目,该条目可即时安装NV

  • 多编程语言语法对照表

    本文由腾讯云+社区自动同步,原文地址https://stackoverflow.club/106/背景有时候会出现一天内使用多种语言进行开发的情况,比如在python,matlab,java,c++之间来回切换,稍不注意就会把语法规则搞错,影响效率。本文致力于解决上述问题,主要提供了各语言语法层面的差异,如变量操作、逻辑跳转等语句,供快速查询。python条件跳转1234ifif_clause:process1else:process2循环12345678910111213matlab条件判断 12345678910%if之后不加括号,不加冒号%<statements>不需要括号if<expression><statements>;else<statements>;end循环123456789101112131415161718%while循环while<expression><statements>;end%for循环%使用index=values来控制循环次数forindex=values<program

  • Java 高并发综合

    这篇文章是研一刚入学时写的,今天整理草稿时才被我挖出来。当时混混沌沌的面试,记下来了一些并发的面试问题,很多还没有回答。到现在也学习了不少并发的知识,回过头来看这些问题和当时整理的答案,漏洞百出又十分可笑。发表出来权当对自己的一个提醒——如果不能一直进步,你就看不到当初傻逼的自己。曾经,我在面试Java研发实习生时最常听到的一句话就是:搞Java怎么能不学并发呢?没错,真的是经过了面试官的无数鄙视,我才知道Java并发编程在Java语言中的重要性。并发模型悲观锁和乐观锁的理解及如何实现,有哪些实现方式?悲观锁悲观锁假设最坏的情况(如果你不锁门,那么捣蛋鬼就会闯入并搞得一团糟),并且只有在确保其他线程不会干扰(通过获取正确的锁)的情况下才能执行下去。常见实现如独占锁等。安全性更高,但在中低并发程度下的效率更低。乐观锁乐观锁借助冲突检查机制来判断在更新过程中是否存在其他线程的干扰,如果存在,这个操作将失败,并且可以重试(也可以不重试)。常见实现如CAS等。部分乐观锁削弱了一致性,但中低并发程度下的效率大大提高。并发编程Java中如何创建一个线程从面相接口的角度上讲,实际上只有一种方法实现R

  • Linux下实现自定义命令行工具小技巧

    事件背景最近几天在Linux系统部署服务过程中,常常会用到tar(压缩/解压缩)命令,如果只有个别两个xx.tar.gz文件,还能通过tar-xvfxx.tar.gz命令快速实现解压缩操作,但如果几十、几百个tar包的话,使用此命令一一解压未免过于繁琐。因此,可以通过for循环来实现批量解压缩:fortarin*.tar.gz;dotar-xvf$tar;done复制但随之而来的问题是,如果有多个目录下都有大量的压缩包需要解压,那每解压一个目录下的文件都要敲一遍此命令?能否自定义一个命令行工具,像系统命令ls/mv/cp/tar/ps···那样,在任意目录下都能执行,并实现批量解压缩的操作?答案肯定是可以的。实现思路:在存放可执行程序的目录下创建一个可执行脚本文件将上述批量解压缩命令写在可执行文件中赋予该文件执行权限、重新加载配置实现过程1.创建shell脚本Linux下存放脚本目录及作用目录作用/usr/bin当前用户的程序,为系统预装的可执行程序,会随着系统升级而改变。/usr/local/bin用户放置自己的可执行程序的地方,不会被系统升级而覆盖同名文件。创建脚本cd/usr/l

  • 麒麟系统V10 SP2 KVM virt-install 创建虚拟机

    virt-install创建虚拟机virt-install参数说明--name指定虚拟机名称--memory分配内存大小--vcpus分配CPU核心数--disk指定虚拟机磁盘文件,size指定分配大小单位为G--network网络类型--pxe基于PXE完成安装--accelerate加速--cdrom指定系统iso镜像--location从ftp,http,nfs启动,如ftp://192.168.10.7/dvd;nfs:192.168.10.7:/dvd--graphics图形化控制台none不启用--vnc启用VNC远程管理--vncport指定VNC监控端口,默认端口为5900--vnclisten指定VNC绑定IP,默认绑定127.0.0.1,改为0.0.0.0--os-type虚拟机类型linux,windows--os-variant[使用"osinfo-queryos"查看支持的版本]--force如果有yes或者no的交互式,自动yes--noautoconsole表示不会自动连入虚拟机的控制台--extra-args根据--location指

  • 强化学习读书笔记 - 13 - 策略梯度方法(Policy Gradient Methods)

    强化学习读书笔记-13-策略梯度方法(PolicyGradientMethods) 学习笔记: ReinforcementLearning:AnIntroduction,RichardS.SuttonandAndrewG.Bartoc2014,2015,2016 参照 ReinforcementLearning:AnIntroduction,RichardS.SuttonandAndrewG.Bartoc2014,2015,2016 强化学习读书笔记-00-术语和数学符号 强化学习读书笔记-01-强化学习的问题 强化学习读书笔记-02-多臂老O虎O机问题 强化学习读书笔记-03-有限马尔科夫决策过程 强化学习读书笔记-04-动态规划 强化学习读书笔记-05-蒙特卡洛方法(MonteCarloMethods) 强化学习读书笔记-06~07-时序差分学习(Temporal-DifferenceLearning) 强化学习读书笔记-08-规划式方法和学习式方法 强化学习读书笔记-09-on-policy预测的近似方法 强化学习读书笔记-10-on-policy控制的近似方法 强化学习读书笔

  • Flask 中内置的 Session

    Flask中的Session Flask中的Session不同于Django的session,django的session存在后端数据库中,而flask的session会将你的SessionID存放在客户端的Cookie中,使用起来非常的奇怪   1.Flask中session是需要secret_key的 fromflaskimportsession app=Flask(__name__) app.secret_key="kjklgfjoewghoqh"复制 secret_key实际上是用来加密字符串的,如果在实例化的app中没有secret_key那么开启session一定会抛异常的   2.Flask中session要这样用 @app.route("/login",methods=["GET","POST"]) deflogin(): ifrequest.method=="POST": ifrequest.form["username"]==USER["username"]andrequest.form["password"]==USER["pass

  • iOS开发网络篇—HTTP协议

     iOS开发网络篇—HTTP协议 说明:apachetomcat服务器必须占用8080端口 一、URL 1.基本介绍 URL的全称是UniformResourceLocator(统一资源定位符) 通过1个URL,能找到互联网上唯一的1个资源 URL就是资源的地址、位置,互联网上的每个资源都有一个唯一的URL   2.URL中常见的协议 (1)HTTP 超文本传输协议,访问的是远程的网络资源,格式是http:// http协议是在网络开发中最常用的协议 (2)file 访问的是本地计算机上的资源,格式是file://(不用加主机地址) (3)mailto 访问的是电子邮件地址,格式是mailto: (4)FTP 访问的是共享主机的文件资源,格式是ftp://   二、HTTP协议 1.HTTP协议简介 不管是移动客户端还是PC端,访问远程的网络资源经常使用HTTP协议 访问百度主页:http://www.baidu.com 获得新浪的微博数据 获得大众点评的团购数据   2.HTTP协议的作用 HTTP的全称是HypertextTransferP

  • 协议——如何制作一个简易的串口通信协议

    =================================版权声明================================= 版权声明:本文为博主原创文章未经许可不得转载  请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我 未经作者授权勿用于学术性引用。 未经作者授权勿用于商业出版、商业印刷、商业引用以及其他商业用途。                      本文不定期修正完善,为保证内容正确,建议移步原文处阅读。                                        

  • 2022-2023-1 20221312 《计算机基础与程序设计》第六周学习总结

    作业信息 班级链接:首页-2022-2023-1-计算机基础与程序设计-北京电子科技学院-班级博客-博客园(cnblogs.com) 作业要求:2022-2023-1《计算机基础与程序设计》教学进程-娄老师-博客园(cnblogs.com) 作业目标:了解数据查找方式以及其中的时间复杂度,学习结构名称,复习巩固C语言语法知识 作业正文:2022-2023-120221312《计算机基础与程序设计》第六周学习总结-20221312付安旭-博客园(cnblogs.com) 教材学习内容总结 学习了数组中各种查找数据的方式,了解了各种代码对应的结构,对C语言语法知识有了进一步巩固。 代码调试中的问题与解决过程 问题1:在进制转化的程序中,最终结果只有第一位会正确展示,其余各位都显示0. 问题1解决方案:经询问前辈和老师,知道了malloc函数在使用过程中,会覆盖所有已经借出的内存,导致原来的赋值被初始化为0。 为了解决该问题,可以事先定义以个较大的数组存储数据,或者先计算位数再借取空间。    不过C99及以上的版本是可以用变量定义数组大小的。这时候也不太需

  • C# 广度优先搜索

     复制   广度优先搜索是一种用于图的查找算法,它主要解决两个问题: 1.从节点S到节点E有路径吗? 2.从节点S到节点E的所有路线中,哪条最短? 广度优先搜索的执行过程中,搜索范围从起点开始逐渐向外延伸,即先检查一度关系,再检查二度关系. 所谓一度关系:我的朋友和我就是一度关系. 所谓二度关系:我的朋友的朋友和我就是二度关系. 以此类推. 曾经不知道在哪里看到过一句话: 解决问题,先确定数据结构,数据结构确定好了,算法自然而然就出来了.不过我觉得我离这个境界还有点远.... 那么这个算法应该用哪种数据结构来存储数据呢? 因为一个节点可以指向多个节点,当然,也可以不指向任何节点.所以我们可以用散列表: Dictionary<T,List<T>>(也许还有其他方式,但是小弟确实不懂,只懂这个) 由于多个节点可以指向同一个节点,自己也可以指向自己,所以在搜索的过程中,对于检查过的节点,我们不能再去检查,否则可能会导致无限循环,因此我们需要一个数据结构来保存搜索过的节点,这个用List<T>或者HashSet<T>

  • Rust学习——使用包、crate和模块管理不断增长的项目

    一、包和Crate 一个包至多只能包含一个库crate 包中可以包含任意多个二进制crate 包中至少包含一个crate,不区分类型 src/main.rs 就是一个与包同名的二进制crate的crate根。 src/bin->二进制crate src/lib.rs->库crate src/main.rc->二进制crate 二、定义模块,以控制作用域与私有性 使用mod关键字定义模块。 沿用家庭关系的比喻,如果一个模块A被包含在模块B中,我们将模块A称为模块B的 子(child),模块B则是模块A的 父(parent)。 三、路径,用于引用模块树中的项 Rust私有性边界:不允许外部代码了解、调用和依赖被封装的实现细节。 若希望创建一个私有函数或构造体,可以使用模块mod。 Rust中默认所有项:函数、方法、结构体、枚举、模块和常量,都是私有的。 可以使用crate开头实现绝对路径使用模块。 也可以使用super开头来构建从父模块开始的相对路径。(类似于../)方便在内嵌较深的函数下引用其他模块的函数。 四、use关键字,将名称

  • -管理沟通那些事儿

    如果说角色认知是管理工作的前提,就像空气一样弥漫在管理者所有的言行举止之中的话,那么管理沟通就恰似管理工作的载体,它就像水一样承载着所有管理工作的正常开展,离开了沟通,所有的工作都将搁浅而无法前行。它是如此重要,以至于我们要花7篇文章来探讨。 今天是第一篇,我们先一起来看看,技术管理者在管理沟通中可以遵循的框架。 “管理三明治”(果见) 管理沟通是个大话题,也是很多公司培训课的重头戏,相信你也参加过不少HR组织的管理沟通课,你感觉怎么样?在管理沟通问题上是否胸有丘壑、游刃有余了呢? 我预计答案并不乐观,因为我对超过500位技术管理者进行过统计,列出12个最常见的管理话题请他们选出自己认为最有挑战的选项,霸占前三位的总是这样三个话题:向上沟通、员工激励和团队凝聚力提升,其中向上沟通几乎是每次调研的榜首。而且,紧随这前三甲之后的,往往就是向下沟通。如果把向上沟通和向下沟通加起来,在不包括横向沟通的情况下,就已经一骑绝尘地把其他话题抛在身后了,可见管理沟通是技术管理者心中当之无愧的“最具挑战管理主题NO.1”。 那么,为什么技术管理者们认为管理沟通是如此地挑战?尤其对于向上沟通会如此地头疼

  • linux sort

    sort是在Linux里非常常用的一个命令,管排序的,集中精力,五分钟搞定sort,现在开始! 1sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。 [rocrocket@rocrocketprogramming]$catseq.txt banana apple pear orange [rocrocket@rocrocketprogramming]$sortseq.txt apple banana orange pear 2sort的-u选项 它的作用很简单,就是在输出行中去除重复行。 [rocrocket@rocrocketprogramming]$catseq.txt banana apple pear orange pear [rocrocket@rocrocketprogramming]$sortseq.txt apple banana orange pear pear [rocrocket@rocrocketprogramming]$sort-useq.txt apple banan

  • LeetCode: Find Peak Element 解题报告

    FindPeakElement   Apeakelementisanelementthatisgreaterthanitsneighbors. Givenaninputarraywhere num[i]≠num[i+1],findapeakelementandreturnitsindex. Thearraymaycontainmultiplepeaks,inthatcasereturntheindextoanyoneofthepeaksisfine. Youmayimaginethat num[-1]=num[n]=-∞. Forexample,inarray [1,2,3,1],3isapeakelementandyourfunctionshouldreturntheindexnumber2. clicktoshowspoilers. Credits:Specialthanksto @ts foraddingthisproblemandcreatingalltestcases. SOLUTION1: 线性查找,时间O(N):

  • session 监听

    1.创建一个session容器用来存放所有的用户,不同浏览器对应不用的session,下面用单例模式来创建session容器 packagecom.limin.framework.util; importjava.util.HashMap; importjavax.servlet.http.HttpSession; importcom.limin.framework.listener.SessionListener; importcom.limin.util.Util; /** *使用单例模式 */ publicclassSessionContext{ privatestaticSessionContextinstance; privateHashMap<String,HttpSession>sessionMap; privateSessionContext(){ sessionMap=newHashMap<String,HttpSession>(); } publicstaticSessionContextgetInstance(){ if(in

  • string,QString,opencv,log4cplus与中文

    #include<iostream> #include<opencv2\opencv.hpp> #include<QtCore/QCoreApplication> #include"LogHelper.h" usingnamespacestd; intmain(intargc,char*argv[]) { cout<<"0.中文"<<endl;//OK LOG_INFO("0.中文");//OK cv::Matmat=cv::imread("D:/图片.bmp");//OK strings1="1.中文";//断点查看:OK cout<<s1<<endl;//OK QStringqs1(s1.c_str());//断点查看:乱码QStringqs2=QString::fromStdString(s1);//乱码  QStringqs3=QString::fromLocal8Bit(s1.c_str());//OK QStrings2="2.中文";//断点查看:乱码 cout<<s2

  • 聊聊 PC 端自动化最佳方案 - Pywinauto

    1.前言 大家好,我是安果! 上一篇文章,聊到PC端的一种自动化方案:WinAppDriver 聊聊PC端自动化最佳方案-WinAppDriver 有小伙伴后台给我留言,说「 pywinauto 」作为WinAppDriver的替代方案,也能完美完成PC端的自动化 2.介绍 Pywinauto,完全由Python构建的一个模块,可以用于自动化Windows 上的GUI应用程序 同时,它支持鼠标、键盘操作,在元素控件树较复杂的界面,可以辅助我们完成自动化操作 项目地址:https://github.com/pywinauto/pywinauto 支持的应用为下面2大类: Win32API 包含MFC、VB6、VCL、simpleWinFormscontrolsandmostoftheoldlegacyapps MSUIAutomation 包含WinForms、WPF、Storeapps、Qt5,browsers 其中 win32API的 backend为「 win32 」 MSUIAutomation的backen

相关推荐

推荐阅读