2016-03-06 72 views
2

我有一個類庫,我沒有寫,它定義了幾個類和子類,它們有靜態方法。一個非常精簡例如:當我擁有一個對象時,我可以調用靜態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()); 
    } 
} 

這將打印「未知」,而不是「車」,因爲JVM不需要,或使用對象調用靜態方法,它只是使用了類。

如果這是我的代碼,我會重寫汽車庫使用單身和非靜態方法,但因爲它不是我的代碼,我寧願不要觸摸它。

有什麼辦法可以調用對象的「真實」類的靜態方法,最好不使用反射?如果有幫助,我可以將上述示例中的vehicle更改爲Class <? extends Vehicle>變量並使用該變量,但我看不出如何幫助我避免反射。

+0

是的,有。因爲您已經知道它的具體類別:「汽車=新車()」,因此您可以簡單地向下拖動「車輛」對象。然後'vehicle.getName()'會返回* car *。不過,這樣做會導致警告,因爲您不應該通過實例訪問靜態方法。 – aribeiro

+3

'Car.getName()'? – Filkolev

+5

你似乎想要一個靜態方法以多態的方式表現。這是不可能的。使用該對象來調用靜態方法顯示了一個應該解決的設計問題。靜態方法應該是一個實例方法。 –

回答

5

最好不使用反射?

丟棄要求,:如問

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

可以解決這個問題。

(但是,您應該修改代碼。)

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; 
} 
+0

這仍然在使用反射。 – chrylis

+0

@chrylis你是什麼意思? –

+0

'getClass()'是一個反射調用。 – chrylis

相關問題