静的メソッドがJavaで抽象化できないのはなぜですか?


593

問題はJavaですが、なぜ抽象静的メソッドを定義できないのですか?例えば

abstract class foo {
    abstract void bar( ); // <-- this is ok
    abstract static void bar2(); //<-- this isn't why?
}

9
いくつかの理由:静的メソッドにアクセスするためにクラスのインスタンスを作成する必要がないため、静的メソッドは抽象クラスの一部であっても本体を持つ必要があります。それについて考えるもう1つの方法は、それが許可されていると想定している場合、問題は静的メソッド呼び出しが実行時型情報(RTTI)を提供しないことであり、インスタンスの作成が不要であるため、リダイレクトできないことです。それらの特定のオーバーライドされた実装に、したがってabstarct staticを許可することはまったく意味がありません。言い換えれば、多態性の利点を提供できなかったため、許可されていませんでした。
sactiw 2016年

6
質問への回答が必要な場合は、コメントではなく回答として投稿してください
Solomon Ucko 2016年

回答:


568

「抽象」は「機能を実装しない」という意味であり、「静的」は「オブジェクトインスタンスがなくても機能はある」という意味です。そして、それは論理的な矛盾です。


353
より簡潔な答えは「悪い言語設計」でしょう。静的とは、「クラスに属する」という意味です。これは、まさにこの質問が示すように、それが直感的に使用されるためです。Pythonの「classmethod」を参照してください。
Alexander Ljungberg、

12
@Tomalak申し訳ありません、はっきりしていませんでした。もちろん、静的メソッドは「クラスに属します」。それでも、同じ名前空間に存在するという意味でのみです。静的メソッドは、クラスオブジェクト自体のメソッドではありません。クラスオブジェクトとして「this」を使用して動作せず、継承のチェーンに適切に参加しません。それが本当にクラスのメソッドである場合abstract staticは、完全に意味があります。サブクラスオブジェクトが実装する必要があるのは、クラスオブジェクト自体のメソッドです。もちろん、私が言葉にこだわっているにもかかわらず、物事の答え方は正しいです。
Alexander Ljungberg、

695
これは論理的な矛盾ではなく、言語の欠点であり、他の複数の言語がこの概念をサポートしています。「抽象」は「サブクラスで実装」を意味し、「静的」は「クラスインスタンスではなくクラスで実行される」ことを意味します。論理的な矛盾はありません。
エリックグランジ

10
@エリック:そして、それでも、あなたが言うことは適用されませんabstract static:「サブクラスで実装される」関数X は同時に「クラスで実行される」ことができません - サブクラスでのみです。そのとき、それはもはや抽象的なものではありません。
Tomalak

72
@Tomakak:あなたの論理は循環的です。static「空ではない」という意味ではありません-これは、Javaが静的メソッドを抽象化できないことの結果です。「クラスで呼び出せる」という意味です。(「クラスでのみ呼び出し可能」を意味する必要がありますが、それは別の問題です。)Javaがサポートabstract staticするメソッドの場合、1)サブクラスで実装する必要があり、2)サブクラスのクラスメソッドであることを意味します。一部のメソッドは、インスタンスメソッドとしては意味がありません。残念ながら、Javaでは、抽象基本クラス(またはインターフェース)を作成するときにそれを指定できません。
マイケルカーマン、

326

言語のデザインが悪い。静的抽象メソッドを直接呼び出す方が、その抽象メソッドを使用するためだけにインスタンスを作成するよりもはるかに効果的です。特に、列挙型クラスを拡張できない場合の回避策として抽象クラスを使用する場合は、これは別の貧弱な設計例です。それらが次のリリースでそれらの制限を解決することを願っています。


25
Javaには奇妙な制限がたくさんあります。final変数のみにアクセスするクロージャーは別のものです。そして、残りのリストはほとんど無限です。それらとその回避策を知ることは、Javaプログラマの仕事です。楽しい時間を過ごすために、私たちは暇なときにJavaよりも良いものを使わなければなりません。しかし、私は気にしません。それは進歩を達成するための種です。
ceving

22
あなたが「貧弱な言語設計」と呼んでいるのは、本当に「保護言語設計」のようなものだと思います。それは、不要な言語機能のためにプログラマーが行うオブジェクト指向の原則違反を制限することです。
ethanfar 2014年

22
「抽象的な静的」の概念はオブジェクト指向の原則に違反していますか?
Trevor

7
@threed、まったくそうではありませんが、もちろん、staticそれ自体の単なる概念はすでに違反であると言う人々がいます...
Pacerier

4
静的の必要性は、「OOの原則」が通常主張されているほど包括的ではないことを明確に示しています。
ベン

147

静的メソッドをオーバーライドすることはできないため、それを抽象化しても意味がありません。さらに、抽象クラスの静的メソッドは、オーバーライドするクラスではなく、そのクラスに属しているため、いずれにしても使用できませんでした。


18
はい、それは静的メソッドがJavaでオーバーライドできないという点で本当に残念です。
ミシェル

12
@Michel:ポイントは何でしょうか?インスタンスベースの動作が必要な場合は、インスタンスメソッドを使用します。
Ran Biron

8
この答えは間違っています。抽象クラスの静的メソッドは正常に機能し、一般的に使用されます。クラス自体の静的メソッドが抽象的でない可能性があるだけです。@Michel静的メソッドをオーバーライドしても意味がありません。インスタンスがない場合、ランタイムはどのメソッドを呼び出すかをどのようにして知るのでしょうか?
エリクソン2008

63
@erickson-インスタンスがなくても、クラス階層はそのままです-静的メソッドの継承は、インスタンスメソッドの継承と同じように機能します。Smalltalkはそれを行い、それは非常に便利です。
Jared、

8
@matiasgそれはまったく新しいものではありません。抽象クラスは常に静的な非抽象メソッドを持つことができました。
マットボール

70

abstractメソッドへのアノテーションは、メソッドがサブクラスでオーバーライドされなければならないことを示しています。

Javaでは、staticメンバー(メソッドまたはフィールド)をサブクラスでオーバーライドすることはできません(これは他のオブジェクト指向言語では必ずしも当てはまりません。SmallTalkを参照してください)。staticメンバーは非表示になる場合がありますが、それはオーバーライドされたものとは根本的に異なります。

静的メンバーはサブクラスでオーバーライドできないため、abstractアノテーションをそれらに適用することはできません。

余談ですが、他の言語はインスタンスの継承と同様に静的な継承をサポートしています。構文の観点から、これらの言語では通常、ステートメントにクラス名を含める必要があります。たとえば、Javaでは、ClassAでコードを記述している場合、これらは同等のステートメントです(methodA()が静的メソッドであり、同じシグネチャを持つインスタンスメソッドがない場合)。

ClassA.methodA();

そして

methodA();

SmallTalkでは、クラス名はオプションではないため、構文は次のとおりです(SmallTalkは。を使用して「主語」と「動詞」を区切るのではなく、statemendターミネーターとして使用します)。

ClassA methodA.

クラス名は常に必要であるため、クラス階層をたどることによって、メソッドの正しい「バージョン」を常に決定できます。それだけの価値があるので、私はときどきstatic継承を見逃しており、最初にJavaを始めたとき、Javaに静的継承がないことに悩まされました。さらに、SmallTalkはダック型(したがって、契約ごとのプログラムはサポートされていません。)なのでabstract、クラスメンバーの修飾子はありません。


1
「静的メンバーはサブクラスでオーバーライドできません」は誤りです。少なくともJava6では可能です。いつになるかわからないので。
Steven De Groote

15
@Steven De Groote静的メンバーをサブクラスでオーバーライドすることはできません。サブクラスにスーパークラスの静的メソッドと同じシグネチャを持つ静的メソッドがある場合、それはオーバーライドされず、非表示になります。http://docs.oracle.com/javase/tutorial/java/IandI/override.html違いは、ポリモーフィズムがオーバーライドされたメソッドに対してのみ機能し、非表示のメソッドに対しては機能しないことです。
John29、2013

2
@ John29説明をありがとうございます。ただし、命名の違いは別として、使用方法は似ているようです。
Steven De Groote

2
@Steven De Grooteはい、使用方法は似ていますが、動作が異なります。それが静的抽象メソッドがない理由です-多態性をサポートしない場合の静的抽象メソッドのポイントは何ですか?
John29、2013

3
@Steven De Groote:スーパークラス自体でそのメソッドを呼び出したときに違いが明らかになります。Super.fooがSuper.barを呼び出すとします。サブクラスがSubclass.barを実装してからfooを呼び出した場合、fooはSubclass.barではなくSuper.barを呼び出します。したがって、あなたが実際に持っているのは、「バー」と呼ばれる2つのまったく異なる、無関係なメソッドです。これは、どんな意味でもオーバーライドするものではありません。
Doradus

14

私も同じ質問をしました、ここに理由があります

抽象クラスが言うので、それは実装を与えず、サブクラスがそれを与えることを可能にします

したがって、サブクラスはスーパークラスのメソッドをオーバーライドする必要があります。

RULE NO 1 - A静的メソッドがオーバーライドすることはできません

静的メンバーとメソッドはコンパイル時の要素であるため、静的メソッドのオーバーロード(コンパイル時ポリモーフィズム)は、オーバーライド(実行時ポリモーフィズム)ではなく許可されます。

したがって、それらは抽象的であってはなりません。

抽象staticのようなものはあり ません<--- Java Universeでは許可されていません


5
-1、「静的メンバーとメソッドはコンパイル時の要素であるため、Javaは静的メソッドのオーバーライドを許可しない」とは言えません。静的型チェックは、stackoverflow.com / questions / 370962 /…abstract static参照すると確実に可能です。本当の理由 Javaは静的メソッドをオーバーライドすることはできませんので、Javaは静的メソッドをオーバーライドすることはできません理由です。
Pacerier 2014

オーバーロードはポリモーフィズムとは関係ありません。オーバーロードとオーバーライドには、JavaとJavaScriptの両方に「Java」が含まれているのとほぼ同じ方法で接頭辞「over」を除いて、共通点はありません。メソッドの名前は、それを識別するものではなく、そのシグニチャーです。それfoo(String)は同じではありませんfoo(Integer)-それだけです。
キャプテンマン

@CaptainManオーバーロードは、文字通り「パラメトリックポリモーフィズム」と呼ばれます。これは、パラメーターのタイプに応じて、ポリモーフィズムと呼ばれる別のメソッドが呼び出されるためです。
Davor 2018年

12

これはひどい言語設計であり、それが不可能である理由については本当に理由はありません。

実際には、ここではそれがどのように実装されCANで行うことがJAVAは

public class Main {

        public static void main(String[] args) {
                // This is done once in your application, usually at startup
                Request.setRequest(new RequestImplementationOther());

                Request.doSomething();
        }

        public static final class RequestImplementationDefault extends Request {
                @Override
                void doSomethingImpl() {
                        System.out.println("I am doing something AAAAAA");
                }
        }

        public static final class RequestImplementaionOther extends Request {
                @Override
                void doSomethingImpl() {
                        System.out.println("I am doing something BBBBBB");
                }
        }

        // Static methods in here can be overriden
        public static abstract class Request {

                abstract void doSomethingImpl();

                // Static method
                public static void doSomething() {
                        getRequest().doSomethingImpl();
                }

                private static Request request;
                private static Request getRequest() {
                        // If setRequest is never called prior, it will default to a default implementation. Of course you could ignore that too. 
                        if ( request == null ) {
                                return request = new RequestImplementationDefault();
                        }
                        return request;
                }
                public static Request setRequest(Request r){
                        return request = r;
                }

        }
}

=================以下の古い例=================

getRequestを探し、getRequestImpl ... setInstanceを呼び出して、呼び出しが行われる前に実装を変更できます。

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author Mo. Joseph
 * @date 16 mar 2012
 **/

public abstract class Core {


    // ---------------------------------------------------------------        
    private static Core singleton; 
    private static Core getInstance() {
        if ( singleton == null )
            setInstance( new Core.CoreDefaultImpl() );  // See bottom for CoreDefaultImpl

        return singleton;
    }    

    public static void setInstance(Core core) {
        Core.singleton = core;
    }
    // ---------------------------------------------------------------        



    // Static public method
    public static HttpServletRequest getRequest() {      
        return getInstance().getRequestImpl();
    }


    // A new implementation would override this one and call setInstance above with that implementation instance
    protected abstract HttpServletRequest getRequestImpl();




    // ============================ CLASSES =================================

    // ======================================================================
    // == Two example implementations, to alter getRequest() call behaviour 
    // == getInstance() have to be called in all static methods for this to work
    // == static method getRequest is altered through implementation of getRequestImpl
    // ======================================================================

    /** Static inner class CoreDefaultImpl */
    public static class CoreDefaultImpl extends Core { 
        protected HttpServletRequest getRequestImpl() {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        }
    }

     /** Static inner class CoreTestImpl : Alternative implementation */
    public static class CoreTestImpl extends Core { 
        protected HttpServletRequest getRequestImpl() {
            return new MockedRequest();
        }
    }       

}

次のように使用:

static {
     Core.setSingleton(new Core.CoreDefaultImpl());

     // Or

     Core.setSingleton(new Core.CoreTestImpl());

     // Later in the application you might use

     Core.getRequest(); 

}

6
abstract static質問で尋ねられた方法の例をどこに提供したか理解できず、太字でCAN JAVA BE DONE IN JAVAと書いてあります。これは完全に誤解です。
Blip

1
それ自体は抽象静的として定義することはできませんが、このパターン/ハックを使用して静的メソッドの実装を変更できる同様の結果を得ることができます。それはほとんど見当違いです。それは可能ですが、異なるセマンティクスを使用します。
mmm 2017年

これは、抽象クラスを拡張し、静的メソッドを子に配置する例です。これは、Javaで実行できることの例ではありません。
スキューバスティーブ

2
@ScubaSteveまず、あなたの結論は間違っています。次に、同じ結果が得られます。クラスへの静的アクセスの意味は、別の実装によって変更できます。staticキーワードを抽象化可能にしたと言っても答えではありませんが、このパターンを使用すると、静的メソッドを使用して、その実装を変更できます。ただし、グローバルであることにはマイナスの影響がありますが、テスト/製品/開発環境の場合はうまくいきます。
mmm

5
  • 抽象メソッドは、サブクラスでオーバーライドできるようにのみ定義されています。ただし、静的メソッドはオーバーライドできません。したがって、抽象的で静的なメソッドがあると、コンパイル時エラーになります。

    次の質問は、静的メソッドをオーバーライドできないのはなぜですか?

  • これは、静的メソッドがそのインスタンスではなく特定のクラスに属しているためです。静的メソッドをオーバーライドしようとすると、コンパイルエラーや実行時エラーは発生しませんが、コンパイラーはスーパークラスの静的メソッドを非表示にするだけです。


4

静的メソッドは、定義により、知る必要はありませんthis。したがって、それは仮想メソッドになることはできません(それはthis、を通じて利用可能な動的サブクラス情報に従ってオーバーロードされます)。代わりに、静的メソッドのオーバーロードは、コンパイル時に利用可能な情報のみに基づいています(つまり、スーパークラスの静的メソッドを参照すると、スーパークラスメソッドを呼び出しますが、サブクラスメソッドは呼び出しません)。

これによると、抽象静的メソッドは、その参照が定義済みの本体で置き換えられることがないため、まったく役に立たないでしょう。


4

私はすでに無数の答えがあることを知っていますが、実際的な解決策は見ていません。もちろん、これは実際の問題であり、Javaでこの構文を除外する理由はありません。元の質問には、これが必要になる可能性のあるコンテキストがないため、コンテキストと解決策の両方を提供します。

同一のクラスの束に静的メソッドがあるとします。これらのメソッドは、クラス固有の静的メソッドを呼び出します。

class C1 {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    private static void doMoreWork(int k) {
        // code specific to class C1
    }
}
class C2 {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    private static void doMoreWork(int k) {
        // code specific to class C2
    }
}

doWork()メソッド内C1C2同じです。これらの計算はたくさんある可能性があります:C3 C4など。static abstract許可されている場合は、次のようなことを行うことで重複したコードを排除します。

abstract class C {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }

    static abstract void doMoreWork(int k);
}

class C1 extends C {
    private static void doMoreWork(int k) {
        // code for class C1
    }
}

class C2 extends C {
    private static void doMoreWork(int k) {
        // code for class C2
    }
}

しかし、static abstract組み合わせが許可されていないため、これはコンパイルされません。ただし、これstatic classは許可されている構成で回避できます。

abstract class C {
    void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    abstract void doMoreWork(int k);
}
class C1 {
    private static final C c = new  C(){  
        @Override void doMoreWork(int k) {
            System.out.println("code for C1");
        }
    };
    public static void doWork() {
        c.doWork();
    }
}
class C2 {
    private static final C c = new C() {
        @Override void doMoreWork(int k) {
            System.out.println("code for C2");
        }
    };
    public static void doWork() {
        c.doWork();
    }
}

このソリューションでは、複製される唯一のコードは

    public static void doWork() {
        c.doWork();
    }

1
最終的な解決策では、抽象クラスCに静的メソッドがないので、C1とC2がそれを拡張してdoMoreWork()メソッドをオーバーライドし、他のクラスがそのインスタンスを作成して必要なメソッドを呼び出せるようにしないでください。基本的には同じことを行います。つまり、匿名クラスを使用してクラスCを拡張し、次に静的インスタンスを使用してC1およびC2で静的メソッド内からのアクセスを許可しますが、これはまったく必要ありません。
sactiw 2016年

ここで提供されたコンテキストを理解できません。最終的な解決策では、電話をかけるC1.doWork()C2.doWork()、電話をかけることはできませんC.doWork()。また、提供された例では機能しませんが、許可されている場合は、クラスはどのようにC実装を見つけますdoMoreWork()か?最後に、私はあなたのコンテキストコードを悪いデザインと呼びます。どうして?これは、一般的なコードの関数を作成してからクラスに静的関数を実装するのではなく、一意のコードの個別の関数を作成したからですC。これは簡単です!!!
Blip

2

2つのクラスがあると仮定ParentChildます。Parentですabstract。宣言は次のとおりです。

abstract class Parent {
    abstract void run();
}

class Child extends Parent {
    void run() {}
}

つまり、のインスタンスはParentどのようrun()に実行されるかを指定する必要があります。

しかし、今Parentはそうではないと仮定しますabstract

class Parent {
    static void run() {}
}

つまりParent.run()、静的メソッドが実行されます。

abstractメソッドの定義は「宣言されているが実装されていないメソッド」です。つまり、メソッド自体は何も返しません。

staticメソッドの定義は、「呼び出されたインスタンスに関係なく、同じパラメーターに同じ値を返すメソッド」です。

abstractメソッドの戻り値は、インスタンスの変更として変更されます。static方法はないでしょう。static abstractこの方法はかなりの戻り値が一定である方法であるが、何も返しません。これは論理的な矛盾です。

また、static abstractメソッドには理由があまりありません。


2

抽象メソッドは、静的メソッドがその機能に静的にバインドされている間に動的バインディングを実現するために行われるため、静的メソッドを持つことはできません。静的メソッドは、インスタンス変数に依存しない動作を意味するため、インスタンス/オブジェクトは必要ありません。静的メソッドはオブジェクトではなくクラスに属します。それらは、PERMGENと呼ばれるメモリ領域に格納され、そこからすべてのオブジェクトと共有されます。抽象クラスのメソッドは、その機能に動的にバインドされます。


1
抽象クラスは確実に静的メソッドを持つことができます。しかし、静的抽象メソッドではありません。
JacksOnF1re 2016

2

以下のような方法を宣言static私たちはそのクラス名によってそのメソッドを呼び出すことができますし、そのクラスがある場合の手段abstractとしてだけでなく、それがすべてのボディが含まれていないとして、それを呼び出すために、したがって私たちは、両方のメソッドを宣言することはできません意味がないstaticabstract


2

抽象メソッドはクラスに属しているため、実装クラスでオーバーライドすることはできません。同じシグネチャを持つ静的メソッドがある場合でも、メソッドを非表示にし、オーバーライドしません。したがって、本体を取得しないため、抽象メソッドを静的として宣言することは重要ではありません。したがって、コンパイル時エラーが発生します。


1

静的メソッドは、クラスのインスタンスなしで呼び出すことができます。この例では、foo.bar2()を呼び出すことができますが、foo.bar()を呼び出すことはできません。barにはインスタンスが必要だからです。次のコードは機能します:

foo var = new ImplementsFoo();
var.bar();

静的メソッドを呼び出すと、常に同じコードで実行されます。上記の例では、bars2をImplementsFooで再定義しても、var.bar2()を呼び出すとfoo.bar2()が実行されます。

bar2に実装がない場合(これが抽象の意味です)、実装なしでメソッドを呼び出すことができます。それは非常に有害です。


1
また、抽象静的メソッドはインスタンスなしで呼び出すこともできますが、実装は子クラスで作成する必要があります。これは厳密にはポリモーフィズムではありませんが、これを回避する唯一の方法は、「抽象静的」メソッドを「必要とする」インターフェースを具象子に実装させることです。乱雑ですが、実行可能です。
fijiaaron 2010年

3
実際、私は間違っていました。インターフェイスに静的メソッドを含めることもできません。言語の欠陥。
fijiaaron 2010年

1

インターフェイスのメソッド(親クラスの抽象メソッドのように機能する)を静的にできない理由という形で、この質問に対する答えを見つけたと思います。ここに完全な答えがあります(私のものではありません)

基本的に静的メソッドは、それらを呼び出すにはクラスを指定する必要があるため、コンパイル時にバインドできます。これはインスタンスメソッドとは異なり、メソッドの呼び出し元である参照のクラスはコンパイル時に不明になる可能性があります(したがって、呼び出されるコードブロックは実行時にのみ決定できます)。

静的メソッドを呼び出している場合は、それが実装されているクラス、またはその直接のサブクラスをすでに知っています。定義すると

abstract class Foo {
    abstract static void bar();
}

class Foo2 {
    @Override
    static void bar() {}
}

次に、どのFoo.bar();呼び出しも明らかに違法であり、常にを使用しますFoo2.bar();

これを念頭に置いて、静的抽象メソッドの唯一の目的は、サブクラスにそのようなメソッドを実装させることです。最初はこれは非常に間違っていると思うかもしれませんが、ジェネリック型パラメーターがある場合は、できる<E extends MySuperClass>インターフェースを介して保証するとよいでしょう。型消去のため、ジェネリックはコンパイル時にのみ存在することに注意してください。E.doSomething()

それで、それは役に立ちますか?はい、多分それがJava 8がインターフェースで静的メソッドを許可している理由です(ただし、デフォルトの実装でのみ)。クラスのデフォルト実装で静的メソッドを抽象化しないのはなぜですか?デフォルト実装の抽象メソッドが実際には具象メソッドだからです。

デフォルトの実装がない静的メソッドを抽象化/インターフェースしないのはなぜですか?どうやら、Javaがどのコードブロックを実行する必要があるかを識別する方法(単に私の答えの最初の部分)のためです。


1

抽象クラスはOOPSの概念であり、静的メンバーはOOPSの一部ではないので...
静的な完全なメソッドをインターフェイスで宣言でき、インターフェイス内でメインメソッドを宣言することでインターフェイスを実行できる

interface Demo 
{
  public static void main(String [] args) {
     System.out.println("I am from interface");
  }
}

0

抽象静的メソッドを持つという考えは、その特定の抽象クラスをそのメソッドに直接使用することはできないということですが、その静的メソッド(または総称:総称の実際のクラス)使用する)。

このようにして、たとえば、sortableObject抽象クラスを作成したり、(auto-)abstract静的メソッドとのインターフェースを作成したりして、ソートオプションのパラメーターを定義できます。

public interface SortableObject {
    public [abstract] static String [] getSortableTypes();
    public String getSortableValueByType(String type);
}

これで、これらのすべてのオブジェクトで同じである主なタイプでソートできるソート可能なオブジェクトを定義できます。

public class MyDataObject implements SortableObject {
    final static String [] SORT_TYPES = {
        "Name","Date of Birth"
    }
    static long newDataIndex = 0L ;

    String fullName ;
    String sortableDate ;
    long dataIndex = -1L ;
    public MyDataObject(String name, int year, int month, int day) {
        if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed.");
        if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date.");
        this.fullName = name ;
        this.sortableDate = MyUtils.createSortableDate(year,month,day);
        this.dataIndex = MyDataObject.newDataIndex++ ;
    }
    public String toString() {
        return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")";
    }

    // override SortableObject 
    public static String [] getSortableTypes() { return SORT_TYPES ; }
    public String getSortableValueByType(String type) {
        int index = MyUtils.getStringArrayIndex(SORT_TYPES, type);
        switch(index) {
             case 0: return this.name ;
             case 1: return this.sortableDate ;
        }
        return toString(); // in the order they were created when compared
    }
}

これで、

public class SortableList<T extends SortableObject> 

これは、タイプを取得し、ソートするタイプを選択するポップアップメニューを作成し、そのタイプからデータを取得することでリストを再ソートし、ソートタイプが選択されたときに自動で追加できる追加関数を持っています-新しいアイテムを並べ替えます。SortableListのインスタンスは "T"の静的メソッドに直接アクセスできることに注意してください。

String [] MenuItems = T.getSortableTypes();

インスタンスを使用する必要がある場合の問題は、SortableListにまだ項目がない可能性がありますが、優先される並べ替えを提供する必要があることです。

チェリオ、オラフ。


0

まず、抽象クラスの要点-抽象クラスはインスタンス化できません(wikiを参照)。だから、あなたが作成することはできません任意の抽象クラスのインスタンスを。

現在、Javaが静的メソッドを処理する方法は、そのクラスのすべてのインスタンスとメソッドを共有することです。

したがって、クラスをインスタンス化できない場合、抽象メソッドは拡張を要求するため、そのクラスは抽象静的メソッドを持つことができません。

ブーム。


抽象クラスのすべてのメソッドは、実行するためにとにかく拡張するクラスを必要とするので、これは言い訳にはなりません。抽象クラスを拡張できます(同時に、抽象メソッドを実装します)。したがって、これは説明としては機能しません。
ペレ

0

Java docに従って:

静的メソッドは、オブジェクトではなく、それが定義されているクラスに関連付けられているメソッドです。クラスのすべてのインスタンスはその静的メソッドを共有します

Java 8では、デフォルトのメソッドとともに、静的メソッドもインターフェイスで許可されています。これにより、ライブラリでヘルパーメソッドを整理しやすくなります。インターフェースに固有の静的メソッドを、別のクラスではなく同じインターフェースに保持できます。

この良い例は:

list.sort(ordering);

の代わりに

Collections.sort(list, ordering);

静的メソッドを使用する別の例もドキュメント自体に記載されています。

public interface TimeClient {
    // ...
    static public ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +
                "; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

    default public ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }    
}

0

「抽象」はメソッドがオーバーライドされることを意味し、「静的」メソッドをオーバーライドすることはできないためです。


この答えは、以前の答えがまだ対処していないことを何も追加しません。
MarsAtomic、2015

@MarsAtomic私は、トップ投票の回答よりも適切だと思います。また、それは簡潔です。
Praveen Kumar

その後、十分な担当者がいる場合、以前の回答を編集して改善することができます。あなたがしているのは、重複した答えを作成することによって信号にノイズを追加することだけです。独自に作成して他のすべての人が従うことを期待するのではなく、Stack Overflowの確立されたルールと習慣に従ってください。
MarsAtomic、2015

同意しません。私の回答を他の回答、特に上位投票の回答と比較してください。
Praveen Kumar

「なぜこれができないのですか?」回答:「できないから」。
JacksOnF1re 2016

0

通常のメソッドは、サブクラスによってオーバーライドされ、機能が提供されることを意図している場合、抽象的です。クラスFooBar1, Bar2, Bar3etc によって拡張されていることを想像してください。したがって、それぞれのニーズに応じて、抽象クラスの独自のバージョンを持ちます。

これで、静的メソッドは定義によりクラスに属し、クラスのオブジェクトまたはそのサブクラスのオブジェクトとは何の関係もありません。それらは存在する必要さえなく、クラスをインスタンス化することなく使用できます。したがって、それらはすぐに使える必要があり、機能を追加するためにサブクラスに依存することはできません。


0

アブストラクトはアブストラクトメソッドに適用されるキーワードであるため、本文を指定しないでください。そして、静的キーワードについて話す場合、それはクラス領域に属しています。


回答について少し詳しく説明してください。
Blip

0

クラスで静的メンバーまたは静的変数を使用している場合、クラスのロード時にロードされるためです。


3
そしてなぜそれが問題になるのでしょうか?
eis

-1

これは、Java 8のインターフェースで実行できます。

これはそれに関する公式のドキュメントです:

https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html


2
どうやって?解決策を探しましたが、何も見つかりませんでした。
thouliha 2015年

えっ?それはいけません。すべての静的インターフェイスメソッドは、インターフェイスクラスを使用して呼び出す必要があります。
mmm 2015

8
この答えは間違っており、Javaの初心者に誤解を与えています。これは、他の回答では実装および記述できないため、抽象静的メソッドの例を示すためのものです
Blip

-1

クラスが抽象クラスを拡張する場合、抽象メソッドをオーバーライドする必要があり、それは必須であるためです。また、静的メソッドはコンパイル時に解決されるクラスメソッドであるため、オーバーライドされたメソッドは実行時に解決され、動的ポリモーフィズムに従うインスタンスメソッドです。


この混乱を大文字にして句読点を付けてください。
Lorneの侯爵、2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.