从 注解和继承 到 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>

解释如下:

  • 要想每个子类去控制父类成员,必须把父类标记成@XmlTransient,而且子类@XmlType的propOrder要负责所有自己要序列化的成员
  • 类Son的@XmlAccessorType标注为XmlAccessType.PUBLIC_MEMBER,意味着Son只序列化Public字段。加上父类的public成员,Son共有3个public成员,所以@XmlType(propOrder)写了三个成员的顺序。
  • 类Daughter的@XmlAccessorType标注为XmlAccessType.FIELD,意味着所有父类和自己的成员都会序列化,于是标记四个成员的顺序。

忽略dtd

import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource; import org.xml.sax.InputSource;
import org.xml.sax.XMLReader; public class Demo2 { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(MyBean.class); SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
spf.setFeature("http://xml.org/sax/features/validation", false);
spf.setNamespaceAware(true); XMLReader xmlReader = spf.newSAXParser().getXMLReader();
InputSource inputSource = new InputSource(
new FileReader("myfile.xml"));
SAXSource source = new SAXSource(xmlReader, inputSource); Unmarshaller unmarshaller = jc.createUnmarshaller();
MyBean foo = (MyBean) unmarshaller.unmarshal(source);
}
}

从 注解和继承 到 JAXB中的注意事项的更多相关文章

  1. JAXB中的@XmlRootElement注解详解

    @Retention(value=RUNTIME) @Target(value=TYPE) public @interface XmlRootElement @Inherited @Retention ...

  2. Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用

    Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用 Spring 系列目录(https://www.cnblogs.com/binarylei/p/1019 ...

  3. 【Java EE 学习 24 下】【注解在数据库开发中的使用】【反射+注解+动态代理在事务中的应用service层】

    一.使用注解可以解决JavaBean和数据库中表名不一致.字段名不一致.字段数量不一致的问题. 1.Sun公司给jdbc提供的注解 @Table.@Column.@Id.@OneToMany.@One ...

  4. 继承在WCF中的问题和解决办法

    1. 问题 假设有代码如下: [ServiceContract] public interface IA { [OperationContract] string M1(); } [ServiceCo ...

  5. android开发中关于继承activity类中方法的调用

    android开发中关于继承activity类中的函数,不能在其他类中调用其方法. MainActivity.java package com.example.testmain; import and ...

  6. C#继承机制 C#中的继承符合下列规则

    1.继承是可传递的.如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员.Object 类作为所有类的基类. 2.派生类应当是对基类的扩展.派生类可以添加新的成员, ...

  7. python基础语法15 面向对象2 继承,多态,继承json模块中JSONEncoder,并派生出新的功能

    继承 1.什么是继承? 继承是一种新建类的方式,新建的类称之为子类或派生类,继承的父类称之为基类或超类. - 在Python中,一个子类可以继承多个父类.(面试可能会问) - 在其它语言中,一个子类只 ...

  8. C++ //多继承语法 C++中允许一个类继承多个类

    1 //多继承语法 C++中允许一个类继承多个类 2 #include <iostream> 3 #include <string> 4 using namespace std ...

  9. 关于JDBC学习过程中的注意事项(分享自己犯过的错误,写给初学JDBC的小伙伴的八条建议)

    关于JDBC学习过程中的注意事项(分享自己犯过的错误,写给初学JDBC的小伙伴的八条建议) 前言:最近在学习JDBC,总结了几个小问题,特地分享给大家,让大家不要犯这样的错误,也希望大家养成学会总结的 ...

随机推荐

  1. h3c_7506e引擎主备镜像同步

    备份引擎的镜像文件不匹配会导致主引擎无法识别备引擎解决方法:1.备份主引擎上的启动文件同步到备引擎    ftp ip地址    get 在ftp服务器的镜像文件名 为其命名为本地文件(均为源文件名) ...

  2. siimpleHttpServer 快速建立一个文件服务器

    利用 SimpleHTTPServer 可以非常快速的建立一个http服务器,如果有同学在做共享文件时遇到了困难,只需要一行代码,即可建站完成. 在想要映射的文件夹目录内,执行命令行 python - ...

  3. Java(日期、随机数、系统工具类)

    Date类 一般用于获取时间 Date date1 = new Date();//获取当前系统时间 Date date2 = new Date(10000);//获取从标准基准时间起10000毫秒的时 ...

  4. update_engine-DownloadAction(一)

    通过update_engine-整体结构(一),(二),(三)对update_engine整体的运行机制有了一定的认识之后.开始逐个分析重要的Action.先从DownloadAction开始分析. ...

  5. 自己DIY出来一个JSON结构化展示器

    说来也巧,这个玩意,一直都想亲手写一个,因为一直用着各种网上提供的工具,觉得这个还是有些用途,毕竟,后面的实现思路和原理不是太复杂,就是对json的遍历,然后给予不同节点类型以不同的展现风格. 我这次 ...

  6. 窗口关闭时弹出内存不能为read

    出现这个错误的原因是:某个指针类型的变量或对象,其记录的内容不可用,但进程对其进行了访问.可能由于:指针类型的变量或对象未被赋值就被使用:或者已经被正常释放后,又被访问所致.由于是在结束进程时报这样的 ...

  7. Spring boot加载REACTIVE源码分析

    一,加载REACTIVE相关自动配置 spring boot通过判断含org.springframework.web.reactive.DispatcherHandler字节文件就确定程序类型是REA ...

  8. 配置中心Nacos

    Nacos 是阿里巴巴2018年7月份开源的项目,如其名, Naming Configuration Service ,专注于服务发现和配置管理领域. Nacos 是什么?上面已经大概介绍了,更多详细 ...

  9. 如何限制指定textFiled第三方输入法切换

    在有些项目中需要用到输入纯数字的键盘,并且还不能切换到第三方输入法! textFiled.secureTextEntry = YES; [textFiled addTarget:self action ...

  10. jumpservice配置:快速入门

    快速入门 说明 到 Jumpserver 会话管理-终端管理 查看 Coco Guacamole 等应用是否在线 一.系统设置 1.1 基本设置 # 修改 url 的"localhost&q ...