Java字符串池加上反射可以在Java中产生一些难以想象的结果:
import java.lang.reflect.Field;
class MessingWithString {
public static void main (String[] args) {
String str = "Mario";
toLuigi(str);
System.out.println(str + " " + "Mario");
}
public static void toLuigi(String original) {
try {
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringValue.set(original, "Luigi".toCharArray());
} catch (Exception ex) {
// Ignore exceptions
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将打印:
"Luigi Luigi"
Run Code Online (Sandbox Code Playgroud)
马里奥怎么了?
我正在学习 Java 中的反射。偶然间,我发现了以下对我来说意想不到的行为。
下面写的两个测试都成功。
class NewInstanceUsingReflection {
@Test
void testClassNewInstance()
throws NoSuchMethodException, InvocationTargetException,
InstantiationException, IllegalAccessException
{
final var input = "A string";
final var theClass = input.getClass();
final var constructor = theClass.getConstructor();
final String newString = constructor.newInstance();
assertEquals("", newString);
}
@Test
void testClassNewInstanceWithVarOnly()
throws NoSuchMethodException, InvocationTargetException,
InstantiationException, IllegalAccessException
{
final var input = "A string";
final var theClass = input.getClass();
final var constructor = theClass.getConstructor();
final var newString = constructor.newInstance();
assertEquals("A string", newString);
}
}
Run Code Online (Sandbox Code Playgroud)
除了断言之外的唯一区别是变量类型在第一个测试中是显式的,并在第二个测试中newString声明。var
我正在使用 …
考虑以下代码:
String first = "abc";
String second = new String("abc");
Run Code Online (Sandbox Code Playgroud)
使用new关键字时,Java会abc String再次创建吗?这会存储在常规堆还是String池中?多少人String在将s结尾String池?
在一次采访中,有人问我要在给定问题上创建的对象数量:
String str1 = "First";
String str2 = "Second";
String str3 = "Third";
String str4 = str1 + str2 + str3;
Run Code Online (Sandbox Code Playgroud)
我回答说将在字符串池中创建6个对象。
三个变量中的每个变量都为3。
1代表str1 + str2(假设str)。
1代表str2 + str3。
1将代表str + str3(str = str1 + str2)。
我给出的答案正确吗?如果没有,正确答案是什么?
java string string-concatenation string-building string-pool
有没有办法检查,目前字符串池中有哪些字符串.
我可以以编程方式列出池中存在的所有字符串吗?
要么
任何IDE都有这种插件吗?
刚刚在gdb中检查以下内容:
char *a[] = {"one","two","three","four"};
char *b[] = {"one","two","three","four"};
char *c[] = {"two","three","four","five"};
char *d[] = {"one","three","four","six"};
Run Code Online (Sandbox Code Playgroud)
我得到以下内容:
(gdb) p a
$17 = {0x80961a4 "one", 0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four"}
(gdb) p b
$18 = {0x80961a4 "one", 0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four"}
(gdb) p c
$19 = {0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four", 0x80961b7 "five"}
(gdb) p d
$20 = {0x80961a4 "one", 0x80961ac "three", 0x80961b2 "four", 0x80961bc "six"}
Run Code Online (Sandbox Code Playgroud)
我真的很惊讶字符串指针对于相同的单词是相同的.我原以为每个字符串都会在堆栈上分配自己的内存,无论它是否与另一个数组中的字符串相同.
这是某种编译器优化的示例,还是这种字符串声明的标准行为?
使用private final static Stringin java和使用本地字符串变量是否有任何性能优势,每次访问该方法时都必须"初始化"?
我确实认为使用private static final字符串是一种很好的做法,可以在类的不同部分重用,但是如果一个字符串仅在一个方法中使用,在一个位置,出于一个非常特殊的原因,没有其他方法涉及关于,我实际上更喜欢用较少的私有成员保持类的内部接口清洁,并且只使用局部变量.
鉴于java具有String interning,并且实际上使用quotes(String s = "some string")声明的每个字符串的单个副本保留一个池,每次访问该方法时,必须声明/初始化/分配变量实际上会有性能损失vs使用静态字符串?
为了使它更清楚,使用SS或之间会有任何区别LS吗?
class c {
private final static String SS = "myString";
private void method(){
//do something with SS
}
private void OtherMethod(){
String LS = "myOtherString"
//do same thing with LS
}
}
Run Code Online (Sandbox Code Playgroud) 我正在准备参加OCA SE 7考试,其中一些问题真的很棒(!).
在我使用的其中一本书中,我发现了一个错误,所以我想确认以下内容...
public static void main(String... args) {
String autumn = new String("autumn"); // line one
System.out.println("autumn" == "summer"); // line two
}
Run Code Online (Sandbox Code Playgroud)
在之后println方法执行,有多少String对象是那里的游泳池?
我的理解是: - 第一行不会将字符串添加到池中 - 第二行创建"autumn"和"summer"并将它们添加到池中所以书中的正确答案是2.
但是,我也认为......因为我应该对考试问题产生偏执......也会创建字符串"false"并添加到池中...所以我认为3应该是正确的答案......或者其他一些黑魔法是否会发生......默认情况下JVM已经将"true"和"false"放入池中了什么?...
有人可以确认吗?
编辑:经过一些研究后,我发现在书中谈到"错误"并不公平; 作为一般提示:考试题目通常根据"以下代码"制定; 所以他们显然对简单的计算代码本身在本地做什么的简单计算感兴趣.因此,范围不允许检查println(boolean b)实现或编译器优化.很公平 :)
如果为内存优化jvm创建string pool,那么为什么每次我们使用new关键字创建字符串时它都会创建新的对象,即使它存在于string pool?
我需要一个"字符串池"对象,我可以在其中重复插入"字符序列"(我使用这个短语来表示"字符串"而不会将其与std :: string或C字符串混淆),获取指向序列的指针,如果/当池需要增长时,保证指针不会失效.使用简单std::string的池作为池将无法工作,因为当字符串超出其初始容量时可能会重新分配字符串,从而使所有先前指针无效.
游泳池不会无限制地增长 - 我会在其上调用一个clear()方法明确定义点- 但我也不想保留任何最大容量.它应该能够在不移动的情况下成长.
我正在考虑的一种可能性是将每个新的字符序列插入到a中forward_list<string>并获得begin()->c_str().另一个是插入unordered_set<string>,但我很难找到当unordered_set必须增长时会发生什么.我正在考虑的第三种可能性(不太热情)是滚动我自己的1K缓冲区链,我将其连接到字符序列中.这具有(我猜)具有最高性能的优势,这是该项目的要求.
我有兴趣听听其他人如何建议接近这个.
更新1:编辑以澄清我对短语"chars序列"的使用等同于"字符串"的一般概念,而不暗示std :: string或以null结尾的char数组.