2013-05-24 6 views
9

Tôi có một lớp đơn giản như dưới đây, nhưng tôi có một câu hỏi về việc sử dụng Generics để trả về một giá trị.Làm thế nào để trả về một số bằng cách sử dụng Generics trong Java?

import java.util.ArrayList; 
public class Box<T extends Number> { 
    private ArrayList<T> list; 
    public Box(){ 
     list = new ArrayList<T>(); 
    } 
    public T get(int i){ 
     if(i <list.size()) 
      return list.get(i); 
     else 
      return 0; // Problem 
    } 
} 

tôi phải nhận được 0 (hoặc 0.0 - nó phụ thuộc vào giá trị của T) khi tôi < list.size() không phải là rỗng. Làm thế nào tôi có thể mã này đúng cách để làm điều đó?

+2

Trả lại 'null' thay vào đó, 0 không phải là đối tượng. –

+2

Vấn đề là mặc dù bạn đã viết "return 0", java cần trả về một thể hiện của lớp T, mà không được biết tại thời gian biên dịch. –

Trả lời

9

Nếu bạn thực sự muốn trở về 0 theo mặc định, bạn có thể làm một cái gì đó như thế này:

public abstract class Box<T extends Number> { 
    private List<T> list; 

    public Box(){ 
     list = new ArrayList<T>(); 
    } 

    public T get(int i){ 
     if(i <list.size()) 
      return list.get(i); 
     else 
      return getDefault(); 
    } 

    protected abstract T getDefault(); 
} 

Sau đó, có một thực hiện đối với từng số kiểu phụ bạn muốn hỗ trợ, ví dụ như

public class IntegerBox extends Box<Integer> { 

    @Override 
    protected Integer getDefault() { 
     return 0; 
    } 
} 

public class DoubleBox extends Box<Double> { 

    @Override 
    protected Double getDefault() { 
     return 0D; 
    } 
} 

vv

Một tính năng thú vị của việc này là nó có thể trả về bất kỳ giá trị mặc định nào, không chỉ bằng 0 ... và nguyên tắc tương tự sẽ hoạt động đối với bất kỳ loại đối tượng nào, không chỉ là số.

+1

Trong khi điều này có thể là một giải pháp * tốt, bạn phải triển khai một lớp con cho mỗi lớp mở rộng 'Số':' Byte', 'Ngắn',' Số nguyên', 'Dài',' Float', 'Đôi',' BigInteger', 'BigDecimal',' AtomicInteger' (và trên ...). Có nhiều mã làm điều này hơn là chỉ xử lý một kết quả 'null' hoặc xử lý một' Ngoại lệ '. –

+2

Có nhiều mã hơn ... nhưng nó cho người hỏi ban đầu những gì anh ta yêu cầu! –

+0

IMO nỗ lực để làm thiết kế * tốt * không đáng giá đối với trường hợp cụ thể này. –

2

0int và Generics chỉ hoạt động với các tham chiếu đối tượng (không phải kiểu gốc). Một cách để sửa mã của bạn sẽ trả về null thay thế.

public T get(int i){ 
    if(i <list.size()) { 
     return list.get(i); 
    } 
    return null; // Problem solved 
} 

tôi phải nhận được 0 (hoặc 0.0 - nó phụ thuộc vào T) khi tôi < list.size() không null

Đi vào tài khoản mà chủ đề thuyết trình như hiển thị 0 cho người dùng phải được xử lý bởi các lớp/phương thức hiển thị dữ liệu, không phải bằng các phương pháp này. Điều này có nghĩa là, không có cách nào để trả về 0 khi bạn phải trả về tham chiếu đối tượng.

9

Nếu bạn thực sự cần Box của bạn để trả về một giá trị không hoặc mặc định rằng khi get bạn không tìm thấy một trận đấu, bạn có thể có một tham số constructor cho không hoặc mặc định của loại T.

Sau đó trở về mặc định mà giá trị trong phương thức get của bạn.

Ví dụ:

public class Box<T extends Number> { 
    private ArrayList<T> list; 
    private T defaultValue; 
    public Box(T defaultValue){ 
     list = new ArrayList<T>(); 
     this.defaultValue = defaultValue; 
    } 
    public T get(int i){ 
     if(i <list.size()) 
      return list.get(i); 
     else 
      return defaultValue; 
    } 
} 
2

Bạn không thể làm điều đó mà không cần tạo lớp con cho tất cả các loại và không có parameterizing và kiểm tra rõ kiểu dữ liệu. Và điều này là bình thường: Tôi có thể tạo ra một loại

public StrictlyPositiveInteger implements Number 

mà thậm chí không có giá trị 0, và sau đó làm

Box<StrictlyPositiveInteger> box = new Box<>(); 

Nói cách khác: bạn muốn hành vi cụ thể đối với các loại cụ thể, vì vậy bạn không thể làm điều đó một cách chung chung.

+0

Giải thích và ví dụ cụ thể. – jahroy