从 注解和继承 到 JAXB中的注意事项

时间:2022-01-06 15:56:42

从 注解和继承 到 JAXB中的注意事项

注解在继承中的行为

如果一个父类添加了一个注解,子类是否能取到这个注解呢?如下

package inheritance;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class Main {
    public static void main(String[] args) {
        Type t = Son.class.getAnnotation(Type.class);
        if (t != null) {
            System.out.println(t.name());
        }
    }
}

@Type(name = "Father")
class Father {
}

class Son extends Father {
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Type {
    String name();
}

如上代码,注解不会被子类继承。如果想注解也被子类继承,该怎么办呢?

只需要在注解定义里修改一下,添加@Inherited

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Type {
    String name();
}

关于@Inherited需要注意的

  • 只能作用于继承,不能作用于接口实现

JAXB 的注解

@XmlAccessorType用于标注该类的成员是否用于绑定到XML,例如XmlAccessType.PUBLIC_MEMBER表示,所有public字段都会被绑定(除去@XmlElement和@XmlTransient的标记,他们优先级更高)。
这个注解就是标记了@Inherited

我们知道序列化顺序可以由@XmlType(propOrder)去设置,那么继承后是什么样子呢?

package inheritance;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

public class Main {
    public static void main(String[] args) throws Exception {
        JAXBContext ctx = JAXBContext.newInstance(Son.class);
        Marshaller ms = ctx.createMarshaller();
        ms.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        ms.marshal(new Son(), System.out);
    }
}

@XmlRootElement(name = "Father")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlType(propOrder = { "two", "one" })
class Father {
    @XmlElement
    private String one = "one";
    @XmlElement
    public String two = "two";
}

@XmlRootElement(name = "Son")
@XmlAccessorType(XmlAccessType.NONE)
@XmlType(propOrder = { "four", "three" })
class Son extends Father {
    @XmlElement
    public String three = "three";
    @XmlElement
    public String four = "four";
}

上述代码会输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Son>
    <two>two</two>
    <one>one</one>
    <four>four</four>
    <three>three</three>
</Son>

即**父类成员先序列化,再子类成员,顺序由各自类的@XmlType设置的顺序决定**

那么如果子类一定想控制父类成员的序列化顺序,而且不同的子类还想各自定义父类成员的序列化顺序怎么办?(CNM, 屁事真多)

好吧,JAXB还是可以满足这种屁事儿的。

package inheritance;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

public class Main {
    public static void main(String[] args) throws Exception {
        go(Son.class);
        go(Daughter.class);
    }

    private static void go(Class<?> clz) throws Exception {
        JAXBContext ctx = JAXBContext.newInstance(clz);
        Marshaller ms = ctx.createMarshaller();
        ms.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        ms.marshal(clz.newInstance(), System.out);
    }
}

@XmlTransient
class Father {
    @SuppressWarnings("unused")
    private String one = "one";
    public String two = "two";
}

@XmlRootElement(name = "Son")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlType(propOrder = { "four", "three", "two" })
class Son extends Father {
    @XmlElement
    public String three = "three";
    @XmlElement
    public String four = "four";
}

@XmlRootElement(name = "Daughter")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = { "one", "two", "three", "four" })
class Daughter extends Father {
    @XmlElement
    public String three = "three";
    @XmlElement
    public String four = "four";
}

上述代码将输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Son>
    <four>four</four>
    <three>three</three>
    <two>two</two>
</Son>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Daughter>
    <one>one</one>
    <two>two</two>
    <three>three</three>
    <four>four</four>
</Daughter>

解释如下: