开发者

Java template class that takes an array; any way to enforce that?

I'm writing a template class which should take an array as its type.

public cl开发者_开发百科ass Foo<T> {...}

How best can I enforce that "T" is an array type? (int[], Bar[], ...) Preferably compile time if possible, obviously, but otherwise what is the best way at debug run time to throw an exception or something if T is not an array?


I am going to agree and extend David Blevin's answer. You can put MyClass inside a factory class and make the constructors of MyClass private. This way only code within the factory class can directly instantiate a MyClass. It is up to you to make sure they do the right thing. You can either make the factory clas parameterized (as below) or make the make method itself parameterized.

// T is the component type of the array
public class MyClassFactory < T >
{
      // we can't directly enforce TARRAY=T[], but TARRAY=T[]
      public final class MyClass < TARRAY > 
      {
            private MyClass ( ... arguments ) throws ... exceptions { ... code }
            // no non private constructors
            .... more code
      }

      // this is the only way to construct a MyClass
      // so we indirectly enforced TARRAY=T[]
      public MyClass<T[]> make ( ... arguments ) throws ... exceptions 
      {
            return new MyClass <T[]>( ... arguments ) ;
      }
}


It is not possible to do it exactly how you have asked and have the generic type specify an array or primitive.

The syntax allows for things like:

public class Foo <az09$_ extends MyClassOrInterface & Serializable & Closeable> {...}

Where az09$_ is any valid identifier that may also be parameterized with an identically formatted generic type.

But az09$_ is restricted to being a java identifier, so you cannot do public class Foo<T[]> {...} any more than you can do public class Foo[] {...}.

Typically you would do what you are after in your usage of T, i.e:

public class Foo<T> {

    public T[] processIt(T... ts) {
        // do something
        return ts;
    } 

}


If you actually want to check if the type is an array, it can be done at runtime with the following code, though this is a bit of a hack and not exactly efficient:

public static boolean isArrayType (Object o) {
    return o.getClass().isArray();
}

Ultimately it depends on exactly what you're trying to do.


@emory is on the right track for a clean way to do this without runtime checks. Personally I'd be concerned with readability of the type name - here's a very compact example using inner classes and I think the resulting type name at the end is very readable.

public static class Bar {}
public static class Foo<T> {
    public static class Array<TA> {
        private Array() {}
    }
    public Array<T[]> make() {
        return new Array();
    }
}
Foo.Array<Bar[]> fooray = new Foo<Bar>().make();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜