Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaBeans和内省-布尔和索引属性搞砸了?_Java_Introspection_Javabeans - Fatal编程技术网

JavaBeans和内省-布尔和索引属性搞砸了?

JavaBeans和内省-布尔和索引属性搞砸了?,java,introspection,javabeans,Java,Introspection,Javabeans,我的一位前同事半小时前开始讨论JavaBeans,以及为什么JavaBeans在JSF中没有按照他想要的方式工作。特殊情况是关于布尔属性的 1。对于名为isUrlEclipse的布尔属性,将生成 private boolean isUrl; public boolean isUrl() {..} public boolean setUrl(boolean url) {..} 但这在JSF中不起作用。他通过添加public boolean getIsUrl()实现了它。实现可能有缺陷,所以让我们

我的一位前同事半小时前开始讨论JavaBeans,以及为什么JavaBeans在JSF中没有按照他想要的方式工作。特殊情况是关于布尔属性的

1。对于名为
isUrl
Eclipse的布尔属性,将生成

private boolean isUrl;
public boolean isUrl() {..}
public boolean setUrl(boolean url) {..}
但这在JSF中不起作用。他通过添加
public boolean getIsUrl()
实现了它。实现可能有缺陷,所以让我们使用内省API来确定谁是对的:

BeanInfo info = Introspector.getBeanInfo(ClassTest.class);
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
      System.out.println(pd.getName() + ": " + pd.getReadMethod() + 
       " : " + pd.getWriteMethod());
}
对于上面的代码,这将打印两种方法——即Eclipse是正确的,JSF是错误的。但这听起来有点可疑,因为我没有提到任何关于双重“是”

但是在浏览规范时,我看到了一些我从未使用过的东西——所谓的索引属性。您可以使用
private String[]bar
,然后使用
public String getBar(int idx)
。因此:

2。我用
内省器
试过了,但它并没有找到一个读取bar的方法。上述代码的结果是:
bar:null:null
。所以我开始思考——现在内省者没有遵循规范。也许在前面的案例中它没有遵循规范,最终,JSF是正确的。事实上,索引属性可以使给定属性有两种读取方法。这在内省API的
PropertyDescriptor
类中是不可能的

这会导致什么呢?我们有一个可能已损坏的API,它不符合规范。这会导致规范的其他实现(JSF显然使用自定义API)。这会导致进一步的误解和混乱

让我感到困扰的是,在JavaBeans规范中,他们将方法的命名约定称为“设计模式”。这听起来不对

那么,现在谈谈问题:

  • JavaBeans规范清楚吗
  • 自省API正确吗
  • 是否需要一个新的JavaBeans规范,至少要澄清布尔人的行为(这在某种程度上是主观的)
  • 更新。JSF的用法似乎是
    bean.isUrl
    而不是
    bean.url
    。这使得不使用
    isUrl()
    accessor更有意义


    p.S.JDK 1.6.020,JSF 1.2,MyFaces

    正如@Peter Lawrey所提到的,就JavaBeans而言,字段的名称是不相关的。它甚至不需要存在,或者你可以给它一个愚蠢的名字,比如前缀
    m

    您没有为整个
    bar
    属性提供合适的读写方法,因此不会显示这些方法。不能在运行时将
    方法
    合成为现有类。我相信索引属性是最新版本,即使没有明显的
    ,因为
    java.beans
    接口没有使用它们

    我没有JSF规范(它将在jcp.org律师墙后面),所以不知道它声称什么。它可能指定了与JavaBeans规范不同的东西[可能],或者您可能正在使用一个带有bug的实现[我猜也是可能的]


    “设计模式”只是一个短语。就像我们设计中的图案一样。它不是GoF中的设计模式。

    JavaBean属性是由方法定义的,而不是由字段定义的。因此,该类具有和方法,但没有
    getField()
    方法

    就我个人而言,我认为你的同事使用了一种不好的做法

    a)
    是一个动词。字段不应以动词命名。
    b) 虽然不是必需的,但良好的做法是将字段命名为属性,这样可以编写如下代码:

    PropertyDescriptor pd; // let's assume this is set
    Method referenceMethod = pd.getReadMethod() == null
      // at least one of these is not null
      ? pd.getWriteMethod() : pd.getReadMethod(); 
    Field underLyingField = referenceMethod
                              .getDeclaringClass()
                              .getDeclaredField(pd.getName());
    
    private String[] bar;
    public String[] getBar(){
        return bar;
    }
    public void setBar(String[] bar){
        this.bar = bar;
    }
    
    private List<String> bar;
    public List<String> getBar(){
        return bar;
    }
    public void setBar(List<String> bar){
        this.bar = bar;
    }
    
    private Map<String, String> bar;
    public Map<String, String> getBar(){
        return bar;
    }
    public void setBar(Map<String, String> bar){
        this.bar = bar;
    }
    
    虽然这段代码没有标准化,但它遵循惯例,非常方便。如果不遵循这样的约定,就无法将字段与属性关联(我知道这是有意的)

    e、 g.我使用上述代码检查字段是否有注释


    关于索引属性:

    您可以对数组或列表(或映射)属性使用索引语法,但前提是它们被定义为标准bean属性

    因此,如果你有这样一个属性:

    PropertyDescriptor pd; // let's assume this is set
    Method referenceMethod = pd.getReadMethod() == null
      // at least one of these is not null
      ? pd.getWriteMethod() : pd.getReadMethod(); 
    Field underLyingField = referenceMethod
                              .getDeclaringClass()
                              .getDeclaredField(pd.getName());
    
    private String[] bar;
    public String[] getBar(){
        return bar;
    }
    public void setBar(String[] bar){
        this.bar = bar;
    }
    
    private List<String> bar;
    public List<String> getBar(){
        return bar;
    }
    public void setBar(List<String> bar){
        this.bar = bar;
    }
    
    private Map<String, String> bar;
    public Map<String, String> getBar(){
        return bar;
    }
    public void setBar(Map<String, String> bar){
        this.bar = bar;
    }
    
    或者像这样:

    PropertyDescriptor pd; // let's assume this is set
    Method referenceMethod = pd.getReadMethod() == null
      // at least one of these is not null
      ? pd.getWriteMethod() : pd.getReadMethod(); 
    Field underLyingField = referenceMethod
                              .getDeclaringClass()
                              .getDeclaredField(pd.getName());
    
    private String[] bar;
    public String[] getBar(){
        return bar;
    }
    public void setBar(String[] bar){
        this.bar = bar;
    }
    
    private List<String> bar;
    public List<String> getBar(){
        return bar;
    }
    public void setBar(List<String> bar){
        this.bar = bar;
    }
    
    private Map<String, String> bar;
    public Map<String, String> getBar(){
        return bar;
    }
    public void setBar(Map<String, String> bar){
        this.bar = bar;
    }
    
    您可以像这样访问映射到
    “baz”
    的值
    ${bar['baz']}


    此功能建立在标准bean功能之上,因此它需要常规的getter/setter。

    也许像C#properties这样的东西会派上用场。阅读了内省程序代码后,isXxxx应该可以工作。使用的字段名并不重要。您是否尝试过Java 6更新23?+1。是的,字段名的“无关性”是我们在讨论中提到的,这解释了eclipse和内省者的行为。Eclipse很聪明。关于设计模式——我同意这只是一个短语,但它有一个非常具体的含义——GoF给出的含义。并不是说它没有其他意义,而是说它很奇怪。一般来说,我同意布尔属性不应该包括
    is
    ,但对我来说,如果字段名是名词而不是形容词,这是有意义的。@Bozho有趣的是,我认为字段名不应该是动词这是一个广为接受的约定,但我找不到任何东西来支持这一说法。每个人都说方法名应该是动词,对我来说,这意味着字段不应该是动词,但没有人这么明确地说(Sun、Wikipedia、Joshua Bloch都没有)