当我拥有的是一个对象时,我可以调用静态java方法吗?

时间:2016-03-06 13:12:36

标签: java

我有一个类库,我没有编写,它定义了几个具有静态方法的类和子类。一个非常简单的例子:

public class Vehicle {
    static String getName() { return "unknown"; }
}

public class Car extends Vehicle {
    static String getName() { return "car"; }
}

public class Train extends Vehicle {
    static String getName() { return "train"; }
}

现在,我有一个物体,它是一辆车,可能是汽车或火车,并且想要调用它的getName()函数。再次,非常剥离:

public class SMCTest {
    public static void main(String[] args) {
        Vehicle vehicle=new Car();
        System.out.println(vehicle.getName());
    }
}

这打印"未知"而不是#34; car",因为JVM不需要或使用该对象来调用静态方法,它只是使用该类。

如果这是我的代码,我会重写车辆库以使用单例和非静态方法,但因为它不是我的代码,所以我宁愿不接触它。

有没有办法调用&#34;真实&#34;的静态方法?对象的类,最好不使用反射?如果有帮助,我可以将上面示例中的vehicle更改为Class <? extends Vehicle>变量并使用它,但我不知道这有助于我避免反思。

2 个答案:

答案 0 :(得分:5)

  

最好不使用反射?

删除该要求,并且:

vehicle.getClass().getMethod("getName").invoke(null);

可以解决问题。

(但是,您应该修复代码。)

答案 1 :(得分:1)

如果您了解所涉及的所有课程,则无需反思。使用java 8(为较低版本的Java创建必要的接口和(匿名)类):

public class VehicleUtil {

    private static final Map<Class<? extends Vehicle>, Supplier<String>> map = createMap();

    private static Map<Class<? extends Vehicle>, Supplier<String>> createMap() {
        Map<Class<? extends Vehicle>, Supplier<String>> result = new HashMap<>();
        result.put(Vehicle.class, Vehicle::getName);
        result.put(Car.class, Car::getName);
        result.put(Train.class, Train::getName);
        return result;
    }

    public static String getName(Vehicle vehicle) {
        return map.get(vehicle.getClass()).get();
    }

    public static void main(String[] args) {
        System.out.println(VehicleUtil.getName(new Vehicle()));
        System.out.println(VehicleUtil.getName(new Car()));
        System.out.println(VehicleUtil.getName(new Train()));
    }
}

以上只是一种更优雅的方式:

public static String getName(Vehicle vehicle) {
    return Vehicle.class.equals(vehicle.getClass()) ? Vehicle.getName()
            : Car.class.equals(vehicle.getClass()) ? Car.getName()
            : Train.class.equals(vehicle.getClass()) ? Train.getName()
            : null;
}