jeudi 15 décembre 2022

Why do I see different methods with reflection vs browsing the source code?

My goal is to create strings from char arrays in Java. The String class has a constructor that accepts a char array and creates a new String object, this works well. However, this constructor makes a defensive copy of the char array, which I am trying to avoid.

I was browsing the source code of the String class (for Java 8, 11 and 17), and I happened to come across a package-private constructor that does exactly what I need:

    /*
    * Package private constructor which shares value array for speed.
    * this constructor is always expected to be called with share==true.
    * a separate constructor is needed because we already have a public
    * String(char[]) constructor that makes a copy of the given char[].
    */
    String(char[] value, boolean share) {
        // assert share : "unshared not supported";
        this.value = value;
    }

Since the constructor is not public, I thought I might be able to use it with reflection. However, when I try to list all the declared constructors for the String class, I don't see the above constructor:

|  Welcome to JShell -- Version 11.0.16.1
|  For an introduction type: /help intro

jshell> import java.lang.reflect.Constructor

jshell> var ctors = String.class.getDeclaredConstructors()
ctors ==> Constructor[18] { public java.lang.String(byte[]) ... ng.String(int[],int,int) }

jshell> for (Constructor<?> c: ctors) System.out.println(c)
public java.lang.String(byte[])
public java.lang.String(byte[],int,int)
public java.lang.String(byte[],java.nio.charset.Charset)
public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException
public java.lang.String(byte[],int,int,java.nio.charset.Charset)
java.lang.String(char[],int,int,java.lang.Void)
java.lang.String(java.lang.AbstractStringBuilder,java.lang.Void)
public java.lang.String(java.lang.StringBuilder)
public java.lang.String(java.lang.StringBuffer)
java.lang.String(byte[],byte)
public java.lang.String(char[],int,int)
public java.lang.String(char[])
public java.lang.String(java.lang.String)
public java.lang.String()
public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException
public java.lang.String(byte[],int)
public java.lang.String(byte[],int,int,int)
public java.lang.String(int[],int,int)

In the above output, I also see some constructors that I don't see in the source code, for example java.lang.String(java.lang.AbstractStringBuilder,java.lang.Void). Can someone help me understand this behavior? Why is the list of constructors from reflection different from the ones in the source code?

I am not using any security manager, in case that influences the answer. Also using vanilla openjdk (tried on version 8, 11 and 17).





Aucun commentaire:

Enregistrer un commentaire