Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果我需要序列化,我应该使用具体列表(例如ArrayList)还是(serializable)列表?_Java - Fatal编程技术网

Java 如果我需要序列化,我应该使用具体列表(例如ArrayList)还是(serializable)列表?

Java 如果我需要序列化,我应该使用具体列表(例如ArrayList)还是(serializable)列表?,java,Java,我们在办公室进行了讨论,无法理解哪种方法更好 我有一个类(SomeClass),它带有接收可序列化对象的方法。签名如下: public void someMethod(Serializable serializableObject){ ... } 我需要从另一个类调用这个方法,但我应该提供一些列表作为事实参数。有两种不同的方法 1.可序列化 private SomeClass SomeClass; 公共无效剂量测定法(){ List al=新的ArrayList(); al.添加(“文

我们在办公室进行了讨论,无法理解哪种方法更好

我有一个类(SomeClass),它带有接收可序列化对象的方法。签名如下:

public void someMethod(Serializable serializableObject){
    ...
}
我需要从另一个类调用这个方法,但我应该提供一些列表作为事实参数。有两种不同的方法

1.可序列化
private SomeClass SomeClass;
公共无效剂量测定法(){
List al=新的ArrayList();
al.添加(“文本”);
someClass.someMethod((可序列化)al);
}
2.ArrayList
private SomeClass SomeClass;
公共无效剂量测定法(){
ArrayList al=新的ArrayList();
al.添加(“文本”);
someClass.someMethod(al);
}
  • 第一个示例的好处是它遵循java的最佳实践,即:使用接口而不是引用类型的具体实现,任何程序员在阅读该源代码时都会理解,我们不需要ArrayList的特殊行为。我们需要它的唯一地方是可序列化行为,我们通过将其强制转换到可序列化接口来添加此行为。程序员可以简单地将列表的当前实现更改为其他可序列化的实现,例如LinkedList,而不会对该元素产生任何副作用,因为我们使用接口列表作为它的引用类型

  • 第二个示例的好处是,我们将ArrayList称为不仅具有列表行为而且具有可序列化行为的类。所以,如果有人查看这段代码并试图将ArrayList更改为List,他将收到一个编译时错误,这将减少程序员理解那里发生了什么的时间


  • 更新:我们无法更改someMethod签名。它来自第三方公司,我们不仅将其用于可序列化列表,还用于字符串、整数和其他一些可序列化对象

    1通常是正确的做法。然而,在这种情况下,我的意见将是弯曲,并宣布它为ArrayList。这避免了强制转换,并保证不会有人将列表的实现更改为不可序列化的实现。

    最好定义
    ArrayList
    ,因为它结合了两个接口-
    List+Serializable
    。你需要把它们放在一个地方

    public void write(Serializable s);
    

    这没什么大不了的,但使用接口对返回类型的应用应该更严格,而对局部变量的应用则不那么严格。

    当您需要的只是接口提供的方法时,您应该使用接口。(这在大多数情况下)但是,如果您需要多个接口,可以使用泛型,但最简单的方法是使用具体类型。

    我会更改
    someMethod
    的签名,以便它反映方法调用方的要求:

    public class SomeClass {
    
        public <T extends List<? extends Serializable> & Serializable> void someMethod(T t) {
    
        }
    
        public static void main(String[] args) {
            SomeClass test = new SomeClass();
            test.someMethod(new ArrayList<String>());   //Works
            test.someMethod(new ArrayList<Image>());   //Compile time error, Image is not Serializable
            List<String> l = null;
            test.someMethod(l); //Compile time error
        }
    }
    
    公共类SomeClass{
    
    公共你不能做(1)因为您不能随意更改列表实现类型,这就是这样做的全部想法。您只能使用实现可序列化的列表实现。因此,您可以在代码中表达这一点。

    在这种情况下,我只使用列表,而不必担心编译器无法保证您的对象是可序列化的zable(如果你在其他地方做对了,很可能是这样)

    请注意,以下类型的方法(接受可序列化参数)提供了错误的安全感,因为编译器永远无法保证需要序列化的整个对象图实际上是可序列化的

    public void write(Serializable s);
    
    考虑一个ArrayList(serializable),它包含不可序列化的对象。签名也可以是:

    public void write(Object o);
    
    这样你就不必担心那些无关的演员了


    也可以考虑,虽然你不能改变你正在使用的API的签名,但是你可以很容易地创建一个具有不同签名的包装器API。

    这可能是一个很好的解决方案,但是我们没有改变“<代码> SomeClass”的方法。
    signature,因为这个方法是由第三方库提供的,它应该接受所有类型的可序列化对象,而不仅仅是可序列化列表。我们的问题是:当我们必须将列表的instase传递给这种方法时,哪种方法会更好。啊,好的。看起来我没有完全理解在这种情况下,我会使用具体的类。这种方法的缺陷是调用方现在必须提供一个可序列化的列表(如ArrayList),这意味着调用方的签名必须接受相同的类型(如ArrayList)。这可能会在许多方法/类中级联,这将非常糟糕,因为它不必要地限制了可在这些方法中使用的列表类型。
    public void write(Object o);