2012-02-13 68 views
12

Tôi có một enumGenerics sử dụng Enum trong Java

public enum Days { 
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
THURSDAY, FRIDAY, SATURDAY 

}

Tôi muốn thực hiện một lớp có thể mất giá trị của ngày loại. Vì vậy, tôi sử dụng Java Generics

public class State<T extend Days> 

Nhưng có một lỗi

The type parameter T should not be bounded by the final type Days. 
Final types cannot be further extended 

Làm thế nào tôi có thể giải quyết này?

Trả lời

6

Không sử dụng Generics ràng buộc. Không cần. Chỉ cần sử dụng một loại vô biên, như thế này:

public class State<T> { 
    public State(T startState) { 
     // whatever 
    } 
} 

Và để sử dụng nó:

State<Days> dayState = new State<Days>(Days.SUNDAY); 

Đây là một lớp học đánh máy đơn giản mà không cần một ràng buộc.

duy nhất ràng buộc mà có thể có ý nghĩa là một ràng buộc với một enum:

public class State<T extends Enum<T>> { 
    public State(T startState) { 
     // whatever 
    } 
} 

Phiên bản này đòi hỏi rằng các tham số chung là một enum. Với phiên bản này, ví dụ sử dụng ở trên vẫn sẽ biên dịch, nhưng điều này sẽ không biên dịch (ví dụ):

State<String> dayState = new State<String>("hello"); 

String không phải là một enum.

+7

Đó không phải là những gì OP muốn. OP muốn chấp nhận chỉ ngày, không phải bất cứ điều gì ở tất cả hoặc bất kỳ enum. Không chỉ anh ta không cần một generics ràng buộc để làm điều đó, anh ta không cần phải sử dụng Generics ở tất cả. – Malcolm

+0

@Malcolm Vâng, anh ta có thể dùng Generics cho lớp 'State' của mình (theo mã của tôi). Anh ta chỉ không cần chung chung để bị ràng buộc. Tôi hiểu ý anh là gì, nhưng anh * có thể làm cho lớp của anh ấy chung chung - nó có vẻ như một lớp học tiện dụng để có thỏa thuận với tình trạng ban đầu/hiện tại – Bohemian

+1

Nó không phục vụ mục đích mà OP đã chỉ định. Anh ấy cần một lớp học hoạt động vào Ngày hoặc con cái của nó: 'Tôi muốn tạo ra một lớp học có thể lấy giá trị của ngày loại'. Vì không có trẻ em cho bất kỳ enum, ông nên viết ngày rõ ràng. Mã của bạn không giới hạn giá trị cho Ngày. – Malcolm

5

Bạn không thể mở rộng enums trong java (http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html về phía cuối). Như vậy là không thể.

-Nếu bạn cần lớp học của bạn chỉ làm việc với enum của bạn, bạn không cần Generics

-Nếu thay vào đó bạn cần nó để làm việc với những người khác enum (nó làm cho tinh thần?), Bạn không cần phải chỉ định phần mở rộng.

Chính xác lớp học của bạn làm gì?

9

enums nhiều loại thức, có nghĩa là, bạn không thể mở rộng từ họ

một chung chung như muốn có một lớp như Parameter đó là ngày hay một lớp mở rộng, nhưng các lớp mở rộng là không thể

nên tham số chỉ có thể là ngày và bạn không cần phải có chung, nếu chỉ có một giá trị có thể

+1

-1 Bạn đang thiếu điểm ở đây. Bất kỳ loại nào đều có thể - đó là một lớp trạng thái chung. – Bohemian

+0

@Bohemian Không, tôi nghĩ đó là bạn đã bỏ lỡ điểm. Xem nhận xét cho câu trả lời của bạn. – Malcolm

2

này biên dịch tốt đối với tôi dưới Java 6:

public enum Days { 
    SUNDAY, 
    MONDAY, 
    TUESDAY, 
    WEDNESDAY, 
    THURSDAY, 
    FRIDAY, 
    SATURDAY 
} 

public class State<T extends Days> { 
    T state; 

    public State(T startState) { 
    this.state = startState; 
    } 
} 

private void test() { 
    State<Days> state = new State<Days> (Days.MONDAY); 
} 

Tuy nhiên, nếu bạn muốn đối tượng State bạn để thay đổi từ một enum khác bạn sẽ được tốt hơn để sử dụng một cái gì đó như:

public class State<S extends Enum<S>> { 
    final ArrayList<S> states = new ArrayList<S>(); 
    private S state; 

    public State(S startState) { 
    states.addAll(EnumSet.allOf(startState.getClass())); 
    this.state = startState; 
    } 

    public S next() { 
    return state = states.get((state.ordinal() + 1) % states.size()); 
    } 

    public S prev() { 
    return state = states.get((state.ordinal() - 1 + states.size()) % states.size()); 
    } 

    public S set(S newState) { 
    return state = newState; 
    } 

    public S get() { 
    return state; 
    } 
} 

private void test() { 
    State<Days> state = new State<Days> (Days.MONDAY); 
    // ... 
} 
+0

'this.states = (S []) states.toArray();' ném một 'ClassCastException'! Tôi đang làm việc trên một giải pháp. – OldCurmudgeon

+0

Đã khắc phục sự cố 'ClassCastException'! – OldCurmudgeon

+0

Nhưng S vẫn có thể là bất kỳ Enum, nó không phải là một 'ngày' enum ... – FBB

5

Những điều cần làm ở đây là

public enum Days{..} 

public class State { // no generic argument! 
    ... 
} 

Khi đứng, bạn không thể có State<T extends Days> vì cách duy nhất để làm hài lòng T extends Days là phải có TđượcDays. Đó là ý nghĩa của việc Daysfinal.

Vì vậy, thay vào đó, bạn nên chắc Statekhông generic, và sử dụng Days trực tiếp ở khắp mọi nơi bạn đang cố gắng sử dụng T. Bạn không thể khai báo public class State<Days>, vì sau đó nó sẽ cố xử lý Days dưới dạng biến số , không phải là lớp Days và đó là không phải là những gì bạn muốn.