3

私は定期的に Eclipse デバッガーを使用していますが、これは常に IDE について私を悩ませてきました。ステップ フィルタリングは非常に貴重なツールです。そのため、ソース コードを持たないクラスや単純に興味のないクラスに足を踏み入れることはありません。ただし、ほとんどの場合、Eclipse は正しく機能しません。特に、「単純なゲッターをフィルター処理する」および「単純なセッターをフィルター処理する」オプションがあります。

メンバー変数の値を単に返すゲッターを使用する場合があります。

private String value;
public String getValue()
{
    return value;
}

あるいは、高価なオブジェクトを遅延してインスタンス化するゲッターかもしれません。

private IObjectFactory instance;
public IObjectFactory getInstance()
{
    if (instance == null)
        instance = ObjectFactory.createFactory();
    return instance;
}

メンバー変数の値を設定するだけのセッターを使用する場合があります。

private String value;
public void setValue(String value)
{
    this.value = value;
}

流暢な構文をサポートしたいかもしれません。

private String value;
public ObjectFactory setValue(String value)
{
    this.value = value;
    return this;
}

または、何らかの検証やイベントのトリガーを行うこともできます。

private String user;
public void setUser(String user)
{
    if (StringUtils.isBlank(user))
        throw ExceptionHelper.argumentNull("user");
    this.user = user;
}

private String title;
public void setTitle(String title)
{
    if (!StringUtils.equals(this.title, title))
    {
        this.title= title;
        onPropertyChanged("title", title);
    }
}

そして、これらの用途のすべてについて、Eclipseを使用してコードにステップインすると、これらのメソッドにステップインします...

Eclipse は何を「単純なゲッター」または「単純なセッター」と見なしますか?

フィルターは確実に有効になっています。

ステップフィルタリング設定

念のために言うと、私は Eclipse Kepler ビルド 20130614-0229 を使用しています。JRE6 を使用して Eclipse を実行し、Tomcat 7 サーバーで Java 1.4 Web アプリをホストしています。最終的には 1.4 をターゲットにしていますが、これは JDK6 を使用してローカルでコンパイルされているため、問題があるとは考えていません。JRebel をインストールして使用していますが、おそらくクラスローダーが、何が「単純」と見なされるかを決定するアルゴリズムに干渉していますか? 「フィルターをステップスルーする」オプションを有効にして組み合わせると、おそらく私のコードをステップスルーしています。これについて考えた後、さらに実験します。

4

2 に答える 2

2

わかりました、私はそれを追跡したと思います。

通常の状況では、これらのフィルターが有効になっている場合、プレーンなゲッターとプレーンなセッター (質問の例 1 と 3) がステップオーバーされます。メソッドをフックするように変更する JRebel などの特別なクラスローダーがインストールされて使用されている場合、メソッドが「単純なゲッター」または「単純なセッター」であるかどうかを判断する Eclipse のアルゴリズムに干渉するようです。

したがって、コードでは次のようなゲッターです。

public String getValue()
{
    return this.value;
}

JVM の観点からは、次のように変更される場合があります。

public String getValue()
{
    Proxy proxy = getProxy(this);
    return (String)proxy.invoke("getValue", new Object[] { });
    // this is all just an example,
    // it's defintely way more complicated than this
}

この変更されたコードは、Eclipse を混乱させ、「これは単純な getter ではないので、それに踏み込む」と考えさせます。それはそうですが、実際のソースコードは私の実際の単純なゲッターであり、「なぜEclipseはこの単純なゲッターに足を踏み入れたのですか?」と混乱させます。

ステップフィルタリングを機能させるために、非常に不自然なテストを実行しました。

import org.apache.commons.lang.StringUtils;

public class Program
{
    public static void main(String[] args)
    {
        User bob = new User("0001", "Bob");
        String id = bob.getId(); //stepped over
        String name = bob.getName(); //stepped over
        IHome home = bob.getHome(); //stepped into

        bob.setId("foo"); //stepped into
        bob.setName("Bobby"); //stepped over
        String asString = bob.setNameFluent("Bobbo").toString(); //stepped into
        IHome newHome = Neighborhood.getHome("moo");
        bob.setHome(newHome); //stepped into
        return;
    }

    static class User
    {
        private String id;
        private String name;
        private IHome home;

        public User() { this("0001", null); }
        public User(String id, String name) { this.id = id; this.name = name; }

        public String getId() // simple
        {
            return id;
        }
        public String getName() // simple
        {
            return name;
        }
        public IHome getHome() // not simple
        {
            if (home == null)
                home = Neighborhood.getHome(id);
            return home;
        }

        public void setId(String id) // not simple
        {
            if (StringUtils.isBlank(id))
                throw ExceptionHelper.argumentBlank("id");
            this.id = id;
        }
        public void setName(String name) // simple
        {
            this.name = name;
        }
        public User setNameFluent(String name) // not simple
        {
            this.name = name;
            return this;
        }
        public void setHome(IHome home) // not simple
        {
            if (home != null)
            {
                this.home = home;
                onHomeChanged();
            }
        }

        protected void onHomeChanged()
        {
            this.id = home.getId();
        }
        public String toString()
        {
            return "User { name=" + getName() + ", home=" + getHome() + " }";
        }
    }

    static interface IHome
    {
        String getId();
        String getLocation();
    }

    static class Neighborhood
    {
        public static IHome getHome(String id)
        {
            return new Home(id);
        }

        static class Home implements IHome
        {
            private String id;
            public Home(String id) { this.id = id; }
            public String getId() { return id; }
            public String getLocation() { return "Home" + id; }
            public String toString() { return "Home: " + getLocation(); }
        }
    }

    static class ExceptionHelper
    {
        public static IllegalArgumentException argumentBlank(String name)
        {
            return new IllegalArgumentException("Argument " + name + " must not be blank");
        }
    }
}

デフォルトの構成 (JRebel なしの JDK6) では、ステップ フィルタリングが機能しているように見えました。単純な方法に足を踏み入れようとすると、実際にはそれらを踏み越えました。JRebel を有効にしてコードをもう一度ステップ実行すると、すべてのメソッドにステップ インしました。また、「フィルターを通過する」が有効かどうかは関係ありません。

tldr;

JRebel を使用することで、Eclipse を混乱させ、単純なゲッターと単純なセッターを元よりも複雑に見せる魔法が行われます。JRebel を無効にすると、フィルターが意図したとおりに機能します。

于 2013-08-23T17:16:39.057 に答える
1

これはEclipseのWebサイトのページで、2つのオプションについてもう少し詳しく説明しています

単純なゲッターをフィルタリングします。

このオプションは、ステップ実行中に単純な Java Bean スタイルの getter を常にフィルタリングするかどうかを制御します。

シンプルなセッターをフィルタリングします。

このオプションは、ステップ実行中に単純な Java Bean スタイルのセッターを常にフィルタリングするかどうかを制御します。

その音から、あなたが与える例1と3は、ここでの意味のように見えます. しかし、なぜあなたがあなたの行動を見ているのか分かりません。

編集:元の投稿者が問題を発見したようです。JRebel がメソッドを過度に複雑にしているということです。

于 2013-08-22T23:49:47.500 に答える