2013-06-18 3 views
0

Извините за титул ...Отражение полезно?

У меня есть метод, как Foo() используется, как показано ниже

public static <T> void foo(T fld1, T fld2) { 
    // here i use some info from fld1 and some from fld2 in order 
    // to do something 
} 
foo(a1.myField, a2.myField) 
  • Я хочу быть уверен, что во время компиляции, что MyField действительно поле объект
  • Я хочу, чтобы избежать необходимости повторить .myField два раза
  • Я хочу, чтобы один не может вызвать метод как foo(a1.myField, a2.anotherField);

Я не знаю, является ли отражение ответом на мою проблему.

я могу написать что-то вроде этого:

static <C> void foo(C o1, C o2, String fieldName) { 
    try { 
     Object fld1 = o1.getClass().getField(fieldName).get(o1); 
     Object fld2 = o2.getClass().getField(fieldName).get(o2); 
     // here i use some info from fld1 and some from fld2 in order 
     // to do something 
    } catch (Exception e) { 
    } 
} 

, но я не могу проверить во время компиляции, если FIELDNAME является допустимым именем поля для класса C

Было бы полезно иметь метод

Field getField(Object field) 

так что

getField(a1.myField) 

равно

a1.getClass().getField("myField") 

Сейчас я пишу этот метод:

public static <T> Field getField(T o, Object fld) { 
    Field rv = null; 
    try { 
     Field[] fields = o.getClass().getFields(); 
     for (Field field : fields) { 
      Object f = field.get(o); 
      if (f==fld) { 
       rv = field; 
       break; 
      } 
     } 
    } catch (Exception e) { 
    } 
    return rv; 
} 

и использовать этот способ

getField(a1, a1.myField); 

Спасибо за любой ответ, Carlo

+0

Возвращает ли myField и anotherField один и тот же тип? Или какой тип они возвращаются? – Damian0o

+0

myField и anotherField имеют один и тот же тип (иначе я получаю ошибку компиляции), но я хочу этого избежать. Я хочу, чтобы fld1 и fld2 были одним и тем же полем двух разных экземпляров одного и того же класса – Carlo

ответ

2

вы можете сделать проверку с instanceOf в методе во время выполнения.

только пример:

if(fd1 instanceOf Fd1Obj) 
2

Я хочу быть уверен, что во время компиляции ..

Reflection все о выполнения. Так что это не полезно для компиляции времени.

+0

Я знаю, но, возможно, он может помочь не для времени компиляции, а для проверки ограничений. – Carlo

0

Как насчет статического родовой для убедившись, что это объект:

static <T extends Object> void foo(T fld1, T fld2) { 
    // ... 
} 

Вы можете использовать отражение, чтобы получить названное поле от объекта:

AType myField1 = (AType)fld1.getClass().getField("myField").get(fld1); 
AType myField2 = (AType)fld2.getClass().getField("myField").get(fld2); 
+1

'extends Object' несколько лишний ... –

+0

Извините, но я не понимаю. fld1 и fld2 - это поля, поэтому я не могу выполнить 'fld1.getClass(). getField (« myField »)' в классе fld1 не существует поля «myField». – Carlo

+0

Я изменил свой вопрос, предложив вам, чтобы вы могли понять, почему это не ответ для меня. – Carlo

0

Вы можете указать тип при вызове foo (..) like:

yourClass.foo (a1.myField, a2.myField).

Таким образом, вы можете быть уверены, что проверка типов выполняется при компиляции.

Однако, это не является обязательным, если вы не предоставите тип аргумента, то есть в данном случае, документация Java говорит, что:

алгоритм вывода пытается найти наиболее конкретный тип, который работает с все аргументы.

посмотрите здесь:

http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

И никакого отражения не будет, что хорошо о помощи для компиляции проверки времени.

+0

Я думаю, что мой вопрос недостаточно ясен ... Метод foo() является статическим и не относится к определенному классу. – Carlo

+0

Статический метод относится к классу, а не к какому-либо конкретному экземпляру. Поэтому, когда вы вызываете его, вы можете указать аргументы типа. Надеюсь, я получу тебя. – hakish

+0

Извините, но ... я хочу, чтобы fld1 и fld2 были одним и тем же полем двух разных экземпляров одного и того же класса (но я не знаю, и мне все равно, что это за класс) – Carlo

0

Это многословие на Java, но ямбам Java8 должен сделать это меньше. Что вам нужно, это время компиляции проверил способ получения из объекта типа С к некоторому значению типа Т. способа указать, что в Java является интерфейс:

public interface Getter<C, T> { 
    T get(C c); 
} 

Затем вам задать функцию

static <C, T> void foo(C c1, C c2, Getter<C, T> getter) { 
    T fld1 = getter.get(c1); 
    T fld2 = getter.get(c2); 
    // ... 
} 

И вы называете это так - это часть, которая раздражающе многословным:

foo(a1, a2, new Getter<A, Integer>() { 
    public Integer get(A a) { return a.fieldName; } 
}); 

лямбды Java8 сделает это значительно более удобным для чтения:

foo(a1, a2, a -> a.fieldName); 
+0

Спасибо! да, это многословие! – Carlo

Смежные вопросы