2011-11-10 4 views
6

次の単純なJavaプログラムは、Hello Worldという文字列をSystem.out.println("Hello World");という文字列で表示していますが、そうではありません。これは単にこれを別の文字列で置き換えます。この場合、おはようございます!を開き、コンソールに表示します。文字列Hello Worldはまったく表示されません。 Javaの次の簡単なコードスニペットを見てみましょう。ここでは、このコードについてうまくいくが、やや難しい方法で機能する単純なJavaコード

package goodday; 

import java.lang.reflect.Field; 

final public class Main 
{ 
    public static void main(String[] args) 
    {   
     System.out.println("Hello World"); 
    } 

    static 
    { 
     try 
     { 
      Field value = String.class.getDeclaredField("value"); 
      value.setAccessible(true); 
      value.set("Hello World", value.get("Good Day !!")); 
     } 
     catch (Exception e) 
     { 
      throw new AssertionError(e); 
     } 
    } 
} 

ただ一つの質問。それは期待どおりに動作しますが、文字列の長さを減らすことはできませんGood Day !!。そうしようとすると、java.lang.ArrayIndexOutOfBoudsExceptionが発生します。長さを増やすと、プログラムは正常に実行されますが、表示文字列の残りの文字は切り捨てられます。これは、両方の文字列の長さがいくらか同じであることを意味します。どうして?これは私が理解できなかったことです。

+3

もちろん、実際のコードでこれを行うべきではないことを認識していますか? –

+2

私は長い間Javaを知っていますが、前にこのようなスマートを見たことはありませんでした。本当に良い質問です:D –

答えて

7

valueフィールドは、文字列がバッキングストアとして使用する文字配列を内部的に格納するchar[]です。その他のフィールドは、文字配列への初期オフセットと文字列の長さを示します。 (部分文字列を取るためには、同じchar[]を参照するが、開始オフセットと長さが異なる新しいStringオブジェクトを作成するだけです)。

これらのフィールドも同様に変更すると、文字列で。サンプル:

import java.lang.reflect.Field; 

public class Test 
{ 
    // Obviously in real code you wouldn't use Exception like this... 
    // Although hacking string values with reflection is worse, of course. 
    public static void main(String[] args) throws Exception 
    {   
     System.out.println("Hello World"); 
     replaceHelloWorld("Goodbye!"); 
     System.out.println("Hello World"); 
     replaceHelloWorld("Hello again!"); 
     System.out.println("Hello World"); 
    } 

    static void replaceHelloWorld(String text) throws Exception 
    { 
     // Note: would probably want to do hash as well... 
     copyField(text, "Hello World", "value"); 
     copyField(text, "Hello World", "offset"); 
     copyField(text, "Hello World", "count"); 
    } 

    static void copyField(String source, String target, String name) 
     throws Exception 
    { 
     Field field = String.class.getDeclaredField(name); 
     field.setAccessible(true); 
     field.set(target, field.get(source)); 
    } 
} 
+2

これを奨励するよりもよく知っておくべきです:-) –

関連する問題