我一直听说有关添加到JVM的所有新酷功能,其中一个很酷的功能是invokedynamic.我想知道它是什么以及它如何使Java中的反射编程更容易或更好?
根据Netbeans的提示名为Use chain of .append方法而不是字符串连接
在StringBuilder或StringBuffer的append方法的调用参数中查找字符串连接.
StringBuilder.append()是否真的比字符串连接更有效?
代码示例
StringBuilder sb = new StringBuilder();
sb.append(filename + "/");
Run Code Online (Sandbox Code Playgroud)
与
StringBuilder sb = new StringBuilder();
sb.append(filename).append("/");
Run Code Online (Sandbox Code Playgroud) 我有一个不符合屏幕宽度的长字符串.例如.
String longString = "This string is very long. It does not fit the width of the screen. So you have to scroll horizontally to read the whole string. This is very inconvenient indeed.";
Run Code Online (Sandbox Code Playgroud)
为了便于阅读,我想到了这样写 -
String longString = "This string is very long." +
"It does not fit the width of the screen." +
"So you have to scroll horizontally" +
"to read the whole string." +
"This is very inconvenient indeed.";
Run Code Online (Sandbox Code Playgroud)
但是,我意识到第二种方式使用字符串连接,并将在内存中创建5个新字符串,这可能会导致性能下降.是这样的吗?或者编译器是否足够智能,以确定我需要的只是一个字符串?我怎么能避免这样做?
如果我错了,请纠正我.在Java 8中,出于性能原因,当通过"+"运算符连接多个字符串时,调用了StringBuffer.并且"解决"了创建一堆中间字符串对象和污染字符串池的问题.
Java 9怎么样?Invokedynamic增加了一项新功能.还有一个新的类可以更好地解决问题,StringConcatFactory.
String result = "";
List<String> list = Arrays.asList("a", "b", "c");
for (String n : list) {
result+=n;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:在这个循环中创建了多少个对象?有中介对象吗?我该如何验证呢?
Java logger允许以下语法:
m_logger.info("ID: {} NAME: {}", id, name); // 1
m_logger.info("ID: " + id + " NAME: " + name); // 2
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,基本上我们调用...函数,因此Object[]每次都会创建一个new .
我跑过YourKit,这就是我所看到的.
我的问题是,第一种情况不是我们应该一直避免的昂贵操作吗?但是我已经在很多代码中看到了这一点.使用#1我们获得了什么?
我想我们应该使用StringBuilder最佳性能?
我知道我可以在 Java 中做这样的事情:
String foo = 'a' + "bee";
如果我打印foo到控制台,我会得到abee. 这里的幕后究竟发生了什么?我假设'a'正在被提升为String,但我不确定什么规则管理这种类型的转换。据我所知,这似乎不是自动装箱的情况,因为自动装箱从原始类型映射到包装类(例如int-> Integer)。被String认为是 a的包装器char吗?
使这更有趣的一件事是,如果我执行类似的操作,则会
String test = 'a' + 'b';
出现编译错误。我明白,这是因为字符作为整数处理在添加时,虽然看似合理的期望,我会得到这样的事情"ab"在test加入时给出的行为char和String。
我目前正在用 C# 编写 JVM,纯粹出于学术目的(也许将来会构建混合的 .NET 和 Java/Scala 应用程序)。
我写了一个简单的JAVA类:
public class test
{
public static String hello_world(int i)
{
return "Hello " + i + " World!";
}
}
Run Code Online (Sandbox Code Playgroud)
并将其编译成test.class. 当我使用反编译器(我将其编写为 JVM 的一部分)对其进行反编译时,我看到此方法的以下说明:
iload_0
invokedynamic 2
areturn
Run Code Online (Sandbox Code Playgroud)
当在常量池中查找索引处的常量时2,我看到一个包含以下数据的 InvokeDynamic-Constant 条目:
makeConcatWithConstants : (I)Ljava/lang/String;
Run Code Online (Sandbox Code Playgroud)
我想这是有道理的(我更像是 .NET 用户而不是 JAVA 用户)。
hello_world当使用参数执行我的方法时1,在执行之前我有以下堆栈invokedynamic 2:
----TOP---
0x00000001
--BOTTOM--
Run Code Online (Sandbox Code Playgroud)
我的问题是:我该如何使用invokedynamic?
我无法解析该方法makeConcatWithConstants,因为 InvokeDynamic-Constant 没有给我任何makeConcatWithConstants可能位于何处的提示(请参阅文档)。 …
我知道使用"+"连接运算符来构建字符串是非常低效的,这就是为什么建议使用StringBuilder类,但我想知道这种模式是否也是低效的?
String some = a + "\t" + b + "\t" + c + "\t" + d + "\t" + e;
Run Code Online (Sandbox Code Playgroud)
我猜这里的编译器会优化编程,不是吗?
我正在学习StringBuider类。我在该站点和许多其他书籍中已经读到,当编译器遇到文字的“ +”运算符时,它将自动使用StringBuilder append的方法来将它们连接起来。
这似乎有点问题,因为将在运行时创建StringBuilder对象,但是应该在编译时获取String引用的串联String对象的地址。
String s1 = "hello";
String s2 ="bc";
int value = 22;
Run Code Online (Sandbox Code Playgroud)
当编译器“满足”此代码时:
String s = s1+s2+22;
Run Code Online (Sandbox Code Playgroud)
它将“更改”为:
String s = new StringBuilder().append("hello").append("bc").append(22).toString();
Run Code Online (Sandbox Code Playgroud)
也许我误会了什么?
由于字符串在 Java 中是不可变的,这会创建 3 个对象,还是在内部仅创建一个对象。
在 JVM 中执行将如何发生,它是否取决于 JVM 实现?
class Main{
public static void main(String[] args) throws Exception{
String s = "FirstString" + "SecondString" + "ThirdString";
}
}
Run Code Online (Sandbox Code Playgroud)
如果上面的情况在编译时解决了下面的情况如何工作。
class Main{
public static void main(String[] args) throws Exception{
String s = "FirstString" + "SecondString" + args[0];
}
}
Run Code Online (Sandbox Code Playgroud) java ×10
string ×6
jvm ×3
char ×1
java-8 ×1
java-9 ×1
jvm-bytecode ×1
logging ×1
reflection ×1