Доступ к скрытым полям суперкласса при использовании отражения

Я объясню это на примере, так как я не могу объяснить проблему.

Давайте возьмем 2 класса, как показано ниже,

public class Vehicle {
    public String series = "Sedan";
}

public class Audi extends Vehicle {
    public String series = "A8";
}

Теперь я хочу получить как серии автомобилей, так и Audi. Так что я могу использовать,

Audi audi = new Audi();
Vehicle vehicle = audi;
String audiSeries = audi.series; //This will give me "A8"
String vehicleSeries = vehicle.series; //This will give me "Sedan"

Вот моя проблема: Но если у меня нет доступа к Vehicle а также Audi классы во время компиляции и могут использовать только отражение, чтобы получить объект, как я могу получить vehicle's series,

Class audiClass = Class.forName("Audi");
Class vehicleClass = Class.forName("Vehicle");

Object audiObj = audiClass.newInstance();
Field audiSeries = audiClass.getField("series");

System.out.println(audiSeries.get(audiObj));

Выход: A8

Есть ли в любом случае, чтобы получить Vehicle учебный класс' series Поле "Седан" по вышеуказанному способу.

PS: я не могу изменить дизайн, чтобы избежать этой проблемы.

3 ответа

Решение

Я сам был удивлен, что вы можете получить доступ к полю Транспортного средства, просто наложив его на Автомобиль.

Ваш подход работает, вам просто нужно сделать последний шаг, используя поле из класса транспортного средства:

Audi audi = new Audi();
Vehicle vehicle = audi;
String audiSeries = audi.series; 
System.out.println("direct-audi: " + audiSeries);
String vehicleSeries = vehicle.series; 
System.out.println("direct-vehicle: " + vehicleSeries);


Class audiClass = Class.forName(Audi.class.getName());
Class vehicleClass = Class.forName(Vehicle.class.getName());


Object audiObj = audiClass.newInstance();
Field audiSeriesField = audiClass.getField("series");
Field vehicleSeriesField = vehicleClass.getField("series");

System.out.println("reflection-audi: " + audiSeriesField.get(audiObj));
System.out.println("reflection-vehicle: " +  vehicleSeriesField.get(audiObj));

Результат:

direct-audi: A8
direct-vehicle: Sedan
reflection-audi: A8
reflection-vehicle: Sedan

Если вы не знаете имя суперкласса, вы можете просто использовать Class vehicleClass = audiClass.getSuperclass();

Вы можете решить это следующим образом:

Field someField = someClass.getDeclaredField("fieldname");
someField.setAccessible(true);
Object val = someField.get(someObj);

Но это не то, для чего предполагается использовать рефлексию, и в целом довольно уродливое решение, которое вы не должны использовать. Кроме того, эти операции довольно дороги. Вы должны просто реализовать метод getter для обязательных полей. Если вам нужно использовать вышеупомянутое решение, вам следует подумать о том, чтобы полностью переработать его, так как это далеко от чистого ООП.

Если вы можете добавить getter в суперклассе это поможет вам:

public class Audi extends Vehicle {
    String myString = "A8";

    public static void main(String[] args) throws Throwable {
        System.out.println(new Audi().myString);        // outputs A8
        System.out.println(new Audi().getMyString());   // outputs Sedan
    }

}

class Vehicle {
    String myString = "Sedan";

    public String getMyString() {
        return myString;
    }
}
Другие вопросы по тегам