当前位置: 首页 > 知识库问答 >
问题:

Java注释递归依赖

全誉
2023-03-14

我试图在注释中创建一些信息树结构。经过一些尝试和帮助(请参阅java注释中的类型层次结构),我转向了以下模型。

@interface Node {
  LogicalExpression logicalExpression() default LogicalExpression.AND;
  Attribute[] attributes() default {};
  Node[] nodes() default {};
}

该节点应允许我定义一级条件树。LogicalPression中的值定义子节点(属性和其他节点)之间的关系。问题是注释不允许递归依赖:

Cycle detected: the annotation type Node cannot contain attributes of the annotation type itself

即使我在Node和NodeList包含节点列表中添加了一些NodeList注释,循环依赖也会再次被识别。

@interface NodeList {
  Node[] nodes();
}

@interface Node {
  LogicalExpression logicalExpression() default LogicalExpression.AND;
  Attribute[] attributes() default {};
  NodeList nodes() default EmptyList;
}

循环注释定义有什么解决方案吗?

共有3个答案

穆单鹗
2023-03-14

我知道我有点晚了,但今天我不得不解决同一个问题,我发现这个问题没有真正的解决方案或变通方法。

但是,我设法使用以下结构“代理”递归:

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Expression
{
    Node value();

    SubExpression[] subExpressions() default {};
}

@Retention(RetentionPolicy.RUNTIME)
@interface SubExpression
{
    String id();

    String operator();

    Node[] nodes();
}

@Retention(RetentionPolicy.RUNTIME)
@interface Node
{
    String subExpression() default "";

    String name() default "";

    String value() default "";
}

@Expression(
    value = @Node(subExpression = "1"),
    subExpressions = {
        @SubExpression(id = "1", operator = "AND",
            nodes = {
                @Node(name = "responsible", value = "foo"),
                @Node(subExpression = "2")
            }),
        @SubExpression(id = "2", operator = "OR",
            nodes = {
                @Node(name = "status", value = "closed"),
                @Node(name = "visibility", value = "public")
            }),
    })
public class TestAnnotationRecursion
{
    public static void main(String[] args)
    {
        Expression expression = TestAnnotationRecursion.class.getAnnotation(Expression.class);

        Map<String, SubExpression> subExpressionMap = Arrays.stream(expression.subExpressions())
            .collect(Collectors.toMap(x -> x.id(), x -> x));

        String result = parseNode(expression.value(), subExpressionMap);

        System.out.println(result);
    }

    public static String parseNode(Node node, Map<String, SubExpression> subExpressionMap)
    {
        String subExpressionId = node.subExpression();
        if(subExpressionId.isEmpty())
        {
            return node.name() + " = '" + node.value() + "'";
        }

        SubExpression subExpression = subExpressionMap.get(subExpressionId);

        return Arrays.stream(subExpression.nodes())
            .map(n -> parseNode(n, subExpressionMap))
            .collect(Collectors.joining(" " + subExpression.operator() + " ", "(", ")"));
    }
}

评估结果如下:

(responsible = 'foo' AND (status = 'closed' OR visibility = 'public'))

虽然它的易读性值得怀疑,但我认为这是我们在不允许显式递归时可以实现的最佳妥协。

宗苗宣
2023-03-14

由于上述Java中的限制,您无法定义无限递归定义。但是您可以支持一些固定深度的结构,这感觉像递归结构(直到达到深度限制为止)

这是深度3的布尔表达式语言的示例:

public @interface Expression {
    public Term value () default @Term;
    public And and () default @And;
    public Or or () default @Or;
}

定义每个级别的“和”操作:

public @interface And {
    public boolean not () default false;

    public Term[] value () default {};

    public Or1[] or1 () default {};
    public Or2[] or2 () default {};

    public And1[] and1 () default {};
    public And2[] and2 () default {};
}

public @interface And1 {
    public boolean not () default false;

    public Term[] value () default {};

    public Or2[] or2 () default {};

    public And2[] and2 () default {};
}

public @interface And2 {
    public boolean not () default false;
    public Term[] value () default {};
}

定义每个级别的“或”操作:

public @interface Or {
    public boolean not () default false;

    public Term[] value() default {};

    public Or1[] or1 () default {};
    public Or2[] or2 () default {};

    public And1[] and1 () default {};
    public And2[] and2 () default {};
}

public @interface Or1 {
    public boolean not () default false;

    public Term[] value () default {};

    public Or2[] or2 () default {};

    public And2[] and2 () default {};
}

public @interface Or2 {
    public boolean not () default false;
    public Term[] value () default {};
}

现在我们可以这样使用它:

@Expression(@Term("a"))
class A{}

// a or b
@Expression(or=@Or({@Term("a"), @Term("b")}))
class B{}


// a or (not(b and c))
@Expression(or=@Or(
    value=@Term("a"),
    and1=@And1(not=true, value={
        @Term("b"),
        @Term("b")
    })
))
class B{}

正如您所看到的,这个想法是在每次添加嵌套表达式时增加运算符注释的索引。

刁跃
2023-03-14

这是因为这个错误。

注释的继承性、多态性、循环检测的局限性。。。线程讨论它。

您可以创建如下内容

@interface NodeInfo {
    LogicalExpression logicalExpression() default LogicalExpression.AND;
    Attribute[] attributes() default {};
}


@interface Node {
    NodeInfo[] nodes() default {};
}
 类似资料:
  • 我实现了一个非常简单的递归方法,将两个数相乘在一起。我很难理解递归的基本知识。 有没有人能向我解释(如果可能的话,逐行解释)这段代码是如何工作的?我尤其感到困惑的是,基大小写被写为返回0,而实际上返回的是实际的乘法。 谢谢你的帮助

  • 问题内容: 丈夫.java 妻子.java Service.java 当我使用spring数据jpa从数据库中查询丈夫时,结果发生无限递归,参见下图。使用@OneToOne注释时出了什么问题?有人可以给我一些建议吗?或者我以错误的方式使用了注释。 图片 问题答案: 这是一个已知问题,当您具有双向关系时,杰克逊将尝试从另一侧序列化一侧的每个引用,以便逻辑上具有无限递归。 解决方案:有很多解决方案,可

  • 问题内容: 请分步说明递归; 问题答案: 如果您使用的是IDE,则可以使用调试器,亲眼看看发生了什么。 无论如何,让我们尝试一下,当调用递归方法时会发生什么:您使用8()调用该方法: -> 8 ->以8/2 = 4再次调用方法 -> 4 >以4/2 = 2再次调用方法 -> 2 >用2/2 = 1再次调用方法 ->继续上一个通话,() >用2/2 = 1再次调用方法 ->继续上一个通话,() 方法

  • 假设我有一个带有属性的注释: 我想创建一个包含多个元注释的复合注释,包括一个带有属性的注释 有没有一种方法可以将复合注释的属性传递给其中一个元注释? 例如,类似这样的东西: 这相当于,但比 谢谢! PS为我对示例注释的错误选择表示歉意-我没有javax。注射@记住命名注释,只是一些具有属性的任意注释。 谢谢大家的回答/评论。 这显然是不可能的。然而,碰巧我的案例有一个简单的解决方法,我将与大家分享

  • 我有几个项目,没有一个是在Maven框架下。 但是我在项目依赖领域面临一个问题。 让我们用一个非常简单的例子来假设; 我理解这种情况很正常,因为不在类路径上。虽然,我说的是一个更复杂的层次树,我不希望高层项目在他下面添加所有的子依赖树。 提前感谢!

  • 注释是对程序语言的说明,有助于开发者和用户之间的交流,方便理解程序。 注释不是编程语句,因此被编译器忽略。 Java 支持以下三种注释方式: 1)单行注释 以双斜杠“//”标识,只能注释一行内容,用在注释信息内容少的地方。打开 Eclipse,在 Java 代码中使用单行注释,如图 1 所示。 图 1  单行注释 2)多行注释 包含在“/*”和“*/”之间,能注释很多行的内容。为了可读性比较好,一