Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.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
Java 如何在泛型中实现空对象模式?_Java_Generics_Design Patterns_Null - Fatal编程技术网

Java 如何在泛型中实现空对象模式?

Java 如何在泛型中实现空对象模式?,java,generics,design-patterns,null,Java,Generics,Design Patterns,Null,我喜欢的想法,并迫使我使用它,直到它真的感觉正常和良好。目前我不知道如何在泛型类型中使用它。我知道有可能定义第二个泛型类型并传入类来构造默认对象,但对于这种模式来说,这感觉开销太大了。有好办法吗 public class GenericExample<T> { public static final GenericExample NULL = ???; private T attribute; public GenericExample(T attribu

我喜欢的想法,并迫使我使用它,直到它真的感觉正常和良好。目前我不知道如何在泛型类型中使用它。我知道有可能定义第二个泛型类型并传入类来构造默认对象,但对于这种模式来说,这感觉开销太大了。有好办法吗

public class GenericExample<T> {
    public static final GenericExample NULL = ???;

    private T attribute;

    public GenericExample(T attribute) {
        this.attribute = attribute;
    }
}

public class HoldGeneric {
    private GenericExample<String> name = GenericExample.NULL;

    public initLater(String name) {
        this.name = new GenericExample<String>(name);
    }
}
公共类泛型示例{
公共静态最终GenericExample NULL=???;
私有T属性;
公共泛型示例(T属性){
this.attribute=属性;
}
}
公共类HoldGeneric{
private GenericExample name=GenericExample.NULL;
公共initLater(字符串名称){
this.name=新的GenericeExample(名称);
}
}

根据我对你问题的理解,我将同意以下观点

public class GenericExample<T> {

    public static final GenericExample<?> NULL = new GenericExample<Object>(new Object()) {
        public void print() {
        }
    };

    private T attribute;

    public GenericExample(T attribute) {
        this.attribute = attribute;
    }

    public void print() {
        System.out.print(attribute.toString());
    }

    @SuppressWarnings("unchecked")
    public static <X> GenericExample<X> nil() {
        return (GenericExample<X>) NULL;
    }
}

public class Test {

    private static GenericExample<String> name = GenericExample.nil();

    public static void main(String[] args) {
        String x = "blah";
        name.print();
        if (name == GenericExample.NULL) {
            name = new GenericExample<String>(x);
        }
        name.print();
    }
}
公共类泛型示例{
public static final GenericExample NULL=new GenericExample(new Object()){
公开作废印刷品(){
}
};
私有T属性;
公共泛型示例(T属性){
this.attribute=属性;
}
公开作废印刷品(){
System.out.print(attribute.toString());
}
@抑制警告(“未选中”)
公共静态泛型示例nil(){
返回(GenericExample)NULL;
}
}
公开课考试{
私有静态GenericExample name=GenericExample.nil();
公共静态void main(字符串[]args){
字符串x=“blah”;
name.print();
if(name==GenericExample.NULL){
名称=新的通用示例(x);
}
name.print();
}
}

如果不传入
T类
就无法正确实现它。您所能做的最接近于滥用类型擦除的操作是:

class GenericExample<T>
{
  private static final GenericExample<Object> NULL = new GenericExample<Object>(); 

  public static <T> GenericExample<T> nil()
  {
    @SuppressWarnings("unchecked")
    final GenericExample<T> withNarrowedType = (GenericExample<T>)NULL;
    return withNarrowedType;
  }
}
class GenericExample
{
private static final GenericExample NULL=new GenericExample();
公共静态泛型示例nil()
{
@抑制警告(“未选中”)
最后一个GenericExample,其窄类型=(GenericExample)为NULL;
返回窄类型;
}
}

但是,您必须接受
GenericExample.nil()
将与
GenericExample.nil()

相同,您可以按照JDK所做的操作,使用静态方法推断泛型类型并执行未经检查的强制转换

java.util.Collections
为空列表和集合实现空对象。在Java预泛型中,有一个公共静态字段

public static final List EMPTY_LIST = new EmptyList();
后仿制药: 现在有一些静态方法可以推断泛型类型并执行未经检查的强制转换,以便将其强制转换为正确的类型。类型实际上并不重要,因为集合是空的,但它使编译器感到高兴

@SuppressWarnings("unchecked")
public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}
@SuppressWarnings(“未选中”)
公共静态最终列表emptyList(){
返回(列表)空_列表;
}

Guava有一个解决方案(),谢谢你的链接,虽然我看不到与我的具体问题之间的联系。我明白了,你也可以用
Optional
来包装类成员,即
private Optional属性
,但这确实使整个处理复杂化了。我认为这是实现空对象模式的最严格的方法,必须由顶层决定。这不会编译,哪里定义了
GenericExample.nil()
?假设您实际上是指
GenericExample.NULL
那么您将无法将
GenericExample
分配给
GenericExample
。复制/粘贴问题,我修复了我的答案。+1我将只传递属性的
NULL
,而不是
新对象()
,因为如果属性恰好被暴露(只需执行
System.out.print(属性)
),则类型不安全。@PaulBellora,这一点很好,但很大程度上取决于用例。如果参数在构造函数中使用,可能它不能为null。@jan现在可以了,因为
属性
没有公开。但是如果有
public T getAttribute()
,那么例如,调用方可以执行
String str=GenericExamplenil().getAttribute()ClassCastException
。您的想法是正确的,但是存在多个编译错误。对不起,我在这里直接键入了答案,而没有通过编译器运行它。如果你能说出你认为编译错误是什么,那就更有用了,而不是暗示它们的存在……明白了,我只是做些编辑(我不想惹人生气)。主要是,
null
是一个关键字-如果你愿意,我会让你选择其他的。我不喜欢这个答案,因为它没有考虑到我的问题代码中没有空构造函数。类型安全的
nil()
方法很好,但我的主要问题是缺少默认构造函数。第一个答案也使用了
newobject()
,但注释指出使用
null
。但是我想使用
@Nonnull
并相信使用
null
来实现空对象模式是矛盾的。这取决于如何使用属性。您可以使用一个方法来访问该属性,如果该属性为null,则抛出一个异常,就像Scala的Option.get一样。感谢您对JDK的引用。我不清楚如何在我的问题代码中实现一个
新的EmptyGenericExample()
。当然可以使用
null
,查看其他注释…我开始认为这应该是唯一可行的null对象,也就是说,否则应该使用Guava Optional。