• 【Java语言特性】编程规范每日一学--20130911


    语言特性

    序列化

    序列化对象中的HashMapHashSetHashTable等集合不能包含对象自身的引用
    说明:如果一个被序列化的对象中,包含有HashMap、HashSet或HashTable集合,则这些集合中不允许保存当前被序列化对象的直接或间接引用。
    因为,这些集合类型在反序列化的时候,会调用到当前序列化对象的hashCode方法,而此时(序列化对象还未完全加载)计算出的hashCode有可能不正确,从而导致对象放置位置错误,破坏反序列化的实例。
    示例: 

    class Super implements Serializable 
    { 
            final Set<Super> set = new HashSet<Super>(); 
    } 
    
    final class Sub extends Super 
    { 
            private int id; 
    
            public Sub(int id) 
           { 
                    this.id = id; 
                    set.add(this); // 集合中引用了当前对象 
            } 
    
            public void checkInvariant() 
            { 
                    if (!set.contains(this)) 
                  { 
                            throw new AssertionError("invariant violated"); 
                  } 
            } 
    
            public int hashCode() 
           { 
                    return id; 
            } 
    
            public boolean equals(Object o) 
           { 
                    return (o instanceof Sub) && (id == ((Sub) o).id); 
            } 
    } 
    

      


    这个例子中,将当前对象(Sub对象)放入了对象中的HashSet中,在反序列化set时,因为id属性还未完成初始化,导致hashCode的结果为0,从而导致Sub对象在set中的位置放置错误,对象被破坏。

    实现Serializable接口的可序列化类应该显式声明 serialVersionUID
    说明: 如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java(TM) 对象序列化规范”中所述。
    不过,强烈建议所有可序列化类都显式声明 serialVersionUID 值,原因计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException
    。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用 private 修改器显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于立即声明类 –
    serialVersionUID 字段作为继承成员没有用处。
    示例:
    public class BeanType implements Serializable

    {    

    private static final long serialVersionUID = -2589766491699675794L;   

    }

    泛型

    在集合中使用泛型(v1.5+

    说明:Java 1.5版本中增加了泛型,在没有泛型之前,从集合中读取到的每一个对象都必须进行转换。如果有人不小心插入类型错误的对象,在运行时的转换处理就会出错。
    有了泛型之后,可以告诉编译器每个集合中接受哪些对象类型。编译器自动地为你的插入进行转化,并在编译时告知是否插入了类型错误的对象。
    示例:
    不好:错误的将Coin对象插入到samps集合中,直到从集合中获取coin时才收到错误提示
    private final Collection stamps = ...;
    stamps.add(new Coin(...));


    推荐:使用泛型,在编译时会提示类型错误
    private final Collection<Stamp> stamps = ...;
    stamps.add(new Coin(...));


    还有个好处是,从集合中获取元素时,不再需要进行手工类型转换。如下所示:
    for(Stamp s : stamps)

    {        

    ...

    }

    类的设计可优先考虑泛型(v1.5+
    说明:使用泛型类型,比使用需要在客户端代码中进行转换的类型来得更加安全,也更加容易。
    示例:如下所示,一个设计为泛型的stack类,在使用时,无需对栈中元素进行类型转换。

    public static void main(String[] args) 
    { 
                    Stack<String> stack = new Stack<String>(); 
                    for (String arg : args) 
                  { 
                            stack.push(arg); 
                  } 
    
                    while(!stack.isEmpty()) 
                  { 
                            System.out.println(stack.pop().toUpperCase()); 
                  } 
      } 
    

      方法的设计可优先考虑泛型(v1.5+
    说明:就如类可以从泛型中受益一般,方法也一样。静态工具方法尤其适合于泛型化。
    示例:如下所示,泛型方法就像泛型一样,使用起来比要求客户端转换输入参数并返回值的方法来得更加安全,也更加容易。

    public static <E> Set<E> union(Set<E> s1, Set<E> s2) 
    { 
            Set<E> result = new HashSet<E>(s1); 
            result.addAll(s2); 
            return result; 
    } 
            
    public static void main(String[] args) 
    { 
            Set<String> guys = new HashSet<String>(Arrays.asList("Tom", "Dick", "Harry")); 
            Set<String> stooges = new HashSet<String>(Arrays.asList("Larry", "Moe", "Curly")); 
            Set<String> aflCio = union(guys, stooges); 
            System.out.println(aflCio); 
    } 
    

      优先使用泛型集合,而不是数组(v1.5+

    说明:数组与泛型集合相比,有两个重要不同点。首先,数组是协变的(covariant),即SubSuper的子类型,则Sub[]也是Super[]的子类型。

    相反,泛型则是不可变的(invariant),对于任意两个类型Type1Type2List<Type1>既不是List<Type2>的子类型,也不是其超类型。其次,数组是具体化的,因此数组在运行时才知道并检查它们的元素类型约束。

    示例:如下代码是合法的,但执行时会报错


    Object[] objectArray = new
    Long[1];

    objectArray[0] =
    "I don't fit in"; //Throws ArrayStoreException


    而如下代码则会在编译时报错


    List<Object> objectList = new ArrayList<Long>(); //Incompatible types

    objectList.add("I don't fit
    in"
    );

  • 相关阅读:
    文档管理项目
    根据商品名称、价格区间检索商品的SQL语句
    ASP.NET MVC进阶三
    ASP.NET MVC进阶二
    vscode编写html,常用快捷方式与插件
    bpexpdate – 更改映像目录库中备份的截止日期以及介质目录库中介质的截止日期nbu
    Netbackup用于技术支持的问题报告(报障模版)
    netbackup 8.1安装注意事项
    金融的本质是什么?终于有人讲清楚了!(源于网络)
    nbu集群Alwayson相关问题
  • 原文地址:https://www.cnblogs.com/tjw-nau/p/3314029.html
Copyright © 2020-2023  润新知