案例:充分利用接口和反射,在不改變原有代碼的基礎上實現類的加載
- 現有兩種工具:Car 和Plane,其中Car 的速度運算公式爲:A*B/C,Plane 的速度運算公式爲 :A+B+C,需要編寫三類:ComputeTime.java,Plane.java,Car.java和接Common.java
- 要求在未來如果增加第3種交通工具的時候,不必修改以前的任何程序,只需要編寫新的交通工具的程序,其運行過程如下,從命令行輸入ComputeTime的四個參數,第一個是交通工具的類型,第二、三、四個參數分別時整數A、B、C,
- 舉例如下:
計算Plane的時間:”java ComputeTime Plane 20 30 40″
計算Car007的時間:”java ComputeTime Car 23 34 45″
第3種交通工具爲Ship,則只需要編寫Ship.java,運行時輸入:”java ComputeTime Ship 22 33 44″
首先設計類:
- 首先每種交通工具都需要一個單獨的類,其中有交通工具種類,A,B,C四個成員變量,並且要有計算速度的getSpeed方法
- 然後需要一個主類,接收鍵盤數據,並初始化交通工具類,創建其對象並調用getSpeed方法以輸出相應的數據
- 需要接口,抽象出不同的交通工具子類的getSpeed方法,但由於接口不能實例化,無法利用接口直接調用各類的getSpeed方法
- 最後創建一個Speed類,創建vehicleMethod方法,以接口對象爲參數,在方法中調用各自的getSpeed方法,從而可以在主類中實現對象調用方法
主類:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Scanner;
/**
* @Description: 利用反射來加載類
* @author: Joker
* @date: 2017年1月29日 下午8:30:26
*/
public class Java_4
{
public static void main(String[] args)
{
for (int i = 0; i < 10000; i++)
{
//鍵盤輸入對應格式的數據
Scanner sc = new Scanner(System.in);
System.out.println("請按格式輸入數據");
String string = sc.nextLine();
// 正則表達式,根據空格拆分此字符串
String[] str2 = string.split(" ");
// 獲取對象名和A,B,C的值
String vehicleName = str2[2];
int A = Integer.valueOf(str2[3]);
int B = Integer.valueOf(str2[4]);
int C = Integer.valueOf(str2[5]);
try
{
//獲取輸入的類的字節碼文件對象
Class vehicleClass = Class.forName("com.cskaoyan.Day19_HomeWork."
+ vehicleName);
//獲取構造方法,並將鍵盤接受的數據傳入對其進行初始化
Constructor constructor = vehicleClass.getConstructor(String.class, int.class, int.class, int.class);
//創建接口對象。父類的引用指向子類的實例,實現多態
TansportMeans t = (TansportMeans) constructor.newInstance(vehicleName,new Integer(A), new Integer(B), new Integer(C));
//創建speed對象,實現對vehicleMethod方法的調用
Speed vehicle = new Speed();
vehicle.vehicleMethod(t);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
catch (NoSuchMethodException e)
{
e.printStackTrace();
}
catch (SecurityException e)
{
e.printStackTrace();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
}
}
}
接口及實現多態的類:
/**
* @Description:創建接口,定義交通工具中特有的方法
*/
interface TansportMeans
{
public abstract void getSpeed();
}
/**
* 創建speed類,利用vehicleMethod方法實現對各種交通工具類中getSpeed()方法的調用
*/
class Speed
{
public void vehicleMethod(TansportMeans vehicle)
{
vehicle.getSpeed();
}
}
交通工具類:
/**
* Car類的成員變量是vehicleName,A,B,C,
* 爲了接收鍵盤輸入的數據,必須要有構造方法
* 要實現接口中的getSpeed方法,必須對ABC進行相應處理並輸出
*/
class Car implements TansportMeans
{
String vehicleName;
int A, B, C;
/**
* @Description:car類構造方法,用於初始化類
*/
public Car(String vehicleName, int a, int b, int c)
{
this.vehicleName = vehicleName;
A = a;
B = b;
C = c;
}
/**
* @Description:car類計算速度的方法
*/
@Override
public void getSpeed()
{
System.out.println(vehicleName + "的速度是:" + (A * B / C));
}
}
/**
* plane類的成員變量是vehicleName,A,B,C,
* 爲了接收鍵盤輸入的數據,必須要有構造方法
* 要實現接口中的getSpeed方法,必須對ABC進行相應處理並輸出
*/
class Plane implements TansportMeans
{
String vehicleName;
int A, B, C;
//構造方法
public Plane(String vehicleName, int a, int b, int c)
{
this.vehicleName = vehicleName;
A = a;
B = b;
C = c;
}
@Override
public void getSpeed()
{
System.out.println(vehicleName + "的速度是:" + (A + B + C));
}
}
最後,新增一個ship類,直接編寫類ship.java,即可實現ship的速度的計算
class Ship implements TansportMeans
{
String vehicleName;
int A, B, C;
//構造方法
public Ship(String vehicleName, int a, int b, int c)
{
this.vehicleName = vehicleName;
A = a;
B = b;
C = c;
}
@Override
public void getSpeed()
{
System.out.println(vehicleName + "的速度是:" + ((A + B) * C));
}
}
控制檯輸出結果:
請按格式輸入數據
java ComputeTime Car 23 34 45
Car的速度是:17
請按格式輸入數據
java ComputeTime Plane 20 30 40
Plane的速度是:90
請按格式輸入數據
java ComputeTime Ship 22 33 44
Ship的速度是:2420
請按格式輸入數據