2013-07-25 32 views
10

Tôi có 3 lớp được gọi là RedAlert, YellowAlert và BlueAlert.Chuyển tên lớp làm tham số

Trong AlertController lớp của tôi, tôi muốn có một phương pháp như thế này:

public void SetAlert(//TAKE IN NAME OF CLASS HERE//) 
{ 
    CLASSNAME anInstance = new CLASSNAME(); 
} 

Vì vậy, ví dụ tôi muốn:

AlertController aController = new AlertController(); 
SetAlert(RedAlert); 

Làm thế nào bạn có trong tên lớp như một tham số, và dựa trên tên lớp đó tạo đối tượng thích hợp từ tên lớp?

+3

Bạn cần xem xét API phản chiếu Java, [Class] (http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html)! – NINCOMPOOP

+0

Nhưng tại sao bạn lại muốn nó? Có gì sai với 'SetAlert (new RedAlert())'? –

Trả lời

16

Sử dụng phản chiếu có thể. Ở đây cho một className đã cho (chuyển thành một chuỗi). Lớp này sẽ được tìm kiếm trong bộ nhớ (nó sẽ được tải).Tên của lớp được khởi tạo khi chuyển dưới dạng chuỗi phải đủ điều kiện

void createInstanceOfClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ 


     Class classTemp = Class.forName(className); 

     Object obj =classTemp.newInstance(); 



    } 
} 
+0

Quản trị viên có thể kiểm tra xem phiếu bầu xuống có đại diện ở đây không? Và người đã làm điều này cũng không đưa ra lời giải thích. –

1

Bạn có thể có một tài liệu tham khảo của lớp trong chữ ký phương pháp của bạn, một cái gì đó như thế này:

public void SetAlert(Class class) 

Sau đó, trong phương pháp của bạn, bạn có thể tạo ra các thể hiện của lớp đầu vào bằng cách sử dụng phương pháp newInstance:

Object obj = class.newInstance(); 
0

Tránh phụ thuộc nội bộ và initialztions:

AlertController aController = new AlertController(new RedAlert()); 
1

Điều gì về điều này -

public void SetAlert(Class<?> class){ 
    Object obj = class.newInstance(); 
    if(obj isInstanceOf RedAlert){ 
     RedAlert ra= (RedAlert)obj; 
    } 
    ... 
} 
+0

+1 để có câu trả lời nhanh :) –

+0

Cảm ơn người đàn ông ....:) –

2

Trong khi bạn có thể tạo bằng cách sử dụng Phản chiếu v.v ... ... Tôi khuyên bạn nên điều tra một số Mẫu thiết kế sáng tạo.

Cụ thể các mẫu máy

Đây là một (rất) ví dụ thô:

public interface Alert { 
} 


public class BlueAlert implements Alert { 
} 

public class RedAlert implements Alert { 
} 

public class YellowAlert implements Alert { 
} 

public final class AlertFactory { 

    public <T extends Alert> Alert create(Class<T> clazz) { 
     Alert toReturn = null; 
     if (RedAlert.class.equals(clazz)) { 
      toReturn = new RedAlert(); 
     } else if (YellowAlert.class.equals(clazz)) { 
      toReturn = new YellowAlert(); 
     } else if (BlueAlert.class.equals(clazz)) { 
      toReturn = new BlueAlert(); 
     } 
     return toReturn; 
    } 
} 

Và sau đó từ phương pháp của bạn, bạn có thể sử dụng:

public void SetAlert(Class alertClass) { 
    Alert theAlert = new AlertFactory().create(alertClass); 
} 

Dù sao, trong khi đây là một ví dụ thực sự xấu xí, tôi đang cố gắng làm nổi bật rằng có thể bạn có thể xem các Mẫu sáng tạo và giải quyết vấn đề của mình theo một cách khác mà không cần phải chuyển các tên lớp xung quanh.

+0

Nhà máy này có thể được cải thiện rất nhiều bằng cách sử dụng 'equals' thay vì' == 'và sử dụng phản chiếu như bạn đã đề xuất ở đầu. Nếu không, hãy tưởng tượng điều gì sẽ xảy ra khi các lớp con 'Alert' mới xuất hiện. –

+0

Tôi đồng ý hoàn toàn! Thật khó để biết chính xác những trường hợp sử dụng là gì, trong ví dụ này, bạn chỉ cần truyền vào đối tượng instantiated. – edwardsmatt

+0

@ raniejade của câu trả lời là một nhà máy sạch hơn thiết kế này. Câu trả lời ở đây sử dụng cách tiếp cận không phải của OO nếu thử nghiệm. raniejade sử dụng phân lớp của nhà máy. – ToolmakerSteve

13

Thay vì chuyển tên lớp, bạn có thể tự chuyển lớp và sử dụng sự phản chiếu để tạo một thể hiện mới của lớp. Dưới đây là một ví dụ cơ bản (giả sử tất cả XxxAlert lớp học của bạn kéo dài từ một lớp Alert):

public <T extends Alert> void setAlert(Class<T> clazzAlert) { 
    Alert alert = clazzAlert.newInstance(); 
    //use the alert object as you want/need... 
} 

Bây giờ bạn chỉ cần gọi phương pháp như thế này:

setAlert(RedAlert.class); 

Lưu ý rằng nó sẽ tốt hơn sử dụng một lớp siêu trong thông số T, nếu không bạn (hoặc một lập trình viên khác) có thể thực hiện điều này:

setAlert(Object.class); 

sẽ sai.

+2

@edwardsmatt là một phần của câu trả lời của tôi, nếu không OP có thể mắc lỗi khi gọi phương thức như trong ví dụ cuối bằng cách sử dụng Object.class (hoặc bất kỳ lớp nào khác) –

+1

Trong hầu hết các trường hợp, điều này tốt hơn câu trả lời được chấp nhận. – ToolmakerSteve

0

Sử dụng enums:

public enum AlertType {RED_ALERT, YELLOW_ALERT, BLUE_ALERT}; 

// ... 

public void SetAlert(AlertType type) 
{ 
    // ... 
} 

// ... 

AlertController aController = new AlertController(); 
SetAlert(AlertType.RED_ALERT); 
0

Sử dụng Java Reflection để tạo đối tượng từ đối tượng Lớp. Khai báo phương pháp của bạn như thế này:

public void SetAlert(Class clazz) 
{ 
    Constructor<?> ctor = clazz.getConstructor(); 
    Object object = ctor.newInstance(); 
} 

Và sau đó,

AlertController aController = new AlertController(); 
    SetAlert(RedAlert.class); 
0

Đây là cách để tạo ra một thể hiện bằng cách sử dụng tên lớp. Kiểu cụ thể của Alert phải có một hàm tạo công khai không có đối số.

private Alert alert; 

public void setAlert(String className) 
{ 
    try { 
    Class<?> raw = Class.forName(className); 
    Class<? extends Alert> type = raw.asSubclass(Alert.class); 
    Constructor<? extends Alert> ctor = type.getConstructor(); 
    this.alert = ctor.newInstance(); 
    } catch (Exception ex) { 
    throw new IllegalArgumentException("Invalid Alert implementation.", ex); 
    } 
} 

Người gọi sẽ sử dụng nó như thế này:

AlertController aController = new AlertController(); 
controller.setAlert("com.y.foo.RedAlert"); 

Nếu bạn tạo một quy ước để thông qua một tập hợp các tham số cho các nhà xây dựng, bạn có thể làm điều đó quá, nhưng bạn sẽ cần phải làm thêm một chút trong cuộc gọi getConstructor() để tìm. Bạn cũng có thể sử dụng các hàm tạo không công khai, nhưng, một lần nữa, phải mất một chút công việc phụ.

Các đề xuất để chuyển lớp học theo nghĩa đen, RedAlert.class, không có ý nghĩa nhiều. Nếu lớp RedAlert có sẵn cho người gọi tại thời gian biên dịch, bạn chỉ cần sử dụng hàm tạo của nó, new RedAlert().

0

Một cách khác bạn có thể làm điều này mà không cần sử dụng sự phản chiếu là phải có Giao diện thông báo và có các lớp của bạn - RedAlert, YellowAlert và BlueAlert triển khai giao diện Cảnh báo.
Bây giờ phương pháp của bạn trong AlertController trông giống như:

public void setAlert(Alert alert) { 
     // Your code goes here 
} 

Bây giờ bạn có thể làm:

setAlert(new RedAlert()); 
setAlert(new YellowAlert()); 
setAlert(new BlueAlert()); 
2

Tại sao không sử dụng một cách tiếp cận mô hình nhà máy.

public interface Alert {} 

public class RedAlert implements Alert {} 
public class YellowAlert implements Alert {} 
public class BlueAlert implements Alert {} 

public interface AlertFactory { 
    Alert create(); 
} 

public class RedAlertFactory implements AlertFactory { 
    public Alert create() { 
     return new RedAlert(); 
    } 
} 

public class YellowAlertFactory implements AlertFactory { 
    public Alert create() { 
     return new YellowAlert(); 
    } 
} 

public class BlueAlertFactory implements AlertFactory { 
    public Alert create() { 
     return new BlueAlert(); 
    } 
} 

// your setAlert method could probably look like this 
public void setAlert(AlertFactory factory) { 
    aInstance = factory->create(); 
} 

Sau đó, bạn có thể làm điều gì đó như thế này.

setAlert(new RedAlertFactory()); // or YellowAlertFactory, BlueAlertFactory 

Có thể sử dụng phương pháp tiếp cận của bạn bằng cách sử dụng java.lang.Class#newInstance.

+0

LƯU Ý: Chỉ cần một bản sao của mỗi nhà máy. Nếu AlertFactory là một lớp chứ không phải là một giao diện, thì nó có thể chứa các biến tĩnh, một cho mỗi nhà máy; 'public abstract class AlertFactory {... public readonly static RedAlertFactory red = new RedAlertFactory(); ...} 'Sau đó, không cần phải tạo một nhà máy mới mỗi khi nó được sử dụng:' setAlert (AlertFactory.red) '. – ToolmakerSteve

Các vấn đề liên quan