Java变量类型和实例化

Java变量类型和实例化,java,Java,这已经困扰了我一段时间,还没有找到一个可以接受的答案。假设一个类是一个子类或实现一个接口,为什么我要使用父类或接口作为类型,即 List list = new ArrayList(); Vehicle car = new car(); 就ArrayList而言,现在只允许我访问List方法。如果我有一个将列表作为参数的方法,那么我可以将列表或ArrayList传递给它,因为ArrayList是一个列表。显然,在这个方法中,我只能使用List方法,但我看不到将其类型声明为List的理由。就我所见

这已经困扰了我一段时间,还没有找到一个可以接受的答案。假设一个类是一个子类或实现一个接口,为什么我要使用父类或接口作为类型,即

List list = new ArrayList();
Vehicle car = new car();
就ArrayList而言,现在只允许我访问List方法。如果我有一个将列表作为参数的方法,那么我可以将列表或ArrayList传递给它,因为ArrayList是一个列表。显然,在这个方法中,我只能使用List方法,但我看不到将其类型声明为List的理由。就我所见,它只是将我限制在代码中其他地方允许使用的方法上


如果List List=new ArrayList()比ArrayList List=new ArrayList()更好,我们将不胜感激。

如果您只需要父类型的功能,通常建议使用接口或父类型。这样做的目的是明确地说明您并不真正关心实现,从而使以后更容易将具体类替换为不同的类

Java集合类就是一个很好的例子:

如果您总是使用
列表
设置
等,而不是使用例如
ArrayList
,您可以在以后从
ArrayList
切换到
LinkedList
,如果您发现它提供了例如更好的性能。要做到这一点,只需更改构造函数(您甚至不必全部更改它们,您可以混合使用)。代码的其余部分仍然可以看到
List
的实例并继续工作

如果您确实显式地使用了
ArrayList
,则必须在使用它的任何地方更改它。如果您实际上并不需要一个
ArrayList
,那么在接口上使用它并没有什么好处

这就是为什么一般建议(例如,在“有效Java”(J.Bloch)中,第52项:“通过对象的接口引用对象”。)在可能的情况下只使用接口


另请参阅此相关问题:

如果您只需要父类型的功能,通常建议使用接口或父类型。这样做的目的是明确地说明您并不真正关心实现,从而使以后更容易将具体类替换为不同的类

Java集合类就是一个很好的例子:

如果您总是使用
列表
设置
等,而不是使用例如
ArrayList
,您可以在以后从
ArrayList
切换到
LinkedList
,如果您发现它提供了例如更好的性能。要做到这一点,只需更改构造函数(您甚至不必全部更改它们,您可以混合使用)。代码的其余部分仍然可以看到
List
的实例并继续工作

如果您确实显式地使用了
ArrayList
,则必须在使用它的任何地方更改它。如果您实际上并不需要一个
ArrayList
,那么在接口上使用它并没有什么好处

这就是为什么一般建议(例如,在“有效Java”(J.Bloch)中,第52项:“通过对象的接口引用对象”。)在可能的情况下只使用接口


另请参见此相关问题:

关键在于接口或基类限制您可以对变量执行的操作。例如,如果您稍后重构代码以使用该接口或基类的另一个实现,那么您就没有什么可担心的了——您不依赖于实际类型的标识


另一件事是,它通常使读取代码更容易,例如,如果方法的返回类型是
List
,则返回类型为
List
的变量更容易读取。关键是接口或基类限制了您可以对变量执行的操作。例如,如果您稍后重构代码以使用该接口或基类的另一个实现,那么您就没有什么可担心的了——您不依赖于实际类型的标识


另一件事是,它通常使读取代码变得更容易,例如,如果方法的返回类型是
List
,则返回类型为
List

的变量更容易读取。如果编写一个程序,该程序将列表传递给多个类和方法。现在,您希望在多线程环境中使用它。如果您明智地将所有内容声明为
列表
,现在可以对一行代码进行一次更改:

List list = Colllections.synchronizedList(new ArrayList());

如果将列表声明为
ArrayList
,则必须重新编写整个程序。这个故事的寓意是——始终按照代码所需的限制最少的接口进行编程。

您编写的程序可以在几个类和方法之间传递列表。现在,您希望在多线程环境中使用它。如果您明智地将所有内容声明为
列表
,现在可以对一行代码进行一次更改:

List list = Colllections.synchronizedList(new ArrayList());

如果将列表声明为
ArrayList
,则必须重新编写整个程序。故事的寓意是——始终将编程设置为代码所需的限制最少的接口。

接口指定契约(这件事做什么),实现类指定实现细节(它是如何做的)

根据良好的OOP实践,应用程序代码不应与其他类的实现细节相关联。使用接口使应用程序保持松散耦合(读:)


另外,使用接口可以让客户端代码在不同的实现中传递,并使用诸如
Collections.synchronizedList()
Collections.unmodifiableList()
等方法应用装饰器模式。

接口指定了一个契约(这件事是怎么做的),实现类指定实现细节(它是如何实现的)

根据良好的OOP实践,您的应用程序代码不应该与实现deta绑定