使用反射时访问超类的隐藏字段



由于我无法解释这个问题,我将通过一个例子来解释。

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

现在,我想同时得到Vehicle和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"

我的问题来了但是如果我在编译过程中不能访问VehicleAudi类,只能使用反射来获取对象,我怎么能得到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字段"轿车"

p。S:我不能改变设计来避免这个问题。

我自己也很惊讶,你可以通过将list转换为一个Vehicle来访问Vehicle的字段。

你的方法是有效的,你只需要去最后一步,从Vehicle-Class使用字段:

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();

如果你可以在超类中添加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;
    }
}

可以这样解决:

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

但是这是而不是反射应该被用来做什么,并且通常是一个你不应该使用的相当丑陋的解决方案。除此之外,这些手术相当昂贵。您应该简单地为必需的字段实现一个getter方法。如果你需要使用上面的解决方案,你应该考虑重新设计完整的东西,因为这与干净的OOP相去甚远。

相关内容

  • 没有找到相关文章

最新更新