I am learning about reflection in Java. By accident, I discovered the following, for me unexpected behavior.
Both tests as written below succeed.
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);
}
}
The only difference apart from the assertion is that the newString
variable type is explicit in the first test and declared as var
in the second test.
I'm using java 17 and the junit5 test framework.
Why is the value of newString
an empty string in the first test and the input
string value in the second test?
Does it have something todo with the string-pool?
Or is something else going on?
newString
isvar
, you get "A string" only ifinput
isfinal
. – Quadragesimalideone.com
) is a Java 11 version, without JUnit'sassertEquals(...)
, showing the same behaviour. – Catoninput
has an internal type likeconstant string "A string"
(which helps optimizations) instead of justString
. Then, the compiler figures thatnewString
is also an instance ofconstant string "A string"
. Writing String forces it to be String type. – Versed