Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why am I able to use ReverseStringComparator.class as the value of the @SortedComparator annotation when it is not a primitive or a String?

@Entity
@Table(name = "student")
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // other fields

    @ElementCollection
    @CollectionTable(name = "studentImages")
    @MapKeyColumn(name = "file_name")
    @SortComparator(reverseSort.getClass()) // Error: Attribute value must be a constant
    @Column(name = "img_desc")
    private Map<String, String> images = new TreeMap<>();

    private static Comparator<String> reverseSort = Comparator.reverseOrder();
}

For the error denoted above, I have referred these posts:

These indicate that the value for an annotation must be a compile time constant and a compile time constant can only be a primitive or string. But the error indicated above could be resolved by defining an inner class like so:

@Entity
@Table(name = "student")
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // other fields

    @ElementCollection
    @CollectionTable(name = "studentImages")
    @MapKeyColumn(name = "file_name")
    @SortComparator(ReverseStringComparator.class) // Is this a compile time constant?
    @Column(name = "img_desc")
    private Map<String, String> images = new TreeMap<>();

    private class ReverseStringComparator implements Comparator<String> {
        @Override
        public int compare(String o1, String o2) {
            return o2.compareTo(o1);
        }
    }
}

Why am I able to use ReverseStringComparator.class as the value of @SortedComparator annotation when it is not a primitive or a String?
Also, is there any other way than defining and using an inner class here (using @SortComparator)?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You can use ReverseStringComparator.class because that is a class literal, which is explicitly listed as one of the allowed values for an annotation in JLS 9.7.1 Normal Annotations (bold emphasis from source, italic emphasis mine):

It is a compile-time error if the element type is not commensurate with the element value. An element type T is commensurate with an
element value v if and only if one of the following is true:

  • T is an array type E[], and either:

    • [removed for brevity]
  • T is not an array type, and the type of v is assignment compatible (§5.2) with T, and:

    • If T is a primitive type or String, then v is a constant expression (§15.29).
    • If T is Class or an invocation of Class (§4.5), then v is a class literal (§15.8.2).
    • If T is an enum class type (§8.9), then v is an enum constant (§8.9.1).
    • v is not null.

To highlight the specific rule that applies:

  • If T is Class or an invocation of Class (§4.5), then v is a class literal (§15.8.2).

As shown, not only primitive or String is allowed in an annotation, but also a class literal and an enum constant.

To answer your second question: no there is no other way to declare this using @SortComparator, as it expects a Class, and as detailed above, then only a class literal is allowed in the annotation.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading