2012-02-03 31 views
11

Tôi đã học được rằng lớp công khai duy nhất trong một tệp Java cũng phải có phương thức chính. Tuy nhiên, dưới đây bạn có thể thấy phương pháp chính bên trong một lớp bên trong thay vào đó? Quy tắc liên quan đến định nghĩa phương thức chính trong tệp nguồn là gì?Phương pháp chính trong lớp tĩnh bên trong.

public class TestBed { 
    public TestBed() { 
     System.out.println("Test bed c'tor"); 
    } 

    @SuppressWarnings("unused") 
    private static class Tester { 
     public static void main(String[] args) { 
      TestBed tb = new TestBed(); 
      tb.f(); 
     } 
    } 

    void f() { 
     System.out.println("TestBed::f()"); 
    } 
} 
+0

Điều đó sẽ có tác dụng nếu bạn thực hiện điều đó public class bên trong. – Thilo

+0

Nó hoạt động như hiện tại. Tuy nhiên, trong trường hợp của tôi, tôi phải thoát khỏi ký tự '$' để khởi động từ trình bao: '$ java TestBed \ $ Tester' – Vlad

+0

@Thilo - lớp NESTED cần ** không ** công khai. Công khai chỉ đúng với các phiên bản Java đầu tiên (rất). Ngày nay Java là _smart_ đủ để tìm phương thức trong các lớp riêng (được thử nghiệm với Java 5, 6 & 7 trên Windows XP) –

Trả lời

5

Nếu bạn muốn bắt đầu một lớp học với java (Java launcher: java test.MyClass) thì lớp này phải có một phương pháp chính với chữ ký nổi tiếng.

Bạn có thể có phương thức chính có cùng chữ ký ở bất cứ đâu bạn muốn. Nhưng đừng nghĩ rằng trình khởi chạy sẽ tìm thấy nó.

P.S. Tên của ngôn ngữ là Java, không phải là JAVA.

Có một chi tiết nhỏ:

Bạn có thể làm điều này:

package test; 

public class Test { 

    /** 
    * @param args the command line arguments 
    */ 
    static public class A { 

     public static void main(String[] args) { 
      System.err.println("hi"); 
     } 
    } 
} 

java test.Test $ A

nhưng điều này là không đạt tiêu chuẩn ...

+0

Tôi tự hỏi nếu nó sẽ làm việc trong trường hợp này, vì lớp chứa phương thức chính là riêng tư, tĩnh và không được sử dụng ở bất kỳ đâu. –

+1

@KurtDuBois - nó hoạt động, nhưng bạn phải sử dụng đúng tên lớp 'TestBed $ Tester' để bắt đầu nó. –

+1

Lưu ý rằng khi chạy trong một \ * nix shell, bạn có thể phải thoát khỏi '$': 'java test.Test \ $ A'. –

2

Mỗi ứng dụng Java phải có phương pháp chính. Đó là điểm bắt đầu để thực thi mã trong ứng dụng. Chữ ký của phương thức là:

public static void main(String[] args) 

Lớp bên trong tĩnh là lớp được định nghĩa bên trong định nghĩa của lớp khác và được đánh dấu là tĩnh.

Ví dụ: nếu lớp bên ngoài được đặt tên là TestBed, thì lớp bên trong của TestBed, được đặt tên là Tester, sẽ được biên dịch thành TestBed $ Tester.class. Việc tách các tệp .class có nghĩa là bạn có thể giữ mã bổ sung, lồng nhau được kết hợp chặt chẽ với lớp chính, bên ngoài.

Chúng nằm trong cùng một tệp nguồn và lớp bên trong thực sự nằm trong lớp bên ngoài. Tất cả điều đó và bạn không phải trả bất kỳ loại triển khai hoặc chi phí thời gian chạy nào.

Bằng cách sử dụng lớp bên trong tĩnh, bạn có thể thêm chức năng hỗ trợ bổ sung vào hệ thống của mình cho các khả năng như thử nghiệm, trong khi không bị phạt trong triển khai sản xuất thông thường.

Để thực hiện phương thức main() của lớp TestBed.Tester,

% java TestBed$Tester 
+0

là pedantic: theo định nghĩa (JLS 8.1.3) một _inner class_ là một lớp lồng nhau được ** không ** khai báo 'static'! –

4

Bất kỳ lớp nào có thể có phương pháp tĩnh đều có thể có public static void main(String[] args).

Điều này bao gồm:

các lớp cấp cao nhất (dù là công khai hay không), ví dụ:

public class Foo { 
    public static void main(String[] args) { 
     System.out.println("Hello"); 
    } 
} 

và các lớp tĩnh bên trong (dù là công khai hay không) (ví dụ như ví dụ của bạn).

Nó không bao gồm:

  • lớp nặc danh
  • bên trong các lớp học không tĩnh

Vì vậy, cả hai đều bất hợp pháp:

public class Foo { 
    private Object bar = new Object() { 
     public static void main(String[] args) { 
      System.out.println("Hello"); 
     } 
    }; 
} 


public class Foo { 
    private class Bar { 
     public static void main(String[] args) { 
      System.out.println("Hello"); 
     } 
    }; 
} 
+0

pedantic: _inner classes_ có thể ** không ** có một phương thức tĩnh - JLS 8.1.3: '[...] Các lớp bên trong có thể không khai báo các khởi tạo tĩnh (§8.7) hoặc các giao diện thành viên [...]'. Không có các lớp static_ _inner nào, mỗi định nghĩa (JLS 8.1.3 một lần nữa) một lớp _inner là một lớp lồng nhau không tĩnh. –

+0

@CarlosHeuberger Bạn hoàn toàn đúng. Tôi đã cẩu thả trong thuật ngữ của tôi, sử dụng từ 'bên trong' interchanably với 'lồng nhau'. –

+0

Cho phép nói một lớp công khai có phương thức chính và lớp có lớp bên trong tĩnh với phương thức chính. JVM sẽ tìm và chạy lớp nào có phương thức chính? Làm thế nào để nó giải quyết hai lớp học? – user3705478

-1

Đây là thú vị như mã sẽ biên dịch và chạy trong Eclipse, nhưng sẽ chỉ biên dịch từ việc sử dụng dòng commmand. Khi bạn chạy từ nhật thực, nó sẽ tìm ra phương thức tĩnh chính từ bên trong lớp bên trong và chạy nó.

Nhưng khi chạy java TestBed từ dòng lệnh, bạn sẽ gặp lỗi - Exception in thread "main" java.lang.NoSuchMethodError: main là lỗi hợp lệ vì bạn chưa xác định phương thức chính trong lớp chính.

Tại sao bạn muốn xác định phương pháp chính của mình trong lớp bên trong? Phương pháp chính của bạn nên được định nghĩa trong lớp công khai, đây không phải là một quy tắc nhưng thực tế phổ biến.

Trong mã dưới đây tôi đã chuyển sang phương pháp chính vào lớp bên ngoài mà làm việc cả trong Eclipse dòng & lệnh:

public class TestBed { 
    public TestBed() { 
     System.out.println("Test bed c'tor"); 
    } 

    @SuppressWarnings("unused") 
    private static class Tester { 

    } 

    public static void main(String[] args) { 
     TestBed tb = new TestBed(); 
     tb.f(); 
    } 

    void f() { 
     System.out.println("TestBed::f()"); 
    } 
} 
+0

Sai: dòng lệnh - 'java TestBed $ Tester' - hoạt động tốt (Windows XP, Java 6 & 7) và không cần lớp có phương thức chính là công khai. –

+0

Tất nhiên java TestBed $ Tester hoạt động tốt, java Tester sẽ không. "không cần thiết cho lớp học có phương pháp chính để được công khai" Tôi nhận ra nó không cần thiết, tôi chỉ gợi ý thực hành phổ biến là gì, ít nhất là trong những gì tôi đã thấy. Tôi chưa bao giờ thấy cần phải khai báo một lớp chính "cuối cùng" hoặc "trừu tượng". –

+0

chắc chắn 'java Tester' sẽ không hoạt động, không phải trong Eclipse. Bạn phải sử dụng tên lớp đúng, đủ điều kiện. Và bạn không chỉ "chỉ gợi ý thực hành phổ biến là gì" - bạn đã viết rằng nó sẽ chỉ biên dịch từ việc sử dụng dòng lệnh' (nhưng không thực thi) - điều đó sai - nó chạy từ dòng lệnh! Còn "cuối cùng" hoặc "trừu tượng" thì sao? Bạn là người đầu tiên sử dụng các điều khoản này ở đây (trừu tượng BTW sẽ không biên dịch với tĩnh và chính phải là tĩnh). –

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