Отражение в общем классе Java - PullRequest
1 голос
/ 18 ноября 2010

У меня есть следующие классы (это просто упрощенный пример):

public abstract class Material {
    public abstract String name();
    /* ... */
}

public class Wood extends Material {
    @Override
    public String name() {
        return "<WOOD>";
    }
    /* ... */
}

public class Metal extends Material {
    @Override
    public String name() {
        return "{Metal}";
    }
    /* ... */
}

public class Car<T extends Material> {
    public void printName() {
        System.out.println(T.name()); // Here is the problem!
    }
    /* ... */
}

public class Main {
    public static void main(String[] args) {
        Car<Wood> myCar1 = new Car<Wood>();
        Car<Metal> myCar2 = new Car<Metal>();
        myCar1.printName();
        myCar1.printName();
    }
}

Проблема указана в коде.

Ответы [ 6 ]

3 голосов
/ 18 ноября 2010

Это, наверное, как я бы это реализовал. Если это удовлетворительно или нет для вашей ситуации, я не могу сказать.

enum Material {

    WOOD("<WOOD>"),
    METAL("{Metal}");

    String name;
    private Material(String name) {
        this.name = name;
    }
    public String toString() {
        return name;
    }
}

class Car {
    Material material;
    public Car(Material material) {
        this.material = material;
    }
    public void printName() {
        System.out.println(material);
    }
}

public class Main {
    public static void main(String[] args) {
        Car myCar1 = new Car(Material.WOOD);
        Car myCar2 = new Car(Material.METAL);
        myCar1.printName();
        myCar2.printName();
    }
}
2 голосов
/ 18 ноября 2010

Вот одна проблема:

name - это метод экземпляра (не статический), но вы пытаетесь назвать его как статический.

Это должно исправить это

public class Car<T extends Material> {
    public void printName( T material ) {
        System.out.println( material.name()); 
    }
    /* ... */
}
1 голос
/ 18 ноября 2010

В вашем вопросе много недоразумений:

  1. name() не является статической функцией, поэтому вам нужен экземпляр материального объекта для его вызова.даже если name() были статическими, вы не можете вызывать статический метод из общего имени.

Решение?Создайте перечисление материала:

public enum Material {
    WOOD("wood"), 
    METAL("metal");

    private final String name;

    Material(String name) {
        this.name = name;
    }
}

А в машине класс стал:

public class Car {
    private final Material m;

    public Car(Material m) {
        this.m = m
    }

    public void printName() {
        System.out.println(m.name);
    }
    /* ... */
}
1 голос
/ 18 ноября 2010

Проблема заключается в том, что вы пытаетесь вызвать метод экземпляра, не имея экземпляра объекта, для которого он вызывается.

0 голосов
/ 18 ноября 2010

Это никогда не сработает, так как ваш 'T' является всего лишь "подсказкой компилятора", и вы не можете получить доступ к классу, определенному T во время выполнения, если вы не обращаетесь к нему явно в своих функциях.

Это не то, как работают дженерики java: когда вы компилируете свой код, любая ссылка на Wood и Metal теряется, и ваши 2 объекта "Car" идентичны.

Попробуйте это:

myCar1 = new Car<Wood>();
System.out.println(myCar1 instanceof Car<Metal>);
0 голосов
/ 18 ноября 2010

T определяет тип, а name() должен быть статическим для вызова в этом контексте. Также рассмотрим:

public class Car<T extends Material> {
    protected T material;
    // initialize material in constructor or wherever you want.
    ....
    public void printName() {
        System.out.println(material.name()); // there is no problem
    }
    /* ... */
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...