Pergunta

Eu tenho um objeto de retorno de chamada genérico que fornece uma capacidade de retorno de chamada (primitiva) para Java, na ausência de encerramentos. O objeto de retorno de chamada contém um método, e retorna os parâmetros e tipos de retorno para o método através de um par de métodos de acesso que só delegar aos métodos equivalentes no método.

Eu estou tentando validar que uma chamada de retorno I foram pontos fornecido a um método válido. Eu preciso do tipo de atribuição retorno compatível com número e todos os parâmetros a ser atribuição compatível com duplo. Meu método validando esta aparência:

static public void checkFunctionSpec(Callback cbk) {
    Class[]                             prms=cbk.getParmTypes();
    Class                               ret =cbk.getReturnType();

    if(!Number.class.isAssignableFrom(ret)) {
        throw new IllegalArgumentException(
           "A function callback must return a Number type " + 
           "(any Number object or numeric primitive) - function '" +
           cbk + "' is not permitted");
        }
    for(Class prm: prms) {
        if(!Double.class.isAssignableFrom(prm)) {
            throw new IllegalArgumentException(
               "A function callback must take parameters of " +
               "assignment compatible with double " +
               "(a Double or Float object or a double or float primitive) " +
               "- function '" + cbk + "' is not permitted");
            }
        }
    }

O problema que eu encontro é que o quando eu tentar isso com, por exemplo, Math.abs (), está lançando uma exceção para o tipo de retorno da seguinte forma:

java.lang.IllegalArgumentException:
A function callback must return a Number type (any Number object or numeric primitive)
- function 'public static double java.lang.Math.abs(double)' is not permitted

Isso foi surpreendente para mim, porque eu esperava primitivos simplesmente trabalho, porque (a) são refletidos utilizando suas classes de mensagens publicitárias, e (b) o Double.TYPE é declarado como sendo do tipo Class .

Alguém sabe como posso conseguir isso sem modificar meus cheques a ser:

if(!Number.class.isAssignableFrom(ret)
     && ret!=Double.TYPE
     && ret!=Float.TYPE
     && ret!=...) {

Clarificação

Quando você invocar o método double abs(double) usando Method.invoke (), você passa em um Object [] {duplo} e voltar um duplo. No entanto, o meu validação parece estar falhando porque Double.TYPE não é atribuível a um duplo. Desde que eu exigir que todos esses retornos de chamada para retornar algum tipo de número, que será retornado por invoke () como um número, eu estou tentando validar que o método fornecidos retorna ou o número ou um valor numérico primitivo.

Validação dos parms é o mesmo.

Em outras palavras, ao usar o reflexo parm e tipos de retorno duplo e dupla são idênticos e eu gostaria de validá-los facilmente como tal.

EDIT: Para esclarecer: Eu quero validar que um método, quando invoke () é chamado retornar um objeto do tipo Number (a partir do qual eu posso chamar obj.doubleValue () para obter a dupla que eu quero) <. / p>

Foi útil?

Solução

Olhando mais de perto a documentação para Class.isAssignableFrom (), ele afirma especificamente que os tipos para um primitivo não combinam com qualquer classe, exceto a si mesmos. Então eu vou precisar verificar especificamente para == igualdade, a Byte.TYPE, Double.TYPE, Float.TYPE, Integer.TYPE, Long.TYPE e Short.TYPE para o tipo de retorno.

Outras dicas

Por que não ter o compilador fazê-lo?

public interface F<A, B> {
   public B $(A a);
}

Em seguida, você pode passar um F<Double, Double> para um método que espera um F<? extends Number, ? extends Number>.

EDIT:

Você diz que quer fornecer uma única classe para o tipo de uma função com qualquer número de argumentos. Este pode ser feito com o sistema de tipo Java. Conceitualmente cada função possui apenas um argumento. Uma função com dois argumentos é equivalente a uma função que retorna outra função. Então aqui está uma variável cujo valor é uma função que leva duas duplas:

F<Double, F<Double, Double>> f;

Aqui está um método que passa dois duplos para uma determinada função:

public Double operate(F<Double, F<Double, Double>> f, double a, double b) {
   return f.$(a).$(b);
}

Ou, considere um tipo L<A extends L> com duas subclasses C<E, T extends L<T>> representando um "contras", e um tipo terminator N:

public abstract class L<A extends L<A>> {  
 private L() {}  

 private static final N nil = new N();  

 public static N nil() {  
   return nil;  
 }  

 public static final class N extends L<N> {  
   private N() {}  

   public <E> C<E, N> cons(final E e) {  
     return new C<E, L>(e, this);  
   }  
 }  

 public static final class C<E, L extends L<L>> extends L<C<E, L>> {  
   private E e;  
   private L l;  

   private C(final E e, final L l) {  
     this.e = e;  
     this.l = l;  
   }  

   public E head() {  
     return e;  
   }  

   public L tail() {  
     return l;  
   }  

   public <E> C<E, C<E, L>> cons(final E e) {
     return new C<E, C<E, L>>(e, this);
   }  
 }  

}  

Em tal caso, uma, você pode implementar um tipo de função assim:

public interface F<A extends L<A>, B> {
   public B $(A args);
}

O método seguinte espera uma função com dois argumentos Double (e retorna um Double), juntamente com duas doubles a aplicá-lo a:

public Double operate(F<C<Double, C<Double, N>>, Double> f, double a, double b) {
   return f.$(N.nil().cons(b).cons(a));
}

A implementação da interface F teria que obter os argumentos da lista usando head e tail. Então, na verdade, você está implementando LISP em Java. :)

Dito isto, veja Funcional Java , que é uma biblioteca que tem um monte dessas coisas já. Estou certo de que há também um lá fora, que usa a reflexão para que você não tem que escrever-se.

O parâmetro para Math.abs () é o duplo primitivo. Eu não tenho certeza do que você quer dizer com um ser "atribuição compatível" primitivo com um objeto (o que a reflexão API significa, essencialmente, é "pode ??ser um elenco de"). Mas se você quer dizer "pode ??passar para um construtor Double", então isso é, essencialmente, um primitivo double (ou uma string) !! Talvez você precisa para esclarecer um pouco mais o que você precisa fazer?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top