JAXBJava7与Java8的区别

JAXBJava7与Java8的区别,jaxb,Jaxb,我发现了在Java7和Java8上处理Jaxb的另一个区别。我已经将问题简化为一个简单的示例,代码应该作为单个类运行。(更改了类别,使其与工作无关等)当列表的setter被解组器调用时: 我的问题实际上是一个变体 对列表访问器进行编码以省略 编码JaxB时,是否使用Setter?(因为它似乎可以处理 通过Getter列表) 是否有推荐的替代方法 在Java7中运行时,将使用列表中的数据调用setter。 在Java8中运行时,setter将仅使用空列表对象进行调用,该对象显然在以后的解组过程中填

我发现了在Java7和Java8上处理Jaxb的另一个区别。我已经将问题简化为一个简单的示例,代码应该作为单个类运行。(更改了类别,使其与工作无关等)当列表的setter被解组器调用时: 我的问题实际上是一个变体

  • 对列表访问器进行编码以省略 编码JaxB时,是否使用Setter?(因为它似乎可以处理 通过Getter列表)
  • 是否有推荐的替代方法
  • 在Java7中运行时,将使用列表中的数据调用setter。 在Java8中运行时,setter将仅使用空列表对象进行调用,该对象显然在以后的解组过程中填充。 我所经历的不同之处在于,我不能让setter对列表进行任何处理,而是必须有一个仅在对整个对象进行解组后才调用的进程。或者总结一下,“不要在setter中进行任何处理”。 示例如下:(三个类)-在Java7下,返回的结果是在setter中找到的列表上的第一个“album”标题。在Java8下,返回null。 代码应该作为一个没有依赖项的单一类运行。 如果在Java 7中运行,则显示的“第一张专辑”标题为“Abbey Road”。 如果在Java 8中运行,“第一张专辑”标题为空

    import java.io.ByteArrayInputStream;
    import java.io.InputStream;
    import java.util.List;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Unmarshaller;
    import javax.xml.bind.annotation.XmlAttribute;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlType;
    
    public class MainJaxbCase {
        public static void main( String[] args ) {
            new MainJaxbCase().testIt();
        }
        private void testIt() {
            try {
            AlbumLib   myLib = (AlbumLib) loadJaxbDocFromString( inXmlStr, AlbumLib.class );
            System.out.println("category:"+ myLib.getCateg());
            List<AlbumItm> albumList = myLib.getAlbumList();
            System.out.println("AlbumList size is " + albumList.size());
            System.out.println("The first album is titled:"
                    + myLib.getFirstAlbumTitle() 
                    + "- shows \"null\" if using Java 8,  \"Abbey Road\" if using Java 7"
                 );
            } catch ( Exception e ) {
                System.out.println( e.getClass().getSimpleName() + ", msg:" + e.getMessage() );
                e.printStackTrace();
            }
        }
        private final String inXmlStr = 
                "<my_lib categ='albums'>"
                + "  <album title='Abbey Road'/> "
                + "  <album title='Revolver'/>"
                + "  <album title='Sgt.Pepper'/>"
                + "</my_lib>";      
    
    
        private Object loadJaxbDocFromString ( String inStr, Class<?> clazz ) throws Exception {
            Object result = null;
            try {
                InputStream is = new ByteArrayInputStream( inStr.getBytes() );
                result = unmarshal( is, clazz  );
            } catch ( Exception e ) {
                String msg = this.getClass().getSimpleName() + ".loadJaxbDocFromResource() caught " + e.getClass().getSimpleName() + " msg:" + e.getMessage();
                throw new Exception(msg);
            }
            return result;
        }
        private Object unmarshal( InputStream prmIs, Class<?> clazz ) throws Exception{
            Object obj = null;
            try {
                JAXBContext jaxbContext = JAXBContext.newInstance( clazz );
                Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
                obj = jaxbUnmarshaller.unmarshal( prmIs );
            } catch ( Exception e ) {
                String msg = this.getClass().getSimpleName() + " caught " + 
                        e.getClass().getSimpleName() + ", msg:" + e.getMessage();
                msg += " Trying to Unmarshall class " + clazz.getName();
                System.err.println(msg);
                e.printStackTrace();
                throw new Exception(msg);
            }
            return obj;
        }
    }
    
    
    
    @XmlRootElement ( name= "my_lib")
    class AlbumLib {
        private String      categ;
        private List<AlbumItm> albumList;
        private String firstAlbumTitle;
    
        @XmlAttribute ( name="categ")
        public String getCateg() {
            return this.categ;
        }
        public void setCateg( String val ) {
            this.categ=val;
        }
    
        @XmlElement ( name="album")
        public List<AlbumItm> getAlbumList() {
            return this.albumList;
        }
        public void setAlbumList( List<AlbumItm> newList ) {
            if ( newList != null && newList.size() > 0 ) {
                firstAlbumTitle = newList.get(0).getTitle();
            }
            this.albumList = newList;
        }
        public String getFirstAlbumTitle() {
            return this.firstAlbumTitle;
        }
    }
    
    
    
    @XmlType(name = "album")
    class AlbumItm {
        private String title;
        @XmlAttribute ( name="title" )
        public String getTitle() {
            return this.title;
        }
        public void setTitle(String val ) {
            this.title = val;
        }
    }
    
    import java.io.ByteArrayInputStream;
    导入java.io.InputStream;
    导入java.util.List;
    导入javax.xml.bind.JAXBContext;
    导入javax.xml.bind.Unmarshaller;
    导入javax.xml.bind.annotation.XmlAttribute;
    导入javax.xml.bind.annotation.xmlement;
    导入javax.xml.bind.annotation.XmlRootElement;
    导入javax.xml.bind.annotation.XmlType;
    公共类MainJaxbCase{
    公共静态void main(字符串[]args){
    新的MainJaxbCase().testIt();
    }
    私有无效测试(){
    试一试{
    AlbumLib myLib=(AlbumLib)loadJaxbDocFromString(inXmlStr,AlbumLib.class);
    System.out.println(“类别:+myLib.getCateg());
    List albumList=myLib.getAlbumList();
    System.out.println(“AlbumList大小为”+AlbumList.size());
    System.out.println(“第一张专辑的标题是:
    +myLib.getFirstAlbumTitle()
    +-如果使用Java 8,则显示“null”;如果使用Java 7,则显示“Abbey Road”
    );
    }捕获(例外e){
    System.out.println(e.getClass().getSimpleName()+”,msg:“+e.getMessage());
    e、 printStackTrace();
    }
    }
    私有最终字符串inXmlStr=
    ""
    + "   "
    + "  "
    + "  "
    + "";      
    私有对象loadJaxbDocFromString(String inStr,Class clazz)引发异常{
    对象结果=空;
    试一试{
    InputStream is=newbytearrayinputstream(inStr.getBytes());
    结果=解组(is,clazz);
    }捕获(例外e){
    字符串msg=this.getClass().getSimpleName()+”.loadJaxbDocFromResource()捕获“+e.getClass().getSimpleName()+”msg:+e.getMessage();
    抛出新异常(msg);
    }
    返回结果;
    }
    私有对象解组(InputStream prmIs,类clazz)引发异常{
    objectobj=null;
    试一试{
    JAXBContext JAXBContext=JAXBContext.newInstance(clazz);
    解组器jaxbUnmarshaller=jaxbContext.createUnmarshaller();
    obj=jaxbunmarshal.unmarshal(prmIs);
    }捕获(例外e){
    字符串msg=this.getClass().getSimpleName()+“捕获”+
    e、 getClass().getSimpleName()+”,消息:“+e.getMessage();
    msg+=“正在尝试解组类”+clazz.getName();
    系统错误打印项次(msg);
    e、 printStackTrace();
    抛出新异常(msg);
    }
    返回obj;
    }
    }
    @XmlRootElement(name=“my_lib”)
    类库{
    私人字符串类别;
    私人名单;
    私有字符串标题;
    @XmlAttribute(name=“categ”)
    公共字符串getCateg(){
    返回此.categ;
    }
    公共无效设置类别(字符串val){
    这个.categ=val;
    }
    @xmlement(name=“album”)
    公共列表getAlbumList(){
    返回此.album列表;
    }
    public void setAlbumList(列表新建列表){
    if(newList!=null&&newList.size()>0){
    firstAlbumTitle=newList.get(0.getTitle();
    }
    this.albumList=newList;
    }
    公共字符串getFirstAlbumTitle(){
    返回此.firstAlbumTitle;
    }
    }
    @XmlType(name=“album”)
    类相册{
    私有字符串标题;
    @XmlAttribute(name=“title”)
    公共字符串getTitle(){
    返回此.title;
    }
    公共void setTitle(字符串val){
    this.title=val;
    }
    }
    

    出现这个问题是因为我们的代码在切换到Java 8时表现出细微(但很重要)的差异,但没有任何明显的异常。

    我们遇到了与您相同的问题,如上所述

  • 编码列表访问器的推荐做法是在编码JaxB时完全省略Setter吗?(因为它似乎通过Getter处理列表)
  • 是否有推荐的替代方法
  • 重点不是“省略Setter”,而是不要为Setter添加更多功能。塞特只是塞特,仅此而已。添加更多的逻辑违反了setter的“单一责任规则”,并且该函数的名称与它实际执行的不同,可能会出现更多的错误

    当提到推荐的方法时,没有一个标准答案涵盖所有情况。考虑到不存在构造函数init(这对JAXB来说有点困难),并且在setter之后需要更多的逻辑,我们有两个方向可以选择:

    • 使用
      XmlAdapter
      自定义结构以添加逻辑:
    • 没有添加任何逻辑