Javaでコンストラクターを最終、静的、または抽象化できないのはなぜですか?
たとえば、なぜこれが有効ではないのか説明してもらえますか?
public class K {
abstract public K() {
// ...
}
}
メソッドをfinal
に設定すると、次のことを意味します: "クラスをオーバーライドしたくない。"しかし、Java言語仕様:
JLS 8.8 -「コンストラクター宣言はメンバーではありません。継承されることはないため、非表示またはオーバーライドの対象にはなりません。」
メソッドをabstract
に設定すると、次のことを意味します: "このメソッドにはボディがなく、子クラスに実装する必要があります。"しかし、new
キーワードが使用されている場合、コンストラクターは暗黙的に呼び出されるため、本体が不足することはありません。
メソッドをstatic
として設定すると、次のことを意味します: "このメソッドは特定のオブジェクトではなくクラスに属します。"しかし、コンストラクターはオブジェクトを初期化するために暗黙的に呼び出されるので、静的コンストラクターを持つ目的はありません。
問題は、コンストラクタをstatic or abstract or final
にする理由です。
コンストラクターは継承されないため、オーバーライドできないため、最終的なコンストラクターを使用するにはどうすればよいですか
コンストラクターは、クラスのインスタンスが作成されると自動的に呼び出され、クラスのインスタンスフィールドにアクセスできます。静的コンストラクターの使用はどうなりますか。
コンストラクターをオーバーライドすることはできませんので、抽象コンストラクターで何をしますか。
Javaコンストラクタは暗黙的 finalであり、そのセマンティクスの静的/非静的な側面は暗黙的1、およびJavaコンストラクターが抽象的である場合は無意味.
つまり、final
およびstatic
修飾子は冗長であり、abstract
キーワードはまったく意味を持ちません。
当然、Javaデザイナーは、コンストラクターで冗長および/または無意味なアクセス修飾子を許可することについて、いかなる点でも見ませんでした。したがって、これらはJava文法では許可されません。
余談:public
修飾子とabstract
修飾子も冗長であるインターフェースメソッドに対して同じ設計呼び出しを行わなかったのは残念ですが、とにかく許可されています。おそらく、これにはいくつかの(古代の)歴史的な理由があります。しかし、どちらにしても、(おそらく)数百万の既存のJavaプログラムをコンパイル不能にしないと修正できません。
1-実際には、コンストラクターには静的セマンティクスと非静的セマンティクスが混在しています。インスタンスのコンストラクターを「呼び出す」ことはできません。コンストラクターは継承されないか、オーバーライドできません。これは、静的メソッドの動作に似ています。一方、コンストラクターの本体はthis
を参照し、インスタンスメソッドのようにインスタンスメソッドを呼び出すことができます。そして、コンストラクターに固有のコンストラクターチェーンがあります。しかし、実際のポイントは、これらのセマンティクスが固定されていることであり、冗長でおそらく混乱を招くstatic
修飾子を許可するポイントはありません。
public
constructor:オブジェクトはどこでも作成できます。
デフォルトのコンストラクター:オブジェクトは同じパッケージ内でのみ作成できます。
protected
constructor:オブジェクトは、パッケージがサブクラスである場合にのみ、パッケージ外のクラスによって作成できます。
private
constructor:オブジェクトはクラス内でのみ作成できます(シングルトンを実装する場合など)。
static
、final
、およびabstract
キーワードは、コンストラクターにとって意味がありません。理由は次のとおりです。
static
メンバーはクラスに属しますが、オブジェクトを作成するにはコンストラクターが必要です。
abstract
クラスは部分的に実装されたクラスで、子クラスに実装される抽象メソッドが含まれます。
final
は変更を制限します。変数は定数になり、メソッドはオーバーライドできず、クラスは継承できません。
コンストラクターを最終として宣言することはできません。コンパイラーは、「modifier final not allowed」型のエラーを常にメソッドに適用すると、メソッドがサブクラスでオーバーライドできないことを意味します。コンストラクタは通常のメソッドではありません。 (異なるルールが適用されます)さらに、コンストラクターは決して継承されません。したがって、最終的な宣言には意味がありません。
最終:とにかくコンストラクタを上書き/拡張できないため。クラスを拡張する(最終にすることを防ぐ)か、メソッドを上書きする(最終にすることを防ぐ)ことができますが、コンストラクタにはこのようなものはありません。
静的:実行を見ると、コンストラクターは静的ではありません(インスタンスフィールドにアクセスできます)、呼び出し側を見ると、それは(一種)静的です(インスタンスを持たずに呼び出します) 。コンストラクターが完全に静的であるか静的でないかを想像するのは困難であり、これら2つのものを意味的に分離することなく、修飾子でそれらを区別することは意味がありません。
Abstract:Abstractは、上書き/拡張がある場合にのみ意味を持つため、「final」と同じ引数が適用されます
JLS セクション8 はこれに言及しています。
コンストラクター(8.8)はメソッドに似ていますが、メソッド呼び出しで直接呼び出すことはできません。これらは、新しいクラスインスタンスを初期化するために使用されます。メソッドと同様に、それらはオーバーロードされる場合があります(§8.8.8)。
ただし、コンストラクターは通常のメソッドではありません。それらを比較することはできません。
コンストラクターが静的で最終的なものにできない理由は、上記の回答で明確に定義されています。
要約:「抽象」とは、実装がないことを意味します。また、継承を介してのみ実装できます。したがって、クラスを拡張すると、「コンストラクター」を除くすべての親クラスメンバーがサブクラス(子クラス)に継承されます。コンストラクタが子クラスで継承されない場合、サブクラスで実装をどのように与えることができるかよりも、コンストラクタ「Abstract」をどのように宣言するのでしょうか?
そのため、コンストラクターをabstractにすることはできません。
最初の最終公開K(){
*最後の修飾子は制限されます '最終的な場合は、他のクラスまたは同じクラスでのみオーバーライドするため、ここでは最終的には最終的には発生しません:
we want public void(int i,String name){
//this code not allowed
static、static itzをクラスレベルについてすべて説明しますが、 'new'キーワードを使用してオブジェクトベースのコンストラクタを作成しますso , thatsall
抽象メソッドまたは宣言されたメソッドがないため、ここではない最悪の抽象