コードはコンパイルされません:
Test.java:8: Bar の method() は Foo の method() をオーバーライドできません。オーバーライドされたメソッドは static final public static void method() {
静的メソッドは定義によりオーバーライドできないため、このメッセージは誤解を招きます。
私はコーディング時に次のことを行います (常に 100% ではありませんが、「間違っている」ものは何もありません:
(「ルール」の最初のセットは、ほとんどの場合に実行されます - いくつかの特殊なケースは後でカバーされます)
- インターフェイスを作成する
- インターフェイスを実装する抽象クラスを作成する
- 抽象クラスを拡張する具象クラスを作成する
- インターフェイスを実装するが抽象クラスを拡張しない具象クラスを作成する
- 常に、可能であれば、インターフェイスのすべての変数/定数/パラメーターを作成します
インターフェイスには静的メソッドを含めることができないため、問題が発生することはありません。抽象クラスまたは具象クラスで静的メソッドを作成する場合、それらはプライベートにする必要があり、それらをオーバーライドしようとする方法はありません。
特殊なケース:
ユーティリティ クラス (すべての静的メソッドを持つクラス):
- クラスを final として宣言する
- 偶発的な作成を防ぐためにプライベート コンストラクターを指定する
非公開の具象クラスまたは抽象クラスに静的メソッドが必要な場合は、代わりにユーティリティ クラスを作成することをお勧めします。
値クラス (x 値と y 値をほとんど保持している java.awt.Point のように、本質的にデータを保持するために非常に特殊化されたクラス):
- インターフェイスを作成する必要はありません
- 抽象クラスを作成する必要はありません
- クラスは final にする必要があります
- プライベートでない静的メソッドは問題ありません。特に、キャッシュを実行したい場合があるため、構築には問題ありません。
上記のアドバイスに従うと、かなり柔軟なコードになり、責任もかなり明確に分離されます。
値クラスの例は、次の Location クラスです。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class Location
implements Comparable<Location>
{
// should really use weak references here to help out with garbage collection
private static final Map<Integer, Map<Integer, Location>> locations;
private final int row;
private final int col;
static
{
locations = new HashMap<Integer, Map<Integer, Location>>();
}
private Location(final int r,
final int c)
{
if(r < 0)
{
throw new IllegalArgumentException("r must be >= 0, was: " + r);
}
if(c < 0)
{
throw new IllegalArgumentException("c must be >= 0, was: " + c);
}
row = r;
col = c;
}
public int getRow()
{
return (row);
}
public int getCol()
{
return (col);
}
// this ensures that only one location is created for each row/col pair... could not
// do that if the constructor was not private.
public static Location fromRowCol(final int row,
final int col)
{
Location location;
Map<Integer, Location> forRow;
if(row < 0)
{
throw new IllegalArgumentException("row must be >= 0, was: " + row);
}
if(col < 0)
{
throw new IllegalArgumentException("col must be >= 0, was: " + col);
}
forRow = locations.get(row);
if(forRow == null)
{
forRow = new HashMap<Integer, Location>(col);
locations.put(row, forRow);
}
location = forRow.get(col);
if(location == null)
{
location = new Location(row, col);
forRow.put(col, location);
}
return (location);
}
private static void ensureCapacity(final List<?> list,
final int size)
{
while(list.size() <= size)
{
list.add(null);
}
}
@Override
public int hashCode()
{
// should think up a better way to do this...
return (row * col);
}
@Override
public boolean equals(final Object obj)
{
final Location other;
if(obj == null)
{
return false;
}
if(getClass() != obj.getClass())
{
return false;
}
other = (Location)obj;
if(row != other.row)
{
return false;
}
if(col != other.col)
{
return false;
}
return true;
}
@Override
public String toString()
{
return ("[" + row + ", " + col + "]");
}
public int compareTo(final Location other)
{
final int val;
if(row == other.row)
{
val = col - other.col;
}
else
{
val = row - other.row;
}
return (val);
}
}