Java 通用单件工厂

Java 通用单件工厂,java,generics,Java,Generics,在网上阅读时,我遇到了以下问题: public interface UnaryFunction<T> { T apply(T arg); } ....... private static UnaryFuntion<Object> ID_FUNC = new UnaryFunction<Object> {

在网上阅读时,我遇到了以下问题:

public interface UnaryFunction<T>
{
    T apply(T arg);
}

.......


private static UnaryFuntion<Object> ID_FUNC = new UnaryFunction<Object>
                                          {
                                             Object apply(Object arg)
                                             {
                                                  return arg;
                                             }
                                          };

public static <T> UnaryFunction<T> idFunction()
{
    return (UnaryFunction<T>) ID_FUNC;
}
我的问题是,为什么我们需要一个通用的
接口

仅凭以下几点就足够了:

public interface UnaryFunction
{
    Object apply(Object arg); //Object as return type and argument type, instead.
}
??这里有什么必要使用泛型

那么,什么是真正的通用单件工厂?它有什么好处


谢谢。

在您的示例中,通用单例工厂是idFunction。如果没有它,您将在两个丑陋的备选方案中进行选择,或者在使用它的任何地方都需要石膏,如下所示:

public class ExampleWithoutGenericSingletonFactory {

    static UnaryFunction<Object> ID_FUNC = new UnaryFunction<Object>() {
        public Object apply(Object arg) {
            return arg;
        }
    };

    public static void main(String[] args) {
        BigDecimal b = new BigDecimal("1234.1241234");
        BigDecimal b1 = (BigDecimal)(ID_FUNC.apply(b)); // have to cast here >_<
        System.out.println("engineeringstring val of b1 = " 
        + b1.toEngineeringString());
    }
}
没有GenericSingleTonFactory的公共类示例{
静态一元函数ID_FUNC=新一元函数(){
公共对象应用(对象参数){
返回arg;
}
};
公共静态void main(字符串[]args){
BigDecimal b=新的BigDecimal(“1234.1241234”);
BigDecimalB1=(BigDecimal)(ID_FUNC.apply(b));//必须在此处强制转换>_<
System.out.println(“b1的工程字符串值=”
+b1.toEngineeringString());
}
}
或者为您想要支持的每种类型分别实施:

public static UnaryFunction<String> ID_FUNC_STRING = new UnaryFunction<String>() {
    public String apply(String arg) {
        return arg;
    }
};

public static UnaryFunction<Number> ID_FUNC_NUM = new UnaryFunction<Number>() {
    public Number apply(Number arg) {
        return arg;
    }
};

public static UnaryFunction<BigDecimal> ID_FUNC_DECIMAL = new UnaryFunction<BigDecimal>() {
    public Number apply(BigDecimal arg) {
        return arg;
    }
};
public static UnaryFunction ID\u FUNC\u STRING=new UnaryFunction(){
公共字符串应用(字符串参数){
返回arg;
}
};
公共静态一元函数ID\u FUNC\u NUM=新的一元函数(){
公共编号应用(编号arg){
返回arg;
}
};
公共静态一元函数ID\u FUNC\u DECIMAL=新一元函数(){
应用公共编号(BigDecimal参数){
返回arg;
}
};
给你一些难看的冗长的剪切粘贴代码,每种类型都有一个不同的名称,你必须保持笔直。但是,由于您知道它是一个纯函数,并且类型被删除,因此您只能有一个实现(ID_FUNC)并让singleton factory idFunction返回它

如果有一个函数实现,您希望能够在其上指定不同的类型,并且该实现是无状态的,则可以使用此选项

这个例子可能更好,因为它只调用从函数调用返回的对象上的toString,工厂并没有带来任何好处。如果示例显示对返回的对象使用特定于类型的方法,那么好处可能更明显


当你这样做时,会出现一个未经检查的施法警告,但是可以安全地抑制它(这是Joshua Bloch的建议)。

显然,OP在《有效Java》第二版中讨论了一些内容。第27项:支持泛型方法第131页?@NathanHughes是的,先生。你很博学,谢谢你的回复。但非通用接口可以吗?就像我上面建议的例子一样,不使用
T
作为返回值,也不使用arg值,而是使用
Object
?@Unheilig:您可以,但您必须在使用它时进行强制转换。这个例子没有强制转换,因为它除了调用toString之外什么都不做,但是如果你想用它做任何特定于子类型的事情,你需要强制转换。我最困惑的部分是:在
接口上
在函数定义中声明为
t
(即
ID\u FUNC
)它被声明为
Object
,因此我的问题是,为什么作者选择使用通用接口,然后将函数声明为
Object
,而不是
interface
@Unheilig中的
T
:因为他只想实现一次函数,并且使用不带强制转换的返回类型。idFunction的赋值从返回值被赋值的变量中推断出类型。“对不起,如果我没有回答这个问题,”添加了另一个示例。换句话说,他为什么不这样做:
private static UnaryFunction ID\u FUNC=new UnaryFunction{Object apply(t arg){return arg;}?谢谢
public static UnaryFunction<String> ID_FUNC_STRING = new UnaryFunction<String>() {
    public String apply(String arg) {
        return arg;
    }
};

public static UnaryFunction<Number> ID_FUNC_NUM = new UnaryFunction<Number>() {
    public Number apply(Number arg) {
        return arg;
    }
};

public static UnaryFunction<BigDecimal> ID_FUNC_DECIMAL = new UnaryFunction<BigDecimal>() {
    public Number apply(BigDecimal arg) {
        return arg;
    }
};