我在eclipse中使用Java,我读了thread
我真的很喜欢home's answer,因为我之前从未真正考虑过它。子类应该真正无法访问成员的整个想法。但是,如果有人想要试一试,我会有一个有趣的边缘案例。
假设我有一个界面Buildable
和一个枚举CatanPiece
:
public interface Buildable
{
HashMap<Resource, Integer> getCost();
Buildable build( final PlayerHand payment );
}
public enum CatanPiece implements Buildable
{
ROAD
{
@Override
public HashMap<Resource, Integer> getCost()
{
if ( cost.isEmpty() )
{
cost.put( BRICK, 1 );
cost.put( LUMBER, 1 );
}
return cost;
}
},
SETTLEMENT
{
@Override
public HashMap<Resource, Integer> getCost()
{
if ( cost.isEmpty() )
{
cost.put( BRICK, 1 );
cost.put( LUMBER, 1 );
cost.put( SHEEP, 1 );
cost.put( WHEAT, 1 );
}
return cost;
}
},
CITY
{
@Override
public HashMap<Resource, Integer> getCost()
{
if ( cost.isEmpty() )
{
cost.put( WHEAT, 2 );
cost.put( ORE, 3 );
}
return cost;
}
};
protected final HashMap<Resource, Integer> cost;
private CatanPiece()
{
cost = getCost();
}
@Override
public abstract HashMap<Resource, Integer> getCost();
@Override
public Buildable build( final PlayerHand payment )
{
return ( payment.remove( cost ) ? null : this );
}
}
所以Checkstyle给了我关于我正在使用的受保护的HashMap的废话,但是对于那些理解它的人来说,你可以看到我没有人滥用这个变量的问题。我实际上将它设为私有并使用受保护的get方法,但该方法的返回值因实例而异。
可能的答案:忽略checkstyle警告,或者可能包含一个抽象的 init()方法来初始化HashMap,然后简单地为所有成员实现 getCost()方法enum。
您怎么看?
答案 0 :(得分:2)
Checkstyle对Enums的理解有时是不完整的。我猜想VisibilityModifier支票的作者没想到Enums。枚举是一个角落案例,需要一些额外的检查属性。
然而,在您的情况下,意外地,警告仍然是正确的。我相信在任何情况下都不应该在枚举中使用protected
字段。如果在Enum常量中需要特定于实例的状态,请通过构造函数或静态初始化初始化它。
尝试以下方法。这应该会带来几个好处:
Map
现在是private
。CatanPiece
枚举常量现在是常量,因为成本映射是不可变的。CatanPiece
枚举常量的用户可以确保成本映射已正确初始化。唯一的缺点是,无论何时扩展枚举(例如SHIP
),开发人员都不能忘记更新buildCostMap()
。这样的错误会很快出现。
public enum CatanPiece implements Buildable
{
ROAD, SETTLEMENT, CITY;
private static final Map<CatanPiece, Map<Resource, Integer>> allCosts =
buildCostMap();
private static Map<CatanPiece, Map<Resource, Integer>> buildCostMap()
{
Map<CatanPiece, Map<Resource, Integer>> result =
new HashMap<CatanPiece, Map<Resource, Integer>>();
Map<Resource, Integer> cost = new EnumMap<Resource, Integer>(Resource.class);
cost.put(Resource.WHEAT, 2);
cost.put(Resource.ORE, 3);
result.put(CITY, Collections.unmodifiableMap(cost));
cost = new EnumMap<Resource, Integer>(Resource.class);
cost.put(Resource.BRICK, 1);
cost.put(Resource.LUMBER, 1);
cost.put(Resource.SHEEP, 1);
cost.put(Resource.WHEAT, 1);
result.put(SETTLEMENT, Collections.unmodifiableMap(cost));
cost = new EnumMap<Resource, Integer>(Resource.class);
cost.put(Resource.BRICK, 1);
cost.put(Resource.LUMBER, 1);
result.put(ROAD, Collections.unmodifiableMap(cost));
return Collections.unmodifiableMap(result);
}
@Override
public Map<Resource, Integer> getCost() {
return allCosts.get(this);
}
@Override
public Buildable build(final PlayerHand payment) {
return payment.remove(cost) ? null : this;
}
}