Use interface or type for variable definition in java?

后端 未结 8 1997
挽巷
挽巷 2020-11-29 05:59
ArrayList aList = new ArrayList();

List aList = new ArrayList();

What\'s the difference between these two and which is better to use and why?

8条回答
  •  感动是毒
    2020-11-29 06:36

    This is a Java quirk, due to limited type inference and doctrine OOP. For local variables it's mostly style; if you need some specific feature of the subtype, use the subtype (examples below), but otherwise fine to use either.

    Java style is to use the supertype, to enforce interfaces even within the body of implementations, and for consistency with visible types (Effective Java 2nd Edition: Item 52: Refer to objects by their interfaces). In languages with more type inference, such as C++/C#/Go/etc., you don't need to explicitly state the type, and the local variable will have the specific type.

    For visible types (public or protected: fields, or parameters and return value of methods), you almost always want to use the most general type: interface or abstract class, to provide better flexibility (Effective Java: Item 40: Design method signatures carefully). However, for types that are not visible (private or package-private members, or local variables), it's ok to use either (it's just style) and sometimes necessary to use more specific types, including concrete classes.

    See Effective Java for standard guidelines; personal thoughts follow.

    The reason to use more general types even if not visible is to reduce noise: you're stating that you only need the more general type. Using general types on members that are not visible (like private methods) also reduces churn if you ever change types. However, this doesn't apply to local variables, where it's just changing one line anyway: ConcreteFoo foo = new ConcreteFoo(); to OtherConcreteFoo foo = new OtherConcreteFoo();.

    Cases where you do need the subtype include:

    • You need members only present on the subtype, e.g.:
      • some feature of the implementation, like ensureCapacity for ArrayList
      • (common in test code) some member of a fake class, like (hypothetically) FakeFileSystem#createFakeFile.
    • You rely on the behavior of the subtype, notably in overrides of the supertype's methods, like:
      • having a more general type of parameter,
      • more specific return type, or
      • throwing a more specific or fewer exception types.

    As an example of the last, see Should I close a StringReader?: StringReader.html#close overrides Reader.html#close and does not throw an IOException, so using StringReader instead of Reader for the local variable means you don't need to handle an exception that can't actually occur, and significantly reduces boilerplate.

提交回复
热议问题