mvel语法指南_日语语法指南app

mvel语法指南_日语语法指南appmvel受到了java语法的启发,但是存在一些根本性的差异,mvel旨在使其成为更有效的表达式语言.比如直接支持集合、数组和字符串匹配,正则表达式的运算操作等.      mvel2.x有以下几个部分组成: PropertyexpressionsBooleanexpressionsMethodinvocationsVariableassignmentsFunctionde

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

        mvel受到了java语法的启发,但是存在一些根本性的差异,mvel旨在使其成为更有效的表达式语言.比如直接支持集合、数组和字符串匹配,正则表达式的运算操作等.

        mvel2.x有以下几个部分组成: 
  • Property expressions
  • Boolean expressions
  • Method invocations
  • Variable assignments
  • Function definitions
目录:
     1:基本语法
     2:操作运算
     3:值测试
     4:内联list,maps,arrays 
     5:属性导航
     6:字面量值
     7:字面类型
     8:控制流程
     9:



1:基本语法:
  
1:简单的属性表达式:
     用于计算布尔表达式
     
user.name == 'John Doe'

Jetbrains全家桶1年46,售后保障稳定

    和java一样,mvel支持运算符优先级规则的完整的策略,包括使用括号的能力来控制执行顺序。
(user.name == 'John Doe') && ((x * 2) - 1) > 20

     2:复合表达式
     您可以编写脚本可以用任意数量的语句,用分号表示终止声明。
statement1; statement2; statement3

    3:返回值:
     mvel使用最后一个值最为返回值,开发人员不必显示的指定返回值,默认为最后一个值最为返回


2:mvel2.0的操作运算

下面给出的是mvel的现有的所有操作运算符合运算逻辑

Unary Operators

Operator

Description

Example

new

Object instantiation

new String(“foo”)

with

Block WITH Operator. Perform multiple operations on a single object instance

with (value) { name = ‘Foo’, age = 18, sex = Sex.FEMALE }

assert

Assert that a value is true or fail with an AssertionError

assert foo != null

isdef

Tests whether or not a variable is defined within the scope

isdef variableName

!

Boolean negation operator

!true == false

Comparison Operators

Operator

Description

Example

==

Equality Check.  Checks to see if the values on both sides of the operator are equal.  Unlike Java, this is not an identity check.  

“foo” == “foo” is true 

!=

Not Equals Check.  Checks to see if the values on both sides of the operator are not equal. 

“foo” == “bar” is false 

>

Greater Than Check.  Checks to see if the value on the left side of the operator is greater than than value on the right. 

2 > 1 is true 

<

Less Than Check.  Checks to see if the value on the left side of the operator is less than value on the right. 

1 < 2 is true 

>= 

Greater Than or Equal.  Checks to see if the value on the left hand side is greater than or equal to the value on the right. 

1 >= 1 is true 

<=

Less Than or Equal.  Checks to see if the value on the left hand side is less than or equal to the value on the right. 

2 <= 2 is true 

contains

Value Containment Check.  Checks to see if the value on the left contains the value on the right.  For more details on how this operator works, see Contains Operator 

var contains “Foo” 

is orinstanceof

Type Checking Operator.  Checks to see if the value on the left is a member of the class on the right.  

var instanceof Integer 

strsim

String Similarity Check.  Compares to strings and returns a similarity between them as a percentage. See: String Similarity Check

“foobie” strsim “foobar” 

soundslike

Soundex Check.  Performs a soundex comparison between two strings. See: Soundex

“foobar” soundslike “fubar” 

Logical Operators

Operator

Description 

Example

&&

Logical AND.  Checks to see that the values on both sides of the operator are true. 

foo && bar 

||

Logical OR.  Checks to see if either the value on the left or the right is true. 

foo || bar 

or 

Chained OR.  Checks a sequence of values for emptinessand returns the first non-empty value. (This operator, or at least it’s equivalent functionality, is referred to as the “elvis operator” in other languages) 

foo or bar or barfoo or ‘N/A’ 

~=

Regular Expression Match.  Checks to see if the value on the left matches the regular expression on the right. 

foo ~= ‘[a-z].+’

Bitwise Operators

Operator

Description 

Example 

&

Bitwise AND. 

foo & 5

|

Bitwise OR. 

foo | 5

^

Bitwise XOR. 

foo ^ 5

Arithmetic Operators

Operator

Description 

Example

+ 

Addition.  Adds the value on the left to the value on the right 

1 + 2 

Subtraction.  Subtracts the value on the right from the value on the left 

2 – 1 

/

Division.  Divides the number on the left by the number on the right 

2 / 1 

* 

Multiplication.  Multiples the number on the left by the number on the right 

1 * 2 

% 

Modulus.  Divides the number on the left by the number on the right and returns the remainder. 

2 % 1 

Other Operators

Operator

Description 

Example 

+

String Concatenation.  Overloaded operator for concatenating two strings together. 

“foo” + ;bar” 

#

Concatenation Operator.  Concatenates two literals as strings. 

1 # 2returns “12” 

in

Projection/Fold. Projects across a collection.  See:Projections and Folds

(foo in list)

= 

Assignment.  Assigns the value on the right to the variable on the left. 

var = “foobar” 



3:值测试

在mvel中所有的比较都是值比较而不是比较句柄,所有foo==’bar’和java中的equals是相同的

1:判断值是否为emptiness

MVEL提供了一个特殊的字符来表示值为emptiness的情况,叫作empty,如:foo == empty,若foo满足emptiness的任何条件,这个表达式值都为true

For example:

foo == empty

若foo满足emptiness的任何条件,这个表达式值都为true


2:测试null
     mvel中可以使用null或者nil来进行空值判断
foo == null;
foo == nil; // same as null


3:强制转换
     右边的值会强制转换为左边的值在比较的时候:
"123" == 123;

结果为true,因为在比较的时候123被强制转换成string在进行值比较


4:内置集合

mvel可以通过简单的语法创建集合

['Bob' : new Person('Bob'), 'Michael' : new Person('Michael')]


以上代码效果和下面一样
Map map = new HashMap();
map.put("Bob", new Person("Bob"));
map.put("Michael", new Person("Michael"));

这是一个非常强大的方式来表达MVEL内的数据结构。你可以在任何地方使用这些构造,比如作为方法的参数:

something.someMethod(['foo' : 'bar']);


     

Lists

列表用下面的格式来描述: [item1, item2, …]

For example:

["Jim", "Bob", "Smith"]

Maps

Map用下面的格式来描述: [key1 : value1, key2: value2, …]

For example:

["Foo" : "Bar", "Bar" : "Foo"]

Arrays

数组用下面的格式来描述{item1, item2, …}

For example:

{"Jim", "Bob", "Smith"}

数组的强制转换
你可以进行如下操作:
     
foo.someMethod({1,2,3,4});

正如你看到的,虽然你没有定义数组的类型,但是在调用foo方法的时候,会进行转换,比如foo的参数为int[],表达式会进行相应的转换.

5:属性访问

MVEL属性访问遵循其他语言,比如Groovy OGNL,EL等的获取属性对象。不像其他语言需要取决于底层的访问方法,MVEL提供了一个单一的、统一的语法来访问属性,map,list,等等。

在java中,我们通过以以下方式获取数据
user.getManager().getName();

在mvel中你可以使用如下方式
user.manager.name

你还可以进行控制空值

在java中:
if (user.manager != null) { return user.manager.name; } else { return null; }

在mvel中

user.?manager.name


访问arraylist
mvel中
user[6]

jave中:
user.get(6)


访问map:
mvel中
user[“foobar”]

java中
user.get(foobar)

For Maps that use a String as a key, you may use another special syntax:


user.foobar
.

当Map的key是String类型时,还可以使用特殊的方式来访问,如:user.foobar,也就是允许你把map本身看成一个虚拟的对象,来访问其属性


字符串作数组

为了能使用属性的索引(迭代也是如此),所有的字符串都可以看成是一个数组,在MVEL中你可以用下面的方式来获取一个字符串变量的第一个字符:

foo = “My String”;
foo[0]; // returns ‘M’
6 MVEL 2.0 Literals

A literal is used to represent a fixed-value in the source of a particular script.

String literals

在脚本语言中,一段文字用来代表一个固定的值 

字符串常量:

字符串常量可以用一对单引号或一对双引号来界定。如:

"This is a string literal"
'This is also string literal'

字符串中的特殊字符

  • \\ – Double escape allows rendering of single backslash in string.
  • \n – Newline
  • \r – Return
  • \u#### – Unicode character (Example: \uAE00)
  • \### – Octal character (Example: \73)

数字常量 

整数可以表示为十进制(基数为10),8进制(基数为8),或十六进制(基数为16)。

一个十进制数字,不从零开始(相对于8进制、16进制而言),可以表示任意数,如:125

125 // decimal

一个八进制数,以0为前缀,后面跟着0到7内的数字

0353 // octal

一个十六进制,以0X为前缀,后面可以跟着0-9,A-F范围内的数字

0xAFF0 // hex

浮点常量

A floating point number consists of a whole number and a factional part denoted by the point/period character, with an optional type suffix.

10.503 // a double
94.92d // a double
14.5f // a float

二进制常量

You can represent BigInteger and BigDecimal literals by using the suffixes B and I(uppercase is mandatory).

104.39484B // BigDecimal
8.4I // BigInteger

布尔常量

Boolean literals are represented by the reserved keywords true and false.

Null 常量

The null literal is denoted by the reserved keywords null or nil.


7类型声明:
     和java类似

访问内部类:$
           org.proctor.Person$BodyPart 


8:控制流程

if和else 和java相同
if (var > 0) {
   System.out.println("Greater than zero!");
}
else if (var == -1) { 
   System.out.println("Minus one!");
}
else { 
   System.out.println("Something else!");
}


支持三目运算符
var > 0 ? "Yes" : "No";



嵌套的三目运算
var > 0 ? "Yes" : (var == -1 ? "Minus One!" : "No")

迭代:

count = 0;
foreach (name : people) {
   count++;
   System.out.println("Person #" + count + ":" + name);
}
    
System.out.println("Total people: " + count);

支持字符串
     
str = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;
foreach (el : str) {
   System.out.print("[" + el + "]"); 
}
输出结果:
[A][B][C][D][E][F][G][H][I][J][K][L][M][N][O][P][Q][R][S][T][U][V][W][X][Y][Z]

支持数字:

foreach (x : 9) { System.out.print(x); }

现在也支持for关键字

Do While, Do Until

和java中的一样,MVEL也实现了Do While,Do Until,While和Until意义正好相反。

do { 
   x = something();
} 
while (x != null);

… is semantically equivalent to …

do {
   x = something();
}
until (x == null);

While, Until

MVEL 2.0 implements standard while, with the addition of the inverse until.

while (isTrue()) {
   doSomething();
}

… or …

until (isFalse()) {
   doSomething();
}


9:投影和交集

假设user是一个集合对象,要获取user集合中所有parent的name可以通过以下途径

parentNames = (parent.name in users);


假设user对象有一个集合成员familyMember,你可以访问该集合

familyMembers = (name in (familyMembers in users));

Filters


你可以进行过滤
(doSomeMethod() in listOfThings if $.shouldBeRun())

$代表了前面迭代中的每一个item

你也可以用它作为一个返回成员
($ in fooList if $.name contains 'foobie')

其他例子:
(toUpperCase() in ["foo", "bar"]); // returns ["FOO", "BAR"]
(($ < 10) in [2,4,8,16,32]);       // returns [true, true, true, false, false]
($ in [2,4,8,16,32] if $ < 10);     // returns [2,4,8]

下面是一个快排的实现:
     

/** * Sample MVEL 2.0 Script * "Functional QuickSort" * by: Christopher Michael Brock, Inspired by: Dhanji Prasanna */ import java.util.*; // the main quicksort algorithm def quicksort(list) { if (list.size() <= 1) { list; } else { pivot = list[0]; concat(quicksort(($ in list if $ < pivot)), pivot, quicksort(($ in list if $ > pivot))); } } // define method to concatenate lists. def concat(list1, pivot, list2) { concatList = new ArrayList(list1); concatList.add(pivot); concatList.addAll(list2); concatList; } // create a list to sort list = [5,2,4,1,18,10,15,1,0]; // sort it! quicksort(list);


赋值
MVEL允许你对表达式中的变量进行赋值,以便在运行时获取,或在表达式内部使用。因为MVEL是动态类型语言,所以你不必为了声明一个变量
而指定其类型。当然,你也可以选择指定。
str = "My String"; // valid
String str = "My String"; // valid
与java语言不同的是,当给一个指定类型的变量赋值时,MVEL会提供自动的类型转换(可行的话),如:
String num = 1;
assert num instanceof String && num == "1";
对于动态类型变量而言,你要想对其进行类型转换,你只需要将值转换成相应的类型既可:
num = (String) 1;
assert num instanceof String && num == "1";
十、
MVEL可以使用def或function关键字来定义本地函数。
函数必须是先声明后引用,唯一例外的是递归调用的时候。
1、简单示例
定义函数:
def hello() { System.out.println("Hello!"); }
定义了一个没有参数的函数hello.当调用该函数时会在控制台打印"Hello!". An MVEL-defined function works just like any regular method call,
 and resolution preference is to MVEL functions over base context methods.
hello(); // calls function
2、传参和返回值
函数可以接收参数和返回一个值,看下面的例子:
def addTwo(a, b) { 
   a + b;
}
这个函数会接收两个参数(a和b),然后将这两个变量相加。因为MVEL遵循last-value-out原则,所以
结果将会被返回。因此,你可以这样来使用这个函数:
val = addTwo(5, 2);
assert val == 10;
当然,也可以使用return 关键字来强迫从程序内部返回一个函数值。
3、closures
MVEL支持closure,虽然,其功能与本地java函数没有任何关联。
// define a function that accepts a parameter    
def someFunction(f_ptr) { f_ptr(); }
// define a var
var a = 10;
// pass the function a closure
someFunction(def { a * 10 }); 
十一、Lambda表达式
MVEL允许定义Lambda方法,如下所示:
threshold = def (x) { x >= 10 ? x : 0 }; 
result = cost + threshold(lowerBound);
上面的例子定义了一个Lambda,并将其赋值给变量"threshold".Lambda实质上就是一个用来给变量赋值的函数,也是closure
十二、宏
MVEL支持通过宏定义来用外部的可扩展资源来代替一个标记,这是它的一项基本的功能。这一功能被用来创建封装了解释器的特殊关键字。
一个宏可以由任意多个合法的标识符组成,如:modify
考虑下面的代码:
modify (obj) { value = 'foo' };
这不是一个合法的MVEL表达式,因为毕竟在MVEL中没有modify这个关键字。然而,在JBoss Drools 中会用这一功能通过用字符串
@Modify with替代modify标识符来实现结构变化监听器,
1、org.mvel.Macro 接口:
public interface Macro {
    public String doMacro();
}
这个接口非常简单,执行时方法 doMacro() 会返回一个字符串来代替原有的标记,例如:
Macro modifyMacro = new Macro() {
     public String doMacro() {
         return "@Modify with";
     }
}
2、使用MacroProcessor
MacroProcessor是一个轻量级的快速文本转换器,它使用定义的宏来替代所有相对应的标识符。定义的宏存储在一个Map中,需要匹配的标识符作为
键,宏的实例作为值,然后传递给MacroProcessor,如:
Map<String, Macro> myMacros = new HashMap<String, Macro>();
// Add modifyMacro to the Map
myMacros.put("modify", modifyMacro);
// Create the macro processor
MacroProcessor macroProcessor = new MacroProcessor();
// Add the macro map to the macro processor
macroProcessor.setMacros(myMacros);
// Now we pre-parse our expression
String parsedExpression = macroProcessor.parse(expression);
返回的字符串就会直接传递给MVEL的编译器。
十三、拦截器
MVEL提供了在编译后的表达式里使用拦截器的功能,这对实现监听器或是在表达式内部触发一个外部事件特别有用。声明拦截器用的是@Syntax,
有点像java语言中的注解。拦截器的声明应该放在待封装的语句之前,它可以实现之前或之后的监听器,或二者都实现。例如:
@Intercept
foreach (item : fooItems) { 
   total += fooItems.price;
}
在这个特殊的句子里,拦截器封装了整个的foreach块,因此,如果拦截器实现了之后的监听器,则当foreach循环结束后,拦截动作将被触发。
1、拦截器接口org.mvel.intergration.Interceptor 
public interface Interceptor {
    public int doBefore(ASTNode node, VariableResolverFactory factory);
    public int doAfter(Object exitStackValue, ASTNode node, VariableResolverFactory factory);
}
拦截器接口提供了两个待实现的方法:doBefore和doAfter,下面我们来看一下MVEL运行时传递给这两个方法的参数的含义
2、doBefore
在执行封装的命令前会执行doBefore方法。
org.mvel.ASTNode::node	
 ASTNode句柄是 拦截器内部ASTNode 的一个引用,可以用来获取实际编译后的代码的信息。
org.mvel.integration.VariableResolverFactory::factory
变量分析器工厂提供表达式内当前范围内变量的访问权限。 
3、doAfter
在执行完封装的指令后执行doAfter方法
java.lang.Object::exitStackValue
doAfter方法虽是在语句执行后执行,但却不是在帧结束前。因此,操作结束时留在栈中的任何数据都仍然存在,而且能被拦截器访问。例如:
@Intercept cost += value;
这是一个比较特殊的句子,cost的原值一直保存在栈中,直到整个帧执行完毕,因此,这个值在调用doAfter方法时可以通过exitStackValue访问到。
org.mvel.ASTNode::node
这是传递到doBefore方法中的同一个AST 元素,更多细节参考doBefore方法。
org.mvel.intergration.VariableResolverFactory::factory
同doBefore方法
4、编译器中使用拦截器
为了能是拦截器连到表达式中,必须在编译表达式之前提供拦截器,因此有一点需要注意,拦截器可能不用于MVEL解释器。
拦截器是储存在map里提供给编译器的,map中的键为拦截器的名称,值为拦截器实例。如:
// Create a new ParserContext
ParserContext context = new ParserContext();
Map<String, Interceptor> myInterceptors = new HashMap<String, Interceptor>();
// Create a simple interceptor.
Interceptor myInterceptor = new Interceptor() {
    public int doBefore(ASTNode node, VariableResolverFactory factory) {
        System.out.println("BEFORE!");
    }
    public int doAfter((Object value, ASTNode node, VariableResolverFactory factory) {
        System.out.println("AFTER!");
    }
};
// Now add the interceptor to the map.
myInterceptors.put("Foo", myInterceptor);
// Add the interceptors map to the parser context.
context.setInterceptors(myInterceptors);
// Compile the expression.
Serializable compiledExpression = MVEL.compileExpression(expression, context);
十四、数据类型
MVEL是一种有静态类型的动态类型语言。大部分MVEL使用者都比较倾向于用动态类型,因为它非常简单易用。如:
a = 10; // declare a variable 'a'
b = 15; // declare a variable 'b';
a + b;
1、动态类型与强制转换
像MVEL这种直接与java对象(静态类型)打交道的语言,最重要的一个方面就是强制类型转换。因为MVEL不能对一个java.lang.String对象和一个
java.lang.Integer对象进行数学运算,所以就必须把其中一个的类型转换成另一个的类型。
2、性能考虑
在你的应用中集成一个像MVEL这样的东西,性能考虑是必须的。对于重量级程序加载,强制类型转换超负荷等可以通过缓存和优化器(仅用于预编译
的表达式)来解决。然而,并不是所有的强制类型转换都可以忽略不管,关键要看它是在做什么。
比如,当一个String类型的变量在运行中要看成一个整形变量时,要阻止运行时将字符串转换成整型简直是不可能的,像这种情况,一定要考虑其性能。
3、方法调用
调用方法是强制转换的最重要的一个方面。从根本上讲,你可以直接调用,而无需关心参数是什么。解释器或编译器会分析方法的参数类型,然后确定
要进行哪一种强制转换,如果是重载的方法,它会选择与输入类型最接近的那个方法进行调用,以尽可能的避免强制转换。 
4、数组
数组是强制类型转换中最有趣的一个方面,因为MVEL缺省使用无类型数组(也就是说任何情况下都是Object[]),只有当遇到类型冲突时,才会尝试将
整个数组转换成所需的类型,比如在方法调用传参时。
示例:
myArray = {1,2,3};
// pass to method that accepts String[]
myObject.someMethod(myArray);
在这个例子里,somMethod方法接收字符数组,这在MVEL中不会出错,相反,MVEL会将myArray转换成字符数组。
5、静态类型
静态类型与java类似,只不过默认情况下仍然会进行强制转换。
int num = 10;
这个句子声明了一个整型变量num,这时,MVEL运行时会强制转换类型。比如,声明后赋值一个不合适类型的数据,结果就会出现异常。
num = new HashMap(); // will throw an incompatible typing exception.
但如果是一个可以进行强制类型转换的值时,MVEL就会进行强制转换。
num = "100"; // will work -- parses String to an integer.
6、严格类型
严格类型是编译器的一种可选模式,在这种模式下,所有的类型都必须限定,不管是声明时还是在引用时。
启动严格模式:
当编译一个表达式时,可以通过ParserContext设置setStrictTypeEnforcement(true)将编译器设置成严格模式。
严格类型通过表达式内的具体类型声明或提前告诉转换器确定的类型来完成。例如:
ExpressionCompiler compiler = new ExpressionCompiler(expr);
ParserContext context = new ParserContext();
context.setStrictTypeEnforcement(true);
context.addInput("message", Message.class);
context.addInput("person", Person.class);
compiler.compile(context);
在这个例子中我们通知编译器表达式将接收两个外部输入:message 和 person 及它们的类型。这就使得编译器可以在编译时确定某一
个调用是否是安全的,从而防止了运行时的错误。
7、强类型
强类型是MVEL2.0新引入的概念。强类型模式要求所有的变量必须是限定的类型,从这一点上它与严格类型不同。差别在于严格模式只是在编译时
限定属性和方法调用的类型。
十五、Shell
通过交互式的Shell,你可以直接与MVEL打交道,去探究MVEL的特性。
1、运行Shell
只需运行MVEL的分布式jar包既可运行Shell:java -jar mvel2-2.0.jar
或者,你也可以在你喜欢的IDE中通过配置一个该类的运行环境来运行。
十六、FAQ
1、为什么不能使用.class的引用?
MVEL没有像java中的用来执行类型文件的.class标识符,其实它本身就没有class文件,而只需要通过其名称就可以引用这个类。比如,一个方法
接收一个Class类型作为参数,你可以这样来调用:
// MVEL
someMethod(String);
// Java-equivalent
someMethod(String.class);
事实上,MVEL将.class视作一个普通的bean属性,因此,如果使用String。class,那返回值就会是指向java.lang.Class本身的一个
java.lang.Class 的实例,因此就相当于在java中使用String.class.getClass() .
原理是这样的,MVEL使用动态类型系统,这样类型就被当作普通的变量来看待,而不是像java中限定类文件。所以,MVEL允许class类型作为
一个普通变量来引用,而不像java。
十七、为什么不能用object.class.name的格式?
这是MVEL的一个限制,可能会在将来的某个版本中标记出来,但bean属性不支持对Class的引用。并不是说不能调用Class的方法,你必须使用
限定的方法,像:
someVar.class.getName();     // Yes!
someVar.class.name;          // No!
someVar.getClass().getName() // Yes!
someVar.getClass().name      // No!
这一规定完全限制了java.lang.Class仅可用做某个变量的属性,并限制了MVEL处理类的引用的方式。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/234349.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • django的orm查询方法_django获取get请求参数

    django的orm查询方法_django获取get请求参数前言查找是数据库操作中一个非常重要的技术。查询一般就是使用filter、exclude以及get三个方法来实现。我们可以在调用这些方法的时候传递不同的参数来实现查询需求。在ORM层面,这些查询条件都

  • 手机兼容性测试_浏览器兼容性测试工具

    手机兼容性测试_浏览器兼容性测试工具AndroidApp兼容性测试,是一个比较重要的App评价内容说到测试阶段,兼容性测试主要是对App在各类机型上的兼容、适配等情况进行测试。搞清楚这一阶段的测试重点后,因此,AndroidApp在进行兼容性测试前,一定要做好其前序测试内容,否则兼容性测试效果将会较差。1.机型配置问题Android兼容测试一定要做到宽范围覆盖,如果做不到这个,那么就违背了兼容性测试的目标——测试App在各类机型、系统上的运行是否兼容、适配。因此,兼容性测试必须要在各个机型、系统上对App进行运行、测.

    2022年10月26日
  • svn 服务器创建文件夹,svn服务器创建文件夹

    svn 服务器创建文件夹,svn服务器创建文件夹SVN安装配置与使用在本机上创建文件夹SetUp,右键点击SVNCheckout…弹出如下窗体在上图中URLofRepository:下的文本框输入svnserver中代码库的地址,其他默认,点击OK按钮,就开始签出源代码了说明:上图中CheckoutDepth,有四…文章double2li2011-08-12758浏览量转TortoiseSVN405错误服务器发送了意外的返…

  • 4.2.1越狱

    4.2.1越狱
    这是我见过的最简单的越狱方法了!操作成功,绝对简单可用·
     
     
    越狱并非高不可攀,也并非可怕至极,只要不慌张、耐心,一步步来,就没有问题。
    一、升级到4.2.1系统。
          先在威锋网里下载ipad4.2.1固件http://bbs.weiphone.com/read-htm-tid-862081.html,记住下载后的存放位置,然后把ipad连接到电脑,打开itunes,按住shift键点更新,选择刚下载的固件,把系统升级到4.

  • poetry和poet_poetry定义

    poetry和poet_poetry定义Poetry的基本使用准备工作如果你是在一个已有的项目里使用Poetry,你只需要执行poetryinit命令来创建一个pyproject.toml文件:poetryinit可看到

  • eclipse怎样导入java项目

    eclipse怎样导入java项目打开eclipse,点击file,点击import选择ExistingProjectsintoWorkspace,点击next点击Browse然后选择项目所在的文件夹最后点击Finish导入完成

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号