Безопасно ли типизировать «стертый» объект? - PullRequest
1 голос
/ 30 июня 2019

Класс (реализующий универсальный интерфейс) имеет метод, который возвращает java.lang.Object тип данных вместо ожидаемого. Безопасно ли вводить его в операторе вызывающего абонента?

import java.io.*; 
import java.lang.*;

interface dataCharge<A>{
    public A change(A ele); 
}

class APCDcharge implements dataCharge<APCDcharge>{
    private String name;
    private Integer charge;
    public void setName(String name){
        this.name = name;
    }
    public void setCharge(Integer charge){
        this.charge = charge;
    }
    public String getName(){
        return name;
    }
    public Integer getCharge(){
        return charge;
    }
    public String getKey(){
        return name+":"+charge;
    }
    @Override
    public APCDcharge change(APCDcharge ele){
        APCDcharge newele = new APCDcharge();
        newele.setCharge(ele.getCharge()+100);
        newele.setName(ele.getName());
        return newele;
    }
}

public class Main {
    public static void main(String[] args) {
        APCDcharge c = new APCDcharge();
        c.setName("ABC");
        c.setCharge(100);
        APCDcharge d = timePass(c);
        System.out.println(d.getKey());
    }
    private static <T extends dataCharge> T timePass(T element){
        T res = element.change(element);
        return res;
    }
}

Приведенный выше фрагмент кода выдает ошибку:

error: incompatible types: Object cannot be converted to T T res = element.change(element);

Я также пробовал типизацию element.change(element) с T типом данных:

T res = (T)element.change(element);

И код компилируется (с предупреждением: Note: Main.java uses unchecked or unsafe operations.), но выполняется правильно. Это безопасный способ удалить ошибку? Есть ли другой способ исправить это?

Ответы [ 2 ]

3 голосов
/ 30 июня 2019

Ваша проблема в том, что в вашем методе static граница типа T является необработанным типом (dataCharge).

Внесите следующие изменения:

private static <T extends dataCharge<T>> T timePass(T element){
    T res = element.change(element);
    return res;
}

т.е. T extends dataCharge<T> вместо T extends dataCharge.

Теперь код пройдет компиляцию без приведения.

0 голосов
/ 30 июня 2019

Этот метод:

static <T extends dataCharge> T timePass(T element){
    T res = element.change(element);
    return res;
}

Использует raw (т.е. нетипизированный) dataCharge. Вы должны ввести его, а также вернуть тип dataCharge, а не (под) класс dataCharge.

Учитывая то, как вы его использовали, то есть для передачи себя в свой собственный метод, предлагает, чтобы dataCharge был проще определен как поставщик из dataCharge и имел прямой доступ к своему собственному состоянию при создании результата:

interface dataCharge<A>{
    public A change(); 
}

class APCDcharge implements dataCharge<APCDcharge> {
    // other code

    @Override
    public APCDcharge change() {
    APCDcharge newele = new APCDcharge();
    newele.setCharge(getCharge()+100);
    newele.setName(getName());
    return newele;
    }
}

Тогда ваш timePass метод становится:

static <T> T timePass(dataCharge<T> element){
    T res = element.change();
    return res;
}
...