使用反射访问 super class 的隐藏字段
Accessing super class's hidden fields while using reflection
我无法解释这个问题,我将通过示例来解释它。
让我们取 2 类 如下,
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"
我的问题来了:
但是如果我在编译过程中无法访问 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));
Output: A8
Is there anyway to get Vehicle
class' series
field "Sedan" in
the above method.
P.S:我无法更改设计来避免这个问题。
如果您可以在超级 class 中添加一个 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 还很远。
我自己也很惊讶,你可以通过将 ist 施放给载具来访问载具的字段。
您的 Approch 有效,您只需使用车辆中的 Field 进行最后一步-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();
我无法解释这个问题,我将通过示例来解释它。
让我们取 2 类 如下,
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"
我的问题来了:
但是如果我在编译过程中无法访问 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));
Output: A8
Is there anyway to get
Vehicle
class'series
field "Sedan" in the above method.
P.S:我无法更改设计来避免这个问题。
如果您可以在超级 class 中添加一个 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 还很远。
我自己也很惊讶,你可以通过将 ist 施放给载具来访问载具的字段。
您的 Approch 有效,您只需使用车辆中的 Field 进行最后一步-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();