如何使用Java泛型从字符串中检索T
我试图将Java泛型用于我的特定用例。有一个泛型类如何使用Java泛型从字符串中检索T,java,generics,Java,Generics,我试图将Java泛型用于我的特定用例。有一个泛型类Node,在本例中会有很多实现类,比如NodeBoolean public abstract class Node<T> { T defaultValue; public Node(T defaultValue) { this.defaultValue = defaultValue; } protected abstract T par
Node
,在本例中会有很多实现类,比如NodeBoolean
public abstract class Node<T>
{
T defaultValue;
public Node(T defaultValue) {
this.defaultValue = defaultValue;
}
protected abstract T parse(String input) ;
public T getValue()
{
try
{
// here will be some logic to get String value from some db or any other source
String input = "true";
return parse(input);
} catch (Exception e) {
return defaultValue;
}
}
}
我在这种方法中面临的问题
节点
的构造函数有多个变体,那么所有实现类也需要为可见性定义它们。这个问题可以用Builder模式解决,但我只是想知道其他可能的解决方案parse
。我正在寻找一种基于defaultValue
的instanceof
来定义所有不同解析器的方法,在泛型类Node
自身的给定示例中。然后这个节点
类就不是抽象的
parse
方法的功能,该方法采用String
并根据用户需求返回T
值,同时创建节点
类本身的对象。通过这种方式,如果我只有一个出现的节点的特定对象类型,则可以创建,而无需定义任何新的实现类
parse
方法作为抽象方法,为什么不将函数传递到处理解析的节点中呢公共类节点{
私人T值;
私有函数解析器;
公共节点(T默认值,
函数分析器){
this.defaultValue=defaultValue;
this.parser=解析器;
}
公共T getValue()
{
//根据解析器的不同,每次调用它时重新解析可能会很昂贵!
尝试
{
//下面是一些从某个db或任何其他源获取字符串值的逻辑
字符串输入=“true”;
返回parser.apply(输入);
}捕获(例外e){
返回默认值;
}
}
}
现在可以通过执行此操作创建节点
Node<Boolean> node = new Node<>(s -> Boolean.parseBoolean(s))
Node Node=new Node->Boolean.parseBoolean
您还可以在解析器函数中设置默认值,从而无需将其存储在节点中—这取决于您的需求
public interface Function<I, O> {
O apply(I);
}
公共接口功能{
O适用第(I)款;
}
然后以某种方式实现它——具体类、匿名类,等等——正如您需要进行的解析所需
Node<Boolean> node = new Node<>(new Function<String, Boolean>() {
public Boolean apply(String s) {
return Boolean.parseBoolean(s);
}
});
Node节点=新节点(新函数(){
公共布尔应用(字符串s){
返回Boolean.parseBoolean;
}
});
编辑2
对于有关预定义类型的评论,您可以采取几种不同的方法
public class NodeFactory {
private static final Function <String, Boolean> BOOLEAN_PARSER = s -> Boolean.parseBoolean(s);
.// plus more for integers, double, etc, as required
private NodeFactory() {
// no-op
}
public static Node<Boolean> booleanNode(boolean defaultValue){
return new Node<Boolean>(defaultValue,
BOOLEAN_PARSER);
}
// plus more for integer, double, etc, as required
}
公共类节点属性{
私有静态最终函数BOOLEAN\u PARSER=s->BOOLEAN.parseBoolean(s);
.//根据需要为整数、双精度等加上更多
私有NodeFactory(){
//无操作
}
公共静态节点booleanNode(布尔默认值){
返回新节点(默认值,
布尔逻辑分析器);
}
//根据需要为整数、双精度等加上更多
}
或者你可以走延长线
public class BooleanNode extends Node<Boolean> {
public BooleanNode(boolean defaultValue) {
super(defaultValue,
s -> Boolean.parseBoolean(s)); // or use a static parser as in the factory example
}
}
公共类BooleanNode扩展节点{
公共布尔节点(布尔默认值){
超级(默认值,
s->Boolean.parseBoolean(s));//或使用工厂示例中的静态解析器
}
}
在任何情况下,保持
节点
非抽象性可以为您的用户提供很大的灵活性,但您的用例可能不需要这样做。您必须扩展节点
类吗?还是仅仅创建一个匿名类?它实际上是“允许用户定义解析方法”
在客户机中,我们将有以下内容
Node<Boolean> booleanNode = NodeFactory.createNode(Boolean.class);
Node<Integer> integerNode = NodeFactory.createNode(Integer.class);
Node booleanNode=NodeFactory.createNode(Boolean.class);
Node integerNode=NodeFactory.createNode(Integer.class);
也许您应该补充一点,这需要Java 8?使用这种方法,您可以有如下方便的方法来创建节点:公共静态节点boolNode(){return new Node(Boolean::parseBoolean);}
。(还请注意,您可以在这里使用方法引用语法。)(除了Java 1.0没有泛型或菱形,以防有人维护一个非常旧的代码库)@SteveChaloner,但我还想给用户一些常见的预定义解析器,这样他们就不必再编写它了。像节点node1=新节点->布尔值.parseBoolean(s))节点node2=新节点->布尔值.parseBoolean(s))
node1和node2都使用相同的解析器定义,因此我不想重复它,并使用一些预定义的允许我强制用户使用特定类型的特定解析器。如果您选择instanceof路径,这不会影响节点的泛型类型吗?是的,我需要扩展节点
类,因为所有实现类之间都应该共享很多逻辑。很抱歉,我认为这个问题措辞不恰当。我想问的是,您是否需要创建一个“完整类”(通常意味着一个专用的.java文件)或匿名类就足够了。仅供参考,创建匿名类类似于扩展抽象类,但是在另一个类中完成的。在我的建议中,所有扩展节点
类的类都将在NodeFactory
中声明,而不是在一个.javaf中声明
public class NodeFactory {
private static final Function <String, Boolean> BOOLEAN_PARSER = s -> Boolean.parseBoolean(s);
.// plus more for integers, double, etc, as required
private NodeFactory() {
// no-op
}
public static Node<Boolean> booleanNode(boolean defaultValue){
return new Node<Boolean>(defaultValue,
BOOLEAN_PARSER);
}
// plus more for integer, double, etc, as required
}
public class BooleanNode extends Node<Boolean> {
public BooleanNode(boolean defaultValue) {
super(defaultValue,
s -> Boolean.parseBoolean(s)); // or use a static parser as in the factory example
}
}
Node<Boolean> booleanNode = new Node<Boolean>(true) {
@Override
protected Boolean parse(String input) {
return Boolean.parseBoolean(input);
}
};
class NodeFactory {
public <T> static createNode(Class<T> classType) {
if (classType == Boolean.class) {
return newBooleanNode();
} else if (classType == Integer.class){
return newIntegerNode();
}
}
private Node<Boolean> newBooleanNode() {
return new Node<Boolean>(true) {
@Override
protected Boolean parse(String input) {
return Boolean.parseBoolean(input);
}
}
}
private Node<Integer> newIntegerNode() {
return new Node<Integer>(0) {
@Override
protected Boolean parse(String input) {
return Integer.parseInt(input);
}
}
}
}
Node<Boolean> booleanNode = NodeFactory.createNode(Boolean.class);
Node<Integer> integerNode = NodeFactory.createNode(Integer.class);