javac有多聪明?

javac有多聪明?,java,compiler-construction,javac,Java,Compiler Construction,Javac,如果我用javac编译下面的代码,编译器是否足够聪明,只对codeInput.length()进行一次计算,或者通过将受迭代器变量影响的计算放在首位,我是否可能获得更快的程序 // edit: The first character must be an upper case letter, the next four must be // edit: numeric and there must be exactly five characters in total in a product

如果我用javac编译下面的代码,编译器是否足够聪明,只对codeInput.length()进行一次计算,或者通过将受迭代器变量影响的计算放在首位,我是否可能获得更快的程序

// edit: The first character must be an upper case letter, the next four must be 
// edit: numeric and there must be exactly five characters in total in a product
// edit: code.

for (int i = 1; i < 5; i++)
    if (codeInput.length() != 5 || codeInput.charAt(i) < '0' 
        || codeInput.charAt(i) > '9' || codeInput.charAt(0) < 'A'
        || codeInput.charAt(0) > 'Z')
        {if (verbose) System.out.println("Sorry, I don't understand! 
            Use product codes only."); return true;}

//编辑:第一个字符必须是大写字母,接下来的四个字符必须是
//编辑:数字,一个产品中总共必须有五个字符
//编辑:代码。
对于(int i=1;i<5;i++)
如果(codeInput.length()!=5 | | codeInput.charAt(i)<'0'
||codeInput.charAt(i)>'9'| | codeInput.charAt(0)<'A'
||codeInput.charAt(0)>“Z”)
{if(verbose)System.out.println(“对不起,我不明白!
仅使用产品代码。“);返回true;}

是,它将在每次迭代中计算
codeInput.length()。如果
codeInput
是最终的,或者一次只有一个线程可以访问,则编译器可能能够进行优化。否则,
codeInput
可以被当前线程不会注意到的另一个线程更改


所以,程序员决定将
codeInput.length()
转移到循环之外,并利用提高的性能。

是的,它将在每次迭代中评估
codeInput.length()
。如果
codeInput
是最终的,或者一次只有一个线程可以访问,则编译器可能能够进行优化。否则,
codeInput
可以被当前线程不会注意到的另一个线程更改


所以,程序员决定将
codeInput.length()
转移到循环之外,并利用提高的性能;您应该尽可能地编写最简单、最清晰的代码,这样会执行得很好。通常情况下,性能问题的出现使得代码更加清晰更为重要。在你的例子中,我会这样写

static final Pattern CODE = Pattern.compile("[A-Z][0-9]{4}");

if (!CODE.matcher(codeInput).matches()) {
    if (verbose) 
        System.out.println("Sorry, I don't understand! Use product codes only.");
    return true;
}
即使这稍微慢一点,维护IMHO也更清晰、更容易


javac
几乎没有进行优化,它们几乎都是由JIT在运行时执行的

如果我用javac编译下面的代码,编译器是否足够聪明,可以只计算codeInput.length()一次

没有,但是,

或者,通过将受迭代器变量影响的求值放在第一位,我是否有可能获得更快的程序

// edit: The first character must be an upper case letter, the next four must be 
// edit: numeric and there must be exactly five characters in total in a product
// edit: code.

for (int i = 1; i < 5; i++)
    if (codeInput.length() != 5 || codeInput.charAt(i) < '0' 
        || codeInput.charAt(i) > '9' || codeInput.charAt(0) < 'A'
        || codeInput.charAt(0) > 'Z')
        {if (verbose) System.out.println("Sorry, I don't understand! 
            Use product codes only."); return true;}

它不像你会注意到的那样,如果代码运行的时间足够长,JIT就会启动,并且方法将被内联,这样就不需要局部变量;您应该尽可能地编写最简单、最清晰的代码,这样会执行得很好。通常情况下,性能问题的出现使得代码更加清晰更为重要。在你的例子中,我会这样写

static final Pattern CODE = Pattern.compile("[A-Z][0-9]{4}");

if (!CODE.matcher(codeInput).matches()) {
    if (verbose) 
        System.out.println("Sorry, I don't understand! Use product codes only.");
    return true;
}
即使这稍微慢一点,维护IMHO也更清晰、更容易


javac
几乎没有进行优化,它们几乎都是由JIT在运行时执行的

如果我用javac编译下面的代码,编译器是否足够聪明,可以只计算codeInput.length()一次

没有,但是,

或者,通过将受迭代器变量影响的求值放在第一位,我是否有可能获得更快的程序

// edit: The first character must be an upper case letter, the next four must be 
// edit: numeric and there must be exactly five characters in total in a product
// edit: code.

for (int i = 1; i < 5; i++)
    if (codeInput.length() != 5 || codeInput.charAt(i) < '0' 
        || codeInput.charAt(i) > '9' || codeInput.charAt(0) < 'A'
        || codeInput.charAt(0) > 'Z')
        {if (verbose) System.out.println("Sorry, I don't understand! 
            Use product codes only."); return true;}

这与您会注意到的区别不同,因为如果代码运行时间足够长,并且方法将内联,那么JIT将启动,从而消除对局部变量的需要。

编译器必须创建计算
codeInput.length()的代码
,因为它无法知道是否会在每次迭代中返回相同的值。你知道这是因为你知道这门课是如何运作的。但是编译器不知道它,并且必须假设
codeInput
发生了变化(例如,由于调用
charAt()


因此,是的:您可以通过计算
codeInput.length()
一次并将结果分配给局部变量来获得一些性能。

编译器必须在每次迭代时创建计算
codeInput.length()
的代码,因为它无法知道是否在每次迭代时返回相同的值。你知道这是因为你知道这门课是如何运作的。但是编译器不知道它,并且必须假设
codeInput
发生了变化(例如,由于调用
charAt()

因此,是的:您可以通过计算
codeInput.length()
一次并将结果分配给局部变量来获得一些性能。

这里聪明的不是编译器,而是JVM

现代JVM都有JIT(即时),这意味着代码将在运行中得到优化

不要费心用Java优化代码,只需编写正确的代码即可。JVM将为您完成其余的工作

对于您的特定代码段,如果您正在使用,您可以在此处使用
CharMatcher
以获得良好效果:

private static final CharMatcher PRODUCT_CHARS
    = CharMatcher.inRange('A', 'Z')
        .or(CharMatcher.inRange('a', 'z'))
        .or(CharMatcher.inRange('0', '9'))
        .precompute();

// In the verification method:
if (!(codeInput.length() == 5 && PRODUCT_CHARS.matchesAllOf(codeInput)))
    badProductCode();
在这里,聪明的不是编译器,而是JVM

现代JVM都有JIT(即时),这意味着代码将在运行中得到优化

不要费心用Java优化代码,只需编写正确的代码即可。JVM将为您完成其余的工作

对于您的特定代码段,如果您正在使用,您可以在此处使用
CharMatcher
以获得良好效果:

private static final CharMatcher PRODUCT_CHARS
    = CharMatcher.inRange('A', 'Z')
        .or(CharMatcher.inRange('a', 'z'))
        .or(CharMatcher.inRange('0', '9'))
        .precompute();

// In the verification method:
if (!(codeInput.length() == 5 && PRODUCT_CHARS.matchesAllOf(codeInput)))
    badProductCode();

您的第一个目标应该是代码的简单性和可读性。对于像您所提出的问题这样简单的问题,您真的必须不遗余力地将其转化为性能瓶颈。最干净、最灵活的字符串验证方法是正则表达式:

boolean valid = codeInput.matches("[A-Z][0-9]{4}");
if (!valid && verbose) 
   System.out.println("Sorry, I don't understand! Use product codes only.");
return !valid;
如果您真的想从中获得最后一点性能,可以预编译正则表达式:

static final Pattern productCodeRegex = Pattern.compile("[A-Z][0-9]{4}");
boolean validate(String codeInput) {
  boolean valid = productCodeRegex.matcher(codeInput).matches();
  ...
}

您的第一个目标应该是代码的简单性和可读性。对于像您所提出的问题这样简单的问题,您真的必须不遗余力地将其转化为性能瓶颈。最干净、最灵活的字符串验证方法是正则表达式:

boolean valid = codeInput.matches("[A-Z][0-9]{4}");
if (!valid && verbose) 
   System.out.println("Sorry, I don't understand! Use product codes only.");
return !valid;
如果你真的想要最后一点表现