无继承
有 static 修饰
static final
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// 生成随机数字和字母, public static final String getStringRandomFinal(int length) { String val = ""; Random random = new Random(); // 参数length,表示生成几位随机数 for (int i = 0; i < length; i++) { String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; // 输出字母还是数字 if ("char".equalsIgnoreCase(charOrNum)) { // 输出是大写字母还是小写字母 // int temp = random.nextInt(2) % 2 == 0 ? 65 : 97; val += (char) (random.nextInt(26) + 97); } else if ("num".equalsIgnoreCase(charOrNum)) { val += String.valueOf(random.nextInt(10)); } } return val; } |
static 非 final
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// 生成随机数字和字母, public static String getStringRandom(int length) { String val = ""; Random random = new Random(); // 参数length,表示生成几位随机数 for (int i = 0; i < length; i++) { String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; // 输出字母还是数字 if ("char".equalsIgnoreCase(charOrNum)) { // 输出是大写字母还是小写字母 // int temp = random.nextInt(2) % 2 == 0 ? 65 : 97; val += (char) (random.nextInt(26) + 97); } else if ("num".equalsIgnoreCase(charOrNum)) { val += String.valueOf(random.nextInt(10)); } } return val; } |
结果
这里使用了 OpenJDK 的 JMH 基准测试工具来测试的,结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# JMH 1.4.1 (released 903 days ago, please consider updating!) # VM invoker: /srv/jdk1.8.0_92/jre/bin/java # VM options: <none> # Warmup: 20 iterations, 1 s each # Measurement: 20 iterations, 1 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Benchmark: org.agoncal.sample.jmh.Main.benchmark 中间忽略了预热及测试过程,这里只显示结果 Result: 206924.113 ±(99.9%) 7746.446 ops/s [Average] Statistics: (min, avg, max) = (132107.466, 206924.113, 267265.397), stdev = 32798.937 Confidence interval (99.9%): [199177.667, 214670.559] # JMH 1.4.1 (released 903 days ago, please consider updating!) # VM invoker: /srv/jdk1.8.0_92/jre/bin/java # VM options: <none> # Warmup: 20 iterations, 1 s each # Measurement: 20 iterations, 1 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Benchmark: org.agoncal.sample.jmh.Main.benchmarkFinal 中间忽略了预热及测试过程,这里只显示结果 Result: 210111.568 ±(99.9%) 8486.176 ops/s [Average] Statistics: (min, avg, max) = (133813.368, 210111.568, 267525.228), stdev = 35931.001 Confidence interval (99.9%): [201625.392, 218597.744] # Run complete. Total time: 00:13:54 Benchmark Mode Samples Score Error Units o.a.s.j.Main.benchmark thrpt 200 206924.113 ± 7746.446 ops/s o.a.s.j.Main.benchmarkFinal thrpt 200 210111.568 ± 8486.176 ops/s |
总结:你说final的性能比非final有没有提升呢?可以说有,但几乎可以忽略不计。如果单纯地追求性能,而将所有的方法修改为 final 的话,我认为这样子是不可取的。而且这性能的差别,远远也没有网上有些人说的提升 50% 这么恐怖(有可能他们使用的是10年前的JVM来测试的吧^_^,比如 《35+ 个 Java 代码性能优化总结》这篇文章。雷总:不服?咱们来跑个分!)
分析
字节码级别的差别
StringKit.java StringKitFinal.java
它们在字节码上的差别:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
[18:52:08] emacsist:target $ diff /tmp/stringkit.log /tmp/stringkit-final.log 1,5c1,5 < Classfile /Users/emacsist/Documents/idea/logging/target/classes/org/agoncal/sample/jmh/StringKit.class < Last modified 2017-6-15; size 1098 bytes < MD5 checksum fe1ccdde26107e4037afc54c780f2c95 < Compil |