java-Eclipse将什么视为“简单获取器”或“简单设置器”?

我定期使用Eclipse调试器,这一直使我对IDE感到困惑.步进过滤是一种非常宝贵的工具,因此,我不会进入没有源代码的类,或者根本就不感兴趣.但是,在大多数情况下,Eclipse并没有做到这一点.特别是,有“过滤简单的getters”和“过滤简单的setters”选项.

我可能会使用仅返回成员变量值的getter.

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 build 20130614-0229.我正在使用JRE6运行Eclipse和托管Java 1.4 Web应用程序的Tomcat 7服务器.尽管最终目标是1.4,但它是使用JDK6在本地编译的,因此我认为这不是问题.我确实已经安装并使用了JRebel,也许类加载器正在干扰确定什么被认为是“简单”的算法?结合启用“逐步筛选”选项,它可能正在逐步遍历我的代码.考虑这一点后,我将做进一步的实验.

解决方法:

好吧,我想我已经找到了.

在正常情况下,如果启用了这些过滤器,则将跳过普通的获取器和普通的设置器(问题中的示例1和3).如果安装并使用了特殊的类加载器(例如JRebel)来修改要挂接到它们的方法,则它似乎会干扰Eclipse的算法,后者确定方法是“简单getter”还是“简单setter”.

因此,在代码中看起来像这样的getter:

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,因此请踏入它”.确实可以,但是实际的源代码是我的实际简单的getter,然后使我感到困惑:“为什么Eclipse进入了这个简单的getter?”

我进行了一个非常人为设计的测试,以尝试使步骤筛选起作用.

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困惑,使简单的getter和简单的setter看起来比原来更加复杂.禁用JRebel将导致过滤器按预期工作.

上一篇:java-如何使用Eclipse搜索类的实例?


下一篇:java-调试“进入”类调用会导致“找不到类”异常-Eclipse调试