Java变量类型和实例化
这已经困扰了我一段时间,还没有找到一个可以接受的答案。假设一个类是一个子类或实现一个接口,为什么我要使用父类或接口作为类型,即
List list = new ArrayList();
Vehicle car = new car();
就ArrayList而言,现在只允许我访问List方法。如果我有一个将列表作为参数的方法,那么我可以将列表或ArrayList传递给它,因为ArrayList是一个列表。显然,在这个方法中,我只能使用List方法,但我看不到将其类型声明为List的理由。就我所见,它只是将我限制在代码中其他地方允许使用的方法上
如果List List=new ArrayList()比ArrayList List=new ArrayList()更好,我们将不胜感激
# 1 楼答案
关键是接口或基类限制对变量的操作。例如,如果您稍后重构代码以使用该接口或基类的另一个实现,那么您就没有什么可担心的了——您不依赖于实际类型的标识
另一件事是,它通常使读取代码更容易,例如,如果您的方法的返回类型是
List
,您可能会发现返回类型为List
的变量更具可读性# 2 楼答案
如果您只需要父类型的功能,通常建议使用接口或父类型。这样做的目的是明确地说明您并不真正关心实现,从而使以后更容易将具体类替换为不同的类
Java集合类就是一个很好的例子:
如果您总是使用
List
、Set
等来代替例如ArrayList
,那么您可以稍后从ArrayList
切换到LinkedList
,如果您发现它提供了例如更好的性能。要做到这一点,只需更改构造函数(您甚至不必全部更改它们,您可以混合使用)。代码的其余部分仍然可以看到List
的实例并继续工作如果您确实显式地使用了
ArrayList
,则必须在使用它的任何地方都对其进行更改。如果您实际上并不特别需要ArrayList
,那么在接口上使用它并没有什么好处这就是为什么一般建议使用它(例如,在“有效Java”(J.Bloch)中,第52项:“通过对象的接口引用对象”。)尽可能只使用接口
另见这一相关问题:Why classes tend to be defined as interface nowadays?
# 3 楼答案
接口指定契约(这件事做什么),实现类指定实现细节(它是如何做的)
根据良好的OOP实践,应用程序代码不应与其他类的实现细节相关联。使用接口使应用程序保持松散耦合(读取:Coupling)
此外,使用接口可以让客户机代码在不同的实现中传递,并使用
Collections.synchronizedList()
、Collections.unmodifiableList()
等方法应用装饰器模式# 4 楼答案
您可以编写一个程序,在几个类和方法之间传递列表。现在,您希望在多线程环境中使用它。如果您明智地将所有内容声明为
List
,那么现在可以对一行代码进行一次更改:如果将列表声明为
ArrayList
,则必须重新编写整个程序。故事的寓意是——始终将编程设置为代码所需的限制最少的接口# 5 楼答案
一个具体的例子:如果它是一个字段声明,并且您有一个
setList()
,那么当然应该使用一个List
参数来灵活处理对于局部变量(以及没有设置器的字段),使用接口类型的具体好处很少。不管怎样,很多人都会按照一般原则去做
# 6 楼答案
你是对的。在这些情况下,变量是字段或局部变量,它们是而不是公共接口,它们是实现细节。应详细说明实施细节。您应该将ArrayList称为ArrayList,因为您只是特意为实现选择了它
回收陈词滥调的人:看看你的帖子,多想想。这是胡说八道
我先前的答案被否决了:
Use interface or type for variable definition in java?