2013-10-23 12 views
6

Tôi tình cờ gặp lừa này để nhận giá trị từ một lớp bên trong vô danh đến một biến được khai báo trong lớp bên ngoài. Nó hoạt động, nhưng nó cảm thấy như một hack bẩn:Sử dụng mảng 1 phần tử cuối cùng cho lớp bên trong vô danh

private int showDialog() 
{ 
    final int[] myValue = new int[1]; 

    JPanel panel = new JPanel(); 
    final JDialog dialog = new JDialog(mainWindow, "Hit the button", true); 
    dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 

    JButton button = new JButton("Hit me!"); 
    button.addActionListener(new ActionListener() 
    { 
     @Override 
     public void actionPerformed(ActionEvent e) 
     { 
      myValue[0] = 42; 
      dialog.setVisible(false); 
     } 
    }); 

    panel.add(button); 
    dialog.add(panel); 
    dialog.pack(); 
    dialog.setVisible(true); 

    return myValue[0]; 
} 

(. Vâng, tôi nhận ra ví dụ này có thể được thay thế bằng một đơn giản JOptionPane, nhưng hộp thoại thực tế của tôi là phức tạp hơn nhiều) Chức năng bên trong khẳng định rằng tất cả các biến nó tương tác với là final, nhưng tôi không thể khai báo myValue là cuối cùng vì hàm bên trong cần gán cho nó một giá trị. Khai báo nó như là một mảng 1 phần tử được xung quanh vấn đề này, nhưng có vẻ như nó có thể là một Bad Thing TM bằng cách nào đó. Tôi tự hỏi nếu a.) Đây là thực tế phổ biến hoặc b.) Có bất kỳ vấn đề nghiêm trọng mà có thể kết quả từ việc này.

Trả lời

0

Điều đó không có vẻ bẩn. Tôi thực sự không thể nói được nó phổ biến như thế nào, và tôi không biết rằng bạn đang mạo hiểm phá hủy thế giới bằng cách làm điều đó, nhưng nếu tôi cần một thứ như thế này, tôi muốn cắn viên đạn và viết lớp bên trong chính thức (thay vì loại vô danh) để thực hiện ActionListener. Bằng cách đó bạn có thể có nó ảnh hưởng đến các trường của lớp bao quanh và gọi các phương thức khác trong lớp kèm theo khi cần thiết. Tùy thuộc vào chính xác những gì bạn đang làm, nó thậm chí có thể là giá trị nó để chỉ cần đi tất cả trong và phân lớp Dialog để giữ logic này.

Là phần thưởng, các lớp bên trong vô danh giúp bạn gỡ lỗi một chút vì bạn có nhiều thông tin nhận dạng lớp học có sẵn cho bạn.

0

Tôi không nghĩ rằng có vấn đề với mã của bạn. Đôi khi tôi phải sử dụng một cái gì đó tương tự nhưng tôi sử dụng một lớp đặc biệt mà kết thúc tốt đẹp giá trị và tôi gọi một setter trong lớp bên trong nhưng kết quả cuối cùng là như nhau.

private static class Result{ 
    private Integer value; 

    //getter and setters here 

} 

.... 

final Result result = new Result(); 

... 
new InnerClass(){ 

    void foo(){ 
     result.setValue(42); 
    } 
} 

Vấn đề là các lớp bên trong chỉ có thể tham chiếu biến cuối cùng vì địa chỉ bộ nhớ của chúng sẽ không thay đổi.

Lời khuyên duy nhất của tôi đối với bạn là không sử dụng int[] làm giá trị mà là Integer[] để bạn có thể biết sự khác biệt giữa giá trị 0 và giá trị không được đặt (giá trị = null).

+0

Điểm tốt về điều 'int' so với' Số nguyên', nhưng trên thực tế, có nhiều loại khác nhau (không phải thường là nguyên thủy) được truy cập bởi các hộp thoại này, vì vậy đó là một điều nhỏ nhặt. Ngoài ra, vì trong trường hợp này hộp thoại là phương thức và không thể đóng được mà không nhấn nút, nó được đảm bảo khá nhiều không phải là một vấn đề. –

3

Nếu mã là dễ đọc, nó là gì, tôi sẽ không nói làm theo cách đó là khủng khiếp.

Cách khác là để JButton gọi hàm trong lớp có showDialog (được cho phép). Hàm có thể đặt một biến cá thể sẽ được trả về. Nhưng điều đó có vẻ kém rõ ràng hơn với tôi, vì vậy tôi thực sự thích phương pháp của bạn hơn.

Trừ khi bạn đang tạo một khung giao diện người dùng phân cấp sâu sắc, đôi khi những hacks nhỏ này chính xác là thứ bạn nên làm.

Nếu bạn đang quan tâm, bạn có thể làm về cơ bản điều tương tự với một lớp bên trong tin:

private class DialogReturnValue { 
    public int value; 
} 

private int showDialog() 
{ 
    final DialogReturnValue myValue = new DialogReturnValue(); 

    JPanel panel = new JPanel(); 
    final JDialog dialog = new JDialog(mainWindow, "Hit the button", true); 
    dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 

    JButton button = new JButton("Hit me!"); 
    button.addActionListener(new ActionListener() 
    { 
     @Override 
     public void actionPerformed(ActionEvent e) 
     { 
      myValue.value = 42; 
      dialog.setVisible(false); 
     } 
    }); 

    panel.add(button); 
    dialog.add(panel); 
    dialog.pack(); 
    dialog.setVisible(true); 

    return myValue.value; 
} 

Và có cũng ActionListeners nhìn (mà cũng có thể là "đúng" cách tiếp cận).

+0

Nếu nó chỉ là một, tôi có thể thấy làm điều này, nhưng có hàng chục hộp thoại, mỗi với các loại điều khiển trên chúng và các yêu cầu khác nhau cho những gì họ cần truy cập. (Các phương thức của hộp thoại thực ra chủ yếu là các kiểu trả về 'void'.) Tôi phải tạo ra rất nhiều lớp bên trong để bao quát tất cả những thứ tôi cần. Phương pháp hiện tại của tôi dường như yêu cầu mã ít nhất. Chỉ muốn chắc chắn nó sẽ không phá vỡ trong một số trường hợp. (Ví dụ như nó an toàn thread? ActionListeners nói chung làm mang lại một số vấn đề đa luồng.) –

+0

không phải là 'actionPerformed' chỉ được gọi khi nhấn nút hoặc một cái gì đó? Tôi không thấy làm thế nào nút sẽ được ép trước khi 'showDialog' trả về. – newacct

+0

Khi tôi hiểu nó (và tôi có thể không hoàn toàn đúng ở đây), việc tạo và hiển thị JDialog làm cho luồng cơ bản khóa ở dòng 'dialog.setVisible (true)' cho đến khi JDialog bị đóng, trong trường hợp này chỉ có thể xảy ra khi nhấn nút. Tất cả tôi biết chắc chắn là nó hoạt động tốt - thread gọi phương thức 'showDialog()' dừng chạy miễn là hộp thoại hiển thị. –

1

Sử dụng AtomicInteger hoặc AtomicReference có thể làm cho nó ít tốt hơn. Nó thực sự là một thực tế phổ biến, nhưng bạn có thể làm cho nó sạch hơn bằng cách giới thiệu lớp thực tế thực hiện ActionListener và cung cấp giá trị thông qua một getter.

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