27

このコード構成では:

public MyClass(Integer... numbers) {
    do_something_with(numbers[]);
}

numbersこれがコンパイル時にチェックされるような方法で少なくとも1つのエントリを含むことを要求することは可能ですか? (もちろん、実行時に numbers.length だけをチェックできます。)

明らかに私はこれを行うことができます:

public MyClass(Integer number, Integer... more_numbers) {
    do_something_with(number, more_numbers[]);
}

しかし、これはあまりエレガントではありません。

私がこれをしたい理由は、サブクラスがこのコンストラクターを呼び出すことを単に忘れないようにするためです。これは、デフォルトでsuper()リストに番号のない への呼び出しになります。この場合、おなじみのエラー メッセージを取得したいと思います: Implicit super constructor is undefined. Must explicitly invoke another constructor.

このコンストラクターを非暗黙的としてマークする@-注釈のように、同じことを達成する別の方法はありますか?

4

7 に答える 7

22

少なくとも 1 つの引数を持つ最善の方法は、次のように追加することだと思います。

public MyClass (int num, int... nums) {
    //Handle num and nums separately
    int total = num;
    for(i=0;i<nums.length;i++) {
        total += nums[i];
    }
    //...
}

同じ型の引数を varargs と共に追加すると、コンストラクターはそれ (少なくとも 1 つの引数) を強制的に要求します。次に、最初の引数を個別に処理する必要があります。

于 2015-12-07T19:51:09.423 に答える
9

これを行うための信じられないほどハックな方法の 1 つは、引数のないメソッドを作成し、非推奨としてマークすることだと思います。次に、次の 2 つのフラグを使用してコンパイルします-Xlint:deprecation -Werror。これにより、非推奨のメソッドを使用すると、コンパイル時エラーが発生します。

編集(最初の回答から長い時間):

ハックの少ない解決策は、MyClass(Integer... numbers)コンストラクターを捨てて、それを置き換えることMyClass(Integer[] numbers)です (そして、引数なしのプライベートコンストラクターを追加します)。これにより、コンパイラはスーパー クラス コンストラクターを暗黙的に使用できなくなりますが、引数はなく、コンパイル時のエラー メッセージが表示されます。

./some_package/Child.java:7: error: constructor Parent in class Parent cannot be applied to given types;
    public Child(Integer[] args) {
                                 ^
  required: Integer[]
  found: no arguments
  reason: actual and formal argument lists differ in length

コストは、呼び出し構文がもう少し冗長になることです。

new Child(new Integer[] {1, 2, 3});

もちろん、これを支援するヘルパー関数を作成することもできます。

public static Child newInstance(Integer... numbers) {
    return new Child(numbers);
}

@SafeVarargs
public static <T> T[] array(T... items) {
    return items;
}

その後:

Child c0 = Child.newInstance(1, 2, 3);
Child c1 = new Child(array(1, 2, 3));
于 2012-10-05T22:23:06.647 に答える
8

検証するための独自の方法は、パラメーターを検証することです。

引数を検証します。

if (numbers == null || numbers.length == 0 ) {
            throw new IllegalArgumentException("Your angry message comes here");
        }
于 2012-10-05T18:37:34.827 に答える
2

コメントに記載されているように、いいえ、var 引数を少なくともサイズ 1 にすることはできないようです。

私が考えることができる唯一のコンパイル時の修正はInteger[]、コンストラクターへの引数として単に配列 () を要求することです。サブクラスは引き続きコンストラクターで var 引数を取ることができ、クラスの他のユーザーは、コンストラクターを呼び出す前に目的の引数から配列を作成するだけで済みます。

于 2012-10-05T18:39:02.003 に答える
1
public MyClass(boolean ignore, Integer... numbers) {
    do_something_with(numbers[]);
}
于 2012-10-05T19:31:05.220 に答える
0

これを行うことができる非常にハックな方法は、そのメソッドのプライベート バージョンをパラメーターなしで作成することです。これにより、少なくともこのクラスの外部にいる人がコンパイル時に 1 つのパラメーターを渡すことを防ぐことができますが、有用なエラー メッセージは表示されません。しかし、少なくとも 1 つの値が渡されることが非常に重要な場合は、そのようになります。

private MyClass() {
    // This exception will be thrown only if you manage to do a "new MyClass()"
    // within your own class since it is private.
    throw new RuntimeException("Why did you do this?!?"); 
}
于 2012-10-05T18:46:32.177 に答える
0

̶f̶u̶n̶c̶t̶i̶o̶n̶クラス自体ではなく、̶f̶u̶n̶c̶t̶i̶o̶n̶クラスを呼び出すときだと思います。配列で ̶f̶u̶n̶c̶t̶i̶o̶n̶ クラスを呼び出す前に、配列に要素があることを確認してください。

于 2012-10-05T19:45:12.470 に答える