Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码,同时又具有闭包和动态语言中的其他特性。
Groovy是JVM的一个替代语言(替代是指可以用 Groovy 在Java平台上进行 Java 编程),使用方式基本与使用 Java代码的方式相同,该语言特别适合与Spring的动态语言支持一起使用,设计时充分考虑了Java集成,这使 Groovy 与 Java 代码的互操作很容易。(注意:不是指Groovy替代java,而是指Groovy和java很好的结合编程。
类型对于变量,属性,方法,闭包的参数以及方法的返回类型都是可有可无的,都是在给变量赋值的时候才决定它的类型, 不同的类型会在后面用到,任何类型都可以被使用,即使是基本类型 (通过自动包装(autoboxing)). 当需要时,很多类型之间的转换都会自动发生,比如在这些类型之间的转换: 字符串(String),基本类型(如int) 和类型的包装类 (如Integer)之间,可以把不同的基本类型添加到同一数组(collections)中。
闭包就是可以使用参数的代码片段,每个闭包会被编译成继承groovy.lang.Closure类的类,这个类有一个叫call方法,通过该方法可以传递参数并调用这个闭包.它们可以访问并修改在闭包创建的范围内的变量,在闭包内创建的变量在闭包被调用的范围内同样可以被引用, 闭包可以保存在变量中并被作为参数传递到方法中。
Groovy 语法与Java 语言的语法很相似,虽然 Groovy 的语法源于Smalltalk和Ruby这类语言的理念,但是可以将它想像成 Java 语言的一种更加简单、表达能力更强的变体。(在这点上,Ruby与 Groovy 不同,因为它的语法与 Java 语法差异很大。)
许多 Java 开发人员喜欢 Groovy 代码和 Java 代码的相似性。从学习的角度看,如果知道如何编写 Java 代码,那就已经了解 Groovy 了。Groovy 和 Java 语言的主要区别是:完成同样的任务所需的 Groovy 代码比 Java 代码更少。
Groovy类和java类一样,完全可以用标准java bean的语法定义一个Groovy类。但作为另一种语言,可以使用更Groovy的方式定义类,这样的好处是,可以少写一半以上的javabean代码。
如前面所言,Groovy的默认访问修饰符就是public,如果Groovy类成员需要public修饰,则根本不用写它。
同样前面也说过,Groovy也不关心变量和方法参数的具体类型。
在很多ide(如eclipse)早就可以为程序员自动产生getter/setter方法了,在Groovy中,不需要getter/setter方法–所有类成员(如果是默认的public)根本不用通过getter/setter方法引用它们(当然,如果一定要通过getter/setter方法访问成员属性,Groovy也提供了它们)。
不再需要程序员声明任何构造函数,因为实际上只需要两个构造函数(1个不带参数的默认构造函数,1个只带一个map参数的构造函数–由于是map类型,通过这个参数可以构造对象时任意初始化它的成员变量)。
Groovy中,方法不需要return来返回值。
java 项目中使用 Groovy 引入其依赖即可
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
<version>4.0.2</version>
</dependency>
创建一个以 .groovy 为后缀的文件,我们可以在这文件中像开发java代码一样简单的去使用 groovy,并且 groovy 提供的语法更加简洁。
我们可以完全像开发 Java 代码一样去编写 Groovy,也可以根据 Groovy 的语法来简化编写。
class Example {
static void main(String[] args) {
// 使用 println 就可打印输出,并且类和方法默认就是public,可以不用写
println('Hello World');
}
}
运行
Hello World
和 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
和 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 编写中可以,可以省略分号符
和 Java 一样,标识符就是变量名,声明规则和 Java 一样,可以以字母开头,美元或下划线。但不能以数字开头。
大部分关键字和 Java 中的用法一样
as | assert | break | case |
---|---|---|---|
catch | class | const | continue |
def | default | do | else |
enum | extends | false | Finally |
for | goto | if | implements |
import | in | instanceof | interface |
new | pull | package | return |
super | switch | this | throw |
throws | trait | true | try |
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的范围。
class Example {
static void main(String[] args) {
def range = 5..10; // 定义一个5~10的范围
println(range); // 打印范围
println(range.get(2)); // 取范围中是数据
}
}
运行
[5, 6, 7, 8, 9, 10]
7
可以发现,范围变量,本质就是封装了一层数组。在操作时,通过其下标进行存取。
运算符优先级
运算符 | 名称 |
---|---|
++ ,-- ,+ ,- |
预增/减(自增/减),一元加,一元减 |
* , / , % |
乘法,除法,取模 |
+ ,- |
加法,减法(二元) |
== ,!= , <=> |
等于,不等于,比较运算符 |
& |
二进制/位运算符与 |
^ |
二进制/位异或 |
` | ` |
! | 逻辑非 |
&& |
逻辑与 |
` | |
= ,+= ,-= ,*= ,/= ,%= ,**= |
各种赋值运算符 |
Groovy 中的循环和 Java 中一样,包含循环跳出和结束循环等
while、for、break、continue
不同之处
在 Java 中我们常常使用foreach
来遍历
for(String str : strList){
...
}
而在 Groovy 中提供了for in
语句,其使用方法和 Java 一样,只是关键字不同
for(def str in strList){
println(str);
}
Groovy 中的条件语句和 Java 中的一样,其关键字如下
if、else、switch
等
包括其嵌套使用等
在 Groovy 中,方法的返回类型可以是 def 类型,而且在定义方法参数时,可以不必显示的定义参数的具体类型。
其方法修饰符默认为 public,可以添加其它修饰符,和 Java一样,默认 public 可以不用写
def methodName() {
//Method code
}
def methodName(parameter1, parameter2, parameter3) {
// Method code goes here
}
具体示例
class Example {
static void sum(int a,int b) {
int c = a+b;
println(c);
}
static void main(String[] args) {
sum(10,5);
}
}
输出 15
在 Groovy 中,定义方法参数时,可以指定其参数的默认值,如果在调用此方法时有传入值,则使用传入值,否则使用默认值
class Example {
static void sum(int a,int b = 5) {
// 参数b的默认值为5
int c = a+b;
println(c);
}
static void main(String[] args) {
sum(6); // 我们在调用时,只传入了一个参数
}
}
输出 11
因为参数 b 有默认值,所以我们在使用时,可以选择传或不传参数 b
如果调用时,传入参数 b,则在计算时,会使用我们传入的值
class Example {
static void sum(int a,int b = 5) {
int c = a+b;
println(c);
}
static void main(String[] args) {
sum(6,6); // 传入参数b
}
}
输出 12
无参调用
class test {
static void main(String[] args){
sun() // 无参调用
}
static void sun(a = 1,b = 2){
println(a+b)
}
}
输出 3
**注意:**如果方法没有默认值,在调用时,必须传入参数。
Groovy 的IO除了使用 Java 的 API 以外,还提供了辅助类供我们使用
标准 Java 类
可以使用 Groovy 提供的 File 类中的 eachLine 方法来快速读取文本文件的每一行
import java.io.File
class Example {
static void main(String[] args) {
new File("E:/Example.txt").eachLine {
line -> println "line : $line"
}
}
}
如果想将文件的整个内容作为字符串获取,可以使用文件类的 text 属性
class Example {
static void main(String[] args) {
File file = new File("E:/Example.txt")
println file.text
}
}
在写入文件时,也提供了对应的写入辅助
import java.io.File
class Example {
static void main(String[] args) {
new File('E:/','Example.txt').withWriter('utf-8') {
writer -> writer.writeLine 'Hello World'
}
}
}
可以通过 File 类的 length 属性进行获取
class Example {
static void main(String[] args) {
File file = new File("E:/Example.txt")
println "The file ${
file.absolutePath} has ${
file.length()} bytes"
}
}
class Example {
static void main(String[] args) {
def file = new File('E:/')
println "File? ${
file.isFile()}"
println "Directory? ${
file.isDirectory()}"
}
}
// 输出
File?
Directory? True
class Example {
static void main(String[] args) {
def file = new File('E:/Directory')
file.mkdir() // 如果文件夹不存在则创建
}
}
class Example {
static void main(String[] args) {
def file = new File('E:/Example.txt')
file.delete()
}
}
class Example {
static void main(String[] args) {
def src = new File("E:/Example.txt")
def dst = new File("E:/Example1.txt")
dst << src.text
}
}
复制文件使用 <<
特殊符号即可进行复制,
代码解释:将创建文件 Example1.txt,并将文件 Example.txt 的所有内容复制到此文件。
class Example {
static void main(String[] args) {
def rootFiles = new File("test").listRoots() // 获取驱动器列表
rootFiles.each {
file -> println file.absolutePath // 遍历并打印
}
}
}
class Example {
static void main(String[] args) {
new File("E:/Temp").eachFile() {
// 使用 eachFile 获取目录下的所有文件
file->println file.getAbsolutePath()
}
}
}
class Example {
static void main(String[] args) {
new File("E:/temp").eachFileRecurse() {
// 使用 eachFileRecurse 方法
file -> println file.getAbsolutePath()
}
}
}
Groovy中的字符串可以用单引号('),双引号(“)或三引号(" ')括起来。
class test {
static void main(String[] args){
String a = 'Hello Single';
String b = "Hello Double";
String c = "'Hello Triple' + 'Multiple lines'"; // 注意如果单引号在外则不是字符串拼接
println(a);
println(b);
println(c);
}
}
输出
Hello Single
Hello Double
'Hello TripleMultiple lines'
也可以使用占位符去拼接字符串
name = 'Wangfang'
age = '18'
// 占位符拼接的用法
print("my name is ${
name},my age is ${
age}.")
可以直接使用字符下标获取字符串中的字符
class Example {
static void main(String[] args) {
String sample = "Hello world";
println(sample[4]); // 打印第5个字符
// 打印字符串最后一位字符
println(sample[-1]);
println(sample[1..2]);// 打印索引 1 ~ 2 的字符
println(sample[4..2]);// 反向打印,从索引4到索引2
}
}
输出
o
d
el
oll
Groovy 中的一个列表中的数据可以是任意类型。这 java 下集合列表有些不同,java 下的列表是同种类型的数据集合。
Groovy 列表可以嵌套列表。如 [1,2,[3,4,5],“aaa”]
Groovy 列表内置有反转方法 reverse()。调用 List.reverse() 可以实现列表反转。Groovy 列表内置有排序方法 sort()。调用 List.sort() 可以实现列表排序。
添加
def list1 = [100, 101]
def list2 = [ 99,98,1]
println list2.plus(list1) //输出结果: [100, 101, 99, 98,1]
// list2.plus(list1) 也可以写成 list2 + list1
删除
def list1 = [12, 13]
def list2 = [11, 2, 33, 12, 13, 16]
println list2.minus(list1) //输出结果: [11, 2, 33, 16]
//list2.minus(list1) 也可以写成 list2 - list1
在 Groovy 除了使用 Java 的Map集合,还可以显示的定义映射
['TopicName':'Lists','TopicName':'Maps'] //具有TopicName作为键的键值对的集合及其相应的值。
[:] // 空映射。
Groovy 中,使用正则表达式可以使用 ~
符号来判断
'Groovy' =~ 'Groovy'
'Groovy' =~ 'oo'
'Groovy' ==~ 'Groovy'
'Groovy' ==~ 'oo'
'Groovy' =~ '∧G'
'Groovy' =~ 'G$'
'Groovy' =~ 'Gro*vy' 'Groovy' =~ 'Gro{2}vy'
在 Groovy 中可以定义用 traits 修饰的类,表示特征类,它可以看作是有默认实现和状态的接口
trait Marks {
void DisplayMarks() {
println("Display Marks");
}
}
我们可以使用 implement 关键字以类似于接口的方式实现 trait
trait Marks {
void DisplayMarks() {
// 特征里有一个实现方法
println("Display Marks");
}
}
class Student implements Marks {
// 可以像实现接口一样实现 trait 类
int StudentID
int Marks1;
}
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
st.Marks1 = 10;
println(st.DisplayMarks());
}
}
Traits 类可以实现接口
interface Total {
// 接口
void DisplayTotal()
}
trait Marks implements Total {
// trait实现接口
void DisplayMarks() {
println("Display Marks");
}
void DisplayTotal() {
// 实现接口的方法
println("Display Total");
}
}
class Student implements Marks {
// 普通类实现trait类
int StudentID
int Marks1;
}
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
st.Marks1 = 10;
println(st.DisplayMarks());
println(st.DisplayTotal());
}
}
在 trait 类中也可以定义属性
interface Total {
void DisplayTotal()
}
trait Marks implements Total {
//trait类
int Marks1;
void DisplayMarks() {
this.Marks1 = 10;
println(this.Marks1);
}
void DisplayTotal() {
println("Display Total");
}
}
trait Marks {
void DisplayMarks() {
println("Marks1");
}
}
trait Total {
void DisplayTotal() {
println("Total");
}
}
class Student implements Marks,Total {
// 具体类可以实现多个 特征类
int StudentID
}
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
println(st.DisplayMarks());
println(st.DisplayTotal());
}
}
特征类可以继承
trait Marks {
void DisplayMarks() {
println("Marks1");
}
}
trait Total extends Marks {
//Total 继承 Marks
void DisplayMarks() {
println("Total");
}
}
class Student implements Total {
int StudentID
}
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
println(st.DisplayMarks());
}
}
Groovy 的闭包,就是一个匿名的代码块,并且可以作为参数
class Example {
static void main(String[] args) {
def clos = {
println "Hello World"}; // 简单的闭包
clos.call();
}
}
// 输出
Hello World
上面的例子中,使用{代码块}
声明的被称为闭包,变量标识符可以通过 call 方法执行代码块
闭包代码块中,可以包含形式参数
class Example {
static void main(String[] args) {
def clos = {
param -> println "Hello ${
param}"};
clos.call("World");
}
}
还可以使用下面这种方式来进行定义,可以得到相同的结果
class Example {
static void main(String[] args) {
def clos = {
println "Hello ${
it}"};
clos.call("World");
}
}
it
参数,是Groovy定义的关键字,它被称为隐式单个参数
在闭包代码块中,我们还可以使用变量,通过${变量名}
来使用
class Example {
static void main(String[] args) {
def str1 = "Hello";
def clos = {
param -> println "${
str1} ${
param}"}
clos.call("World");
// 改变star1的值
str1 = "Welcome";
clos.call("World");
}
}
输出
Hello World
Welcome World
当我们改变str1变量值的时候,其内部的获取到的值,也会跟着改变。
闭包可以用作方法的参数
class Example {
def static Display(clo) {
// 执行闭包并传入参数
clo.call("Inner");
}
static void main(String[] args) {
def str1 = "Hello";
def clos = {
param -> println "${
str1} ${
param}" }
clos.call("World");
// 将闭包传入到方法
Example.Display(clos);
}
}
输出
Hello World
Hello Inner
集合中,我们可以通过.each
函数来传入一个闭包,并将闭包应用于集合中每一个元素
class Example {
static void main(String[] args) {
def lst = [11, 12, 13, 14];
lst.each {
println it} // 传入闭包,it为单个隐式参数
}
}
输出
11
12
13
14
class Example {
static void main(String[] args) {
def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"]
mp.each {
println it}
mp.each {
println "${
it.key} maps to: ${
it.value}"}
}
}
输出
TopicName = Maps
TopicDescription = Methods in Maps
TopicName maps to: Maps
TopicDescription maps to: Methods in Maps
在Groovy 中对异常处理的写法更为宽松:如果没有在该代码块内通过 try-catch 处理异常,那么该异常就会自动地向上级抛出,且无需在函数声明中使用 throws
主动定义它们。
在java中判断为空
String maybeNull = "I'm Java";
if(maybeNull != null){
System.out.println(nullString.length());
}
而在 Groovy 中可以使用?.
操作符来解决
String maybeNull = 'I\'m groovy'
print(maybeNull?.length())
在编写bean时,可以使用def来表明其属性,不推荐
class Student_{
final name
def age
Student_(name,age){
this.name = name
this.age = age
}
}
s = new Student_('Wang Fang',23) //在使用时,会自动推导其属性的类型
class Student_{
String name
Integer age
}
// 没有实现 Student_(name,age) 构造器,但是可以直接使用
stu1 = new Student_(name: "Wang Fang",age: 12)
// 同样,我们也没有手动实现 Student_(name) 构造器。
stu2 = new Student_(name:"Wang Fang")
在未指定构造器的情况下我们可以使用键值对的形式去构建对象。
如果没有提供构造器,我们不能使用下面的方式进行创建对象。
stu1 = new Student_("Wang Fang",12)
stu2 = new Student_("Wang Fang")
除非手动补上其对应的构造器
def swap(x, y) {
return [y, x]
}
Integer a, b
a = 10
b = 50
// 通过多重赋值实现了两数交换
(a, b) = swap(a, b)
print("a=$a,b=$b")
如果方法 ( 函数 ) 返回的是一个数组,那么 Groovy 支持使用多个变量接收数组内的元素内容。
如果接收的变量和返回值个数不匹配时,Groovy会进行如下操作
在java中实现一个接口方法可以通过匿名或者Lambda的方式来实现
Calculator<Integer> calculator = new Calculator<Integer>() {
// 匿名
@Override
public Integer add(Integer a, Integer b) {
return a + b;
}
};
Calculator<Integer> calculator = (a, b) -> a + b; // Lambda
在Groovy中使用如下方法来实现
def a = {
a,b ->return a+b} as Calculator<Integer>
如果接口是多方法,则可以通过封装一层Map来实现
interface Calculator<T> {
T add(T a, T b)
T sub(T a, T b)
}
def cal = [ //不同方法提供不同实现,通过as关键字来指定接口
add: {
a, b -> a + b },
sub: {
a, b -> a - b }
] as Calculator<Integer>
def c = cal.sub(1,2) //调用方法
print(c)
@Canonical
// 如果不想打印 id 和 score,可以:
// @Canonical(excludes="id,score")
class Student {
Integer id
String name
Integer age
String major
Integer score
}
// 如果没有此注解,打印的则是 Student@Hashcode
// 如果有注解,打印的则是 Student(1,"Wang Fang",20,"CS","score")
print new Student(id: 1,name:"Wang Fang",age: 20,major: "CS",score: 90.0d)
使用 @Delegate
注解,在 Groovy 中实现方法委托非常容易。委托是继承以外的另一种代码复用的思路。在下面的代码块中,Manager 通过注解将 work()
方法委托给了内部的 worker 属性:
class Worker{
void work(){
print("worker is working exactly.")
}
}
// Manager 获得了 Worker 的公开方法,尽管 worker 属性本身是 private.
class Manager{
@Delegate private Worker worker = new Worker() // 委托类
}
// 检查 Manager 实例有没有 work 方法,没有就去委托 worker 执行此方法。
new Manager().work() // 调用委托类的方法
在java中创建不可变对象得使用final关键字,Groovy可以使用@Immutable注解来实现final修饰
@Immutable // 修饰student类为不可变
class Student_{
String id
String name
}
def s = new Student_(id:"0001",name:"Wang Fang")
print s
允许我们创建对象时,忽略new关键字
class Student{
String id
String name
}
class Teacher{
String id
String name
}
@Newify(Student)
def getStudent(){
// 在函数内部创建 Student 时,可以省略掉 new 关键字。
Student(id:"0001",name: "Wang Fang")
}
// 多个类型使用数组的形式排列。
@Newify([Student,Teacher])
static def getStudentAndTeacher(){
[Student(id:"0001",name:"Wang Fang"),Teacher(id: "0002",name:"Cheng Yu")]
}
// 懒加载的单例模式,lazy 项是可选的。
@Singleton(lazy = true)
class TheUnique{
{
println "created only once"
}
}
// 通过 .instance 调用这个单例对象。
TheUnique.instance
在 Java 中,==
可以比较两个基本数据类型的值,或者比较两个引用类型的 HashCode。
而在 Groovy 当中,这两者的混乱程度有所加剧:Groovy 的 ==
相当于是 Java 的 .equals()
方法或者是 compareTo()
方法 (见运算符重载的那个表格),而 Java 原始的 ==
语义在 Groovy 中变成了 is()
方法。
str1 = "111"
str2 = "222"
// 相当于是 Java 语义中的 str1 == str2
str1.is(str2)
// 相当于是 Java 语义中的 str1.equals(str2)
str1 == str2
如果比较的类实现了 Compareble
接口,那么 ==
的语义优先会选择 compareTo()
方法而非 equals()
方法。
文章浏览阅读1.1w次,点赞7次,收藏34次。vue-grid-layout的使用、实例、遇到的问题和解决方案_vue-grid-layout
文章浏览阅读218次。然后连接一个数据源,就会在下面自动产生一个添加附件的组件。把这个控件复制粘贴到页面里,就可以单独使用来上传了。插入一个“编辑”窗体。_powerapps点击按钮上传附件
文章浏览阅读264次。(1) Abstraction (抽象)(2) Polymorphism (多态)(3) Inheritance (继承)(4) Encapsulation (封装)_"object(cnofd[\"ofdrender\"])十条"
文章浏览阅读133次。删除node_modules,重新npm install看是否成功。在 package.json 文件中的 scripts 中加入。修改你的第三方库的bug等。然后目录会多出一个目录文件。_修改 node_modules
文章浏览阅读883次。【代码】【】kali--password:su的 Authentication failure问题,&sudo passwd root输入密码时Sorry, try again._password: su: authentication failure
文章浏览阅读1w次,点赞13次,收藏97次。整理5个优秀的微信小程序开源项目。收集了微信小程序开发过程中会使用到的资料、问题以及第三方组件库。_微信小程序开源模板
文章浏览阅读128次。Centos7最简搭建NFS服务器_centos7 搭建nfs server
文章浏览阅读1.2k次,点赞2次,收藏3次。前言mybatis在持久层框架中还是比较火的,一般项目都是基于ssm。虽然mybatis可以直接在xml中通过SQL语句操作数据库,很是灵活。但正其操作都要通过SQL语句进行,就必须写大量的xml文件,很是麻烦。mybatis-plus就很好的解决了这个问题。..._mybaitis-plus ruledataobjectattributemapper' and 'com.picc.rule.management.d
文章浏览阅读325次。EECE 1080C / Programming for ECESummer 2022Laboratory 4: Global Functions PracticePlagiarism will not be tolerated:Topics covered:function creation and call statements (emphasis on global functions)Objective:To practice program development b_eece1080c
文章浏览阅读53次。被同机房早就1年前就学过的东西我现在才学,wtcl。设要求的数为\(x\)。设当前处理到第\(k\)个同余式,设\(M = LCM ^ {k - 1} _ {i - 1}\) ,前\(k - 1\)个的通解就是\(x + i * M\)。那么其实第\(k\)个来说,其实就是求一个\(y\)使得\(x + y * M ≡ a_k(mod b_k)\)转化一下就是\(y * M ...
文章浏览阅读1.3k次。首先,问题是如何出现的?晚上复查代码,发现一个activity没有调用自己的ondestroy方法我表示非常的费解,于是我检查了下代码。发现再finish代码之后接了如下代码finish();System.exit(0);//这就是罪魁祸首为什么这样写会出现问题System.exit(0);////看一下函数的原型public static void exit (int code)//Added ..._android 手动杀死app,activity不执行ondestroy
文章浏览阅读894次。Q: SylixOS 版权是什么形式, 是否分为<开发版税>和<运行时版税>.A: SylixOS 是开源并免费的操作系统, 支持 BSD/GPL 协议(GPL 版本暂未确定). 没有任何的运行时版税. 您可以用她来做任何 您喜欢做的项目. 也可以修改 SylixOS 的源代码, 不需要支付任何费用. 当然笔者希望您可以将使用 SylixOS 开发的项目 (不需要开源)或对 SylixOS 源码的修改及时告知笔者.需要指出: SylixOS 本身仅是笔者用来提升自己水平而开发的_select函数 导致堆栈溢出 sylixos