为什么使用私有修饰符用于不可变的最终实例var?

时间:2012-11-26 01:09:01

标签: java abstract final

我正在编写一个代表一些简单几何的Java类。

在最顶层的abstract类(本身是 package-private )中,我声明了需要从同一个包中的子类访问的属性。

如果我在final

中将属性声明为AbstractClass
final int foo;

我可以直接在包中访问它,而不用任何getter方法。 然而。根据“实践”(或我认为是共同的风格)做的将是:

private final int foo;

当然需要非private吸气剂。子类必须引用foo(这是一个非常相关和典型的属性),好像它是一些外部对象:

this.getFoo();

它添加了代码并删除了访问这些成员的直接方式(即foo)。

跳过private修饰符是否有任何缺点,因为它们无论如何都是最终的,我不担心在包内部暴露这些属性?

我知道OO倡导者声称getter / setter是对象访问他们自己的属性的一种非常自然的方式 - 但是什么时候这会使任何非整形,非[插入任何JavaBeans风格的东西],差?

考虑一个内部类Coordinate,它非常简单,因为它有两个int属性 - 保留了类OuterClass的所有用法:

class OuterClass{
    final static class Coordinate{
        final int x, y;
        Coordinate(int x, int y){
            this.x = x;
            this.y = y;
        }
    }
    Coordinate coordinate;
}

对于这个内心阶层 - 为什么我会为创造一个吸气剂的实践而烦恼? getter会引入更多代码并强制同一个包中的任何类调用coordinate.getX();而不是简单coordinate.x;。这有任何开销吗?请注意课程final上的Coordinate修饰符。

3 个答案:

答案 0 :(得分:6)

getter的优点是将接口与实现分离。今天您的getFoo可能只会返回foo,但是将来您可能希望远程调用foo成员并返回计算结果。获取者将允许您在不需要在每个呼叫站点进行更改的情况下执行此操作。

答案 1 :(得分:2)

如果你要从JSF页面访问这个值,它会期望getFoo而不仅仅是foo(即使你写object.foo)。

除此之外 - 今天这个领域是最终的,很长一段时间它可以改变(我猜)。即使机会非常接近0,我相信在遵循良好做法方面也没有过度杀伤力。大多数时候你进行更改而不是从头开始编写代码,所以尽可能保护自己(如果只需编写private并且在eclipse的情况下大约需要4次点击来生成getter和setter automaticaly)。

答案 2 :(得分:0)

扩展Feldgendler的答案(提供可能对需要回答此问题的人有用的信息 - 我相信这是相关的,因为它确实是一个关于封装的问题):

使用private修饰符时,您必须创建" getter" (例如int getX(){ ... })以维持访问权限。哪个可以在已实现的interface中声明。 Java interface允许允许声明实例变量,例如final int x; ---或缺少static修饰符的任何其他变量的示例。该接口将充当任何实现类将具有的行为的声明。

如果实施如下:

Coordinate implements ICoordinate { ... }

它在许多场景中都很有用:

使用界面

  • API的自我记录。
    • 易于阅读,记录和管理。
    • 因此,允许使用和交换多个实现。
    • 在基于组件的设计中以及更多:提供提供或的明确方法 要求描述的行为,而不实际准备任何实现代码。
      • 示例:然后可以创建一个提供接口的数据库组件。 John Doe想要编写一个将来会使用数据库的程序。但是现在使用其他更简单的存储形式就足够了。为了不重新编码已经工作的代码,John可以实现一个接口(可能名称为interface IDatabase),方法为void insert( ... ); Object get( ... );,也许还有一些 - 然后实现他的临时解决方案这一天来了,他现在有一个实现相同interface IDatabase的数据库。要交换到新数据库,他可能只需要更改*一行代码*(例如构造函数调用)!
  • 为此而举的例子:http://pastebin.com/vvV2Nck8

使用私有修饰符

  • 澄清班级的意图!与界面非常相似,它具有自我记录的性质。 (它没有安全价值)
    • private修饰符意味着它不会超出范围。或者等效 - 仅在特定范围内访问。同样适用于public," package-private" (没有修饰符暗示包私有)和protected
    • 访问属性不会明确告诉调用者它是什么类型的变量。有一个吸气剂,但没有setter说了别的东西......
    • 注意:对于常量(例如static final double LIGHT_SPEED),有合理的理由省略getter并改为使用public。这只是惯例,因为它将是一个常量,什么是一个具有自己成员的对象。
    • 注意2:如果感兴趣,请阅读final关键字及其对优化的影响。它们既可以用于方法,也可以用于属性。 (Does use of final keyword in Java improve the performance?就是一个例子)