2015-10-31 2 views
2

я работаю на некотором множестве абстракций, представляющих результат SQL набора и написал эти методы:Java компилятор не согласован с безопасностью общего вызова метода

public interface Column<T>{ 
    //some methods 
} 

public class SqlRowExtractor{ 

    public void doExtraction(){ 
     Collection<Column<?>> cols = getColumns(); //Returns the collection of Column<T>. 
                //A particular result set may contain, 
                //for instance 2 Column<Date>, 
                //1 Column<Integer> and so fotrh 

     for(Column<?> c : cols){ 
      put(c, get(c)); //1 <-------------------- HERE 
          //Compile-error 
     } 
     //other staff 
    } 

    public <T> void put(Column<T> c, T o){ 
     //put the extracted value in another place 
    } 

    public <T> T get(Column<T> c) throws SQLException{ 
     //extract the value of the row for the Column<T> c 
    } 
} 

Я получил компиляцию ошибки в //1, хотя совершенно ясно, подписи put и get методов, что нет возможности поставить inaprop соответствующее значение. Как я могу исправить ошибку безопасным способом? Сообщение об ошибке:

The method put(Column<T>, T) is not applicable for the arguments 
(Column<capture#3-of ?>, capture#4-of ?) 
+0

Где появляется ваш цикл for? (то есть в каком классе и какой метод) – Eran

+0

@Eran В методе класса. Класс содержит все перечисленные здесь методы. Но как это важно, когда на самом деле появляются петли? –

+0

@Eran Исправлено, не могли бы вы рассмотреть вопрос об обновлении? –

ответ

1

Это не компилируется, поскольку компилятор не понимает, что использование типа джокера для вызов get - это тот же тип, что и использование типа wild-card для вызова set, даже если методы используются с одним и тем же объектом.

Вы можете решить это, введя метод util с параметром типа. Таким образом, тип wild-card используется только один раз, и внутри метода параметры типа будут иметь конкретный тип, который компилятор может понять, что он тот же, который используется в нескольких местах.

Конкретный тип, который присваивается типу джокера в каждом отдельном месте, где она используется, называется захвата типа джокера, и ему присваивается имя, как capture#3-of ? компилятором.

Следующие компилирует:

private <T> void getPut(Column<T> c) throws SQLException { 
    // Compiles because the type's capture, which in non-wildcard, has been bound to T 
    put(c, get(c)); 
} 

public void doExtraction() throws SQLException { 
    Collection<Column<?>> cols = getColumns(); 
    for(Column<?> c : cols) { 
     // Compiles because wild-card type of c is only used once 
     getPut(c); 
    } 
} 

Тот же метод используется в example of capturing conversion in the JLS.

1

Я не уверен, что именно то, что вы пытаетесь сделать, но для меня, если вы хотите, чтобы сделать все тип безопасно, то вам нужно пройти по типу столбца. Чтобы убедиться, что все они используют один и тот же тип.

interface Column<T>{ 
    //some methods 
} 

class SqlRowExtractor{ 

    public <T> Collection<Column<T>> getColumns(Class<T> clss) { 
     return null; 
    } 
    public <T> void doExtraction(Class<T> clss) throws SQLException{ 
     // Type T needs to be specified before this so compiler 
     // can check it. 
     Collection<Column<T>> cols = getColumns(clss); 
     for(Column<T> c : cols){ 
      put(c, get(c)); 
     } 
     //other staff 
    } 

    public <T> void put(Column<T> c, T o){ 
     //put the extracted value in another place 
    } 

    public <T> T get(Column<T> c) throws SQLException{ 
     //extract the value of the row for the Column<T> c 
     return null; 
    } 
} 
1

Вы должны изменить свой код, потому что в этой форме он не может скомпилироваться. Ваш код не является безопасным для текста для компилятора. Вы можете написать его в следующем виде

interface Column<T>{ 

    /** 
    * extracts valu from the column 
    * 
    * @return the value 
    */ 
    T value() throws SQLException; 
} 

public class test{ 

    public void doExtraction() throws SQLException { 
     Collection<Column<?>> cols = getColumns(); //Returns the collection of Column<T>. 
     for(Column c : cols){ 
      put(c, c.value()); 
     } 
    } 

    public <T> void put(Column<T> c, T o){ 
     //put the extracted value in another place 
    } 

} 

этот код работает, и каждый столбец отвечает за извлечение значения