2015-09-08 14 views
10

以下のコードは、簡単に問題を再現する小さな例です。だから私はデフォルト値が設定されているString型の変数を持っています。Javaのイントロスペクション - 奇妙な動作

  • ゲッター文字列がreadMethodとwriteMethodなどセッターとしてゲッターを返さない

イントロスペクションをブールに変換

  • セッター
  • 便利なメソッド:私は3つの方法があります。代わりにisTest()メソッドをreadMethodとして返します。設定者は空です。

    ドキュメントからは、型がブール値であれば、 "is"メソッドはgetよりも優先度が高くなりますが、型がStringであることを理解していますので、 "is-xxx " 方法?

    public class Test { 
        public class Arguments { 
         private String test = Boolean.toString(true); 
    
         public boolean isTest() { 
          return Boolean.parseBoolean(test); 
         } 
    
         public String getTest() { 
          return test; 
         } 
    
         public void setTest(String test) { 
          this.test = test; 
         } 
        } 
    
        /** 
        * @param args the command line arguments 
        */ 
        public static void main(String[] args) throws IntrospectionException { 
         BeanInfo info = Introspector.getBeanInfo(Arguments.class); 
         System.out.println("Getter: " + info.getPropertyDescriptors()[1].getReadMethod()); 
         System.out.println("Setter: " + info.getPropertyDescriptors()[1].getWriteMethod()); 
         PropertyDescriptor descr = new PropertyDescriptor("test", Arguments.class); 
         System.out.println("T"); 
        } 
    
    } 
    

    これについていくつかの洞察を持っている人はいますか?

    追加情報:

    1. 順序が結果を変更しません。 isTest()メソッドは常にreadMethodと見なされます
    2. isTest()の名前をbsTest()に変更する場合は、getterとsetterをreadMethodとwriteMethodとして選択します。だから "is-xxx"と関係があります。
  • +0

    :あなたは、次のコードでそれを自分自身を納得させることができますか?それが最初のオカレンスであるためブール値として認識され、setterがString型と一致しない可能性があります。 –

    +0

    いいえ、それは意味をなさないが、明らかにそれが彼らが決めたものです(またはバグです)。あなたは、文字列とブール値を表すために停止を除いて、このことについて多くを行うことはできません:D – Dici

    +0

    は私が最初のテキスト内のいくつかのより多くの情報を追加しました。注文は結果に影響を与えません。 – Quirexx

    答えて

    4

    結果は実際にはJavaBeans specificationのように予想される結果です。私たちは同じ型を取ると戻りget<PropertyName>set<PropertyName>方法 の一致するペアを発見した場合は、その後、私たちは読み書きを定義するものとして、これらの方法を考えて

    は、単純なプロパティの段落8.3.1を引用します名前は<propertyName>になります。

    そして、ブーリアンプロパティの段落8.3.2を引用:

    このis<PropertyName>方法代わりget<PropertyName>方法を提供することができる、またはそれはget<PropertyName>方法に加えて提供することができます。

    どちらの場合でも、is<PropertyName>メソッドがブール値プロパティに対して存在する場合は、is<PropertyName>メソッドを使用してプロパティ値を読み取ります。

    あなたの例から、IntrospectorのisTestgetTest方法の両方を検出しています。 isTestgetTestオーバー優先順位を有するので、booleanとしてtestプロパティのタイプを決定するためにisTestを使用します。しかし、その後、Introspectorのセッターが署名void setTest(boolean test)を持っていることを期待し、それはそれを見つけることができませんので、セッターメソッドはnullです。

    何に注意することが重要なのは、イントロスペクターは、フィールドを読んでいないということです。 getter/setterメソッドのシグネチャを使用して、存在するフィールドと対応する型を判別します。 isTestメソッドのシグネチャがタイプbooleantestという名前のプロパティに指定し、その関係なく、testの実際の型の、イントロスペクターは、あなたのクラスは、プロパティboolean testを持っていることを検討します。実際に

    、すべてIntrospecterが懸念されるため、プロパティtestは存在すらしない可能性があります!あなたはクラスの終わりに `isTest`メソッドを宣言するとどうなりますか

    class Test { 
    
        public class Arguments { 
         public boolean isTest() { 
          return true; 
         } 
        } 
    
        public static void main(String[] args) throws IntrospectionException { 
         BeanInfo info = Introspector.getBeanInfo(Arguments.class); 
         System.out.println("Getter: " + info.getPropertyDescriptors()[1].getReadMethod()); 
         System.out.println("Name of property: " + info.getPropertyDescriptors()[1].getName()); 
        } 
    
    } 
    
    +0

    私はTunakiに同意し、いくつかのメタプログラミングを行っている場合、いくつかのパラメータで必要なように動作させることができます: 'PropertyDescriptor descr = new PropertyDescriptor(" test "、Arguments.class、" getTest "、" setTest ") ; ' –

    +0

    "isTestを使ってテストプロパティの型をbooleanと判断しますが、テストの型はStringとして明確に定義されています。または、メソッドの戻り値がBooleanであるため、型をBooleanとして定義していますか? – Quirexx

    +0

    @Quirexx Introspectorはフィールドを読み込みません。 getter/setterメソッドのシグネチャを使用して、存在するフィールドと対応する型を判別します。 'isTest'シグネチャは、実際の「テスト」タイプ「 – Tunaki

    2

    実際のメンバーはIntrospectorとは完全には関係ありません。たとえば、固定Stringを返すgetName()メソッドを持つことができます。Introspectorは、それを "name"というメンバーのゲッターにします。メンバーが存在しない場合でもセッターを持つことができます。 Introspectorへのインターフェイスを提供することもできます。実際のメンバーが存在しない場合でも、そのプロパティからプロパティが決定されます。

    つまり、プロパティは実際に変数を検索するのではなく、ゲッターとセッターメソッドの存在によって決まります。