Các lớp được đánh giá cao trong ngôn ngữ Java


96

Một số lớp trong Java API tiêu chuẩn được xử lý hơi khác so với các lớp khác. Tôi đang nói về những lớp không thể được triển khai nếu không có sự hỗ trợ đặc biệt từ trình biên dịch và / hoặc JVM.

Những thứ tôi nghĩ ra ngay lập tức là:

  • Object (rõ ràng) vì nó, trong số những thứ khác không có một lớp siêu cấp.
  • String vì ngôn ngữ có hỗ trợ đặc biệt cho toán tử +.
  • Thread vì nó có phương thức start () kỳ diệu này mặc dù thực tế là không có lệnh bytecode nào "phân nhánh" việc thực thi.

Tôi cho rằng tất cả các lớp như thế này theo cách này hay cách khác được đề cập trong JLS. Sửa cho tôi nếu tôi sai.

Dù sao thì, những lớp nào khác như vậy tồn tại? Có danh sách đầy đủ nào về "các lớp được tôn vinh" trong ngôn ngữ Java không?


2
Generics gần như phù hợp, nhưng không hoàn toàn. Chúng được triển khai bằng thủ thuật trình biên dịch, nhưng chúng không bị cô lập trong một lớp.
Bill the Lizard

2
Chúng đều là những kiểu tôn kính. ;-)
starblue

1
"Thread.start" có kỳ diệu không? Chắc chắn đó chỉ là một số mã gốc được gọi để làm điều này?
jcoder 13/10/10

Ý nghĩ đó cũng đã xảy ra với tôi. Có lẽ chỉ riêng JNI là đủ để triển khai lớp Thread. Tôi cho rằng nếu tôi cố gắng làm điều này, tôi sẽ sử dụng một số api luồng cấp hệ điều hành, phân nhánh việc thực thi trong quá trình triển khai phương thức start (), thực thi phương thức run () trong luồng phân nhánh và quay trở lại. Nhưng sau đó chuỗi hệ điều hành của tôi sẽ tiếp tục chạy. Điều đó có chạy trơn tru cùng với các luồng được tạo bởi JVM không? và tôn vinh mô hình bộ nhớ JLS và như vậy?
aioobe

2
Theo thông số kỹ thuật, cách duy nhất để tạo một luồng là từ lớp Thread ( java.sun.com/docs/books/jvms/second_edition/html/… ). Tất nhiên, nó dựa trên một số giao tiếp cấp độ nguyên bản với JVM, nhưng nếu bạn đã thực hiện JNI của riêng mình, bạn có thể bắt đầu một chuỗi, nhưng bạn sẽ không khiến JVM hiểu được bạn đang làm gì (khóa, mô hình bộ nhớ, v.v. ). Thread được đặc quyền ở chỗ spec gán cho nó một đặc quyền - cách duy nhất để bắt đầu một thread.
Yishai

Câu trả lời:


35

Có rất nhiều câu trả lời khác nhau, vì vậy tôi nghĩ sẽ hữu ích nếu thu thập tất cả (và thêm một số câu trả lời):

Các lớp học

  • Các lớp AutoBoxing - trình biên dịch chỉ cho phép các lớp cụ thể
  • Lớp - có các ký tự của riêng nó (ví dụ: lớp int.class). Tôi cũng sẽ thêm kiểu gõ chung của nó mà không cần tạo phiên bản mới.
  • Chuỗi - với quá tải + -operator và sự hỗ trợ của các ký tự
  • Enum - lớp duy nhất có thể được sử dụng trong một câu lệnh switch (sắp tới đây cũng là một đặc quyền được trao cho String). Nó cũng thực hiện những việc khác (tạo phương thức tĩnh tự động, xử lý tuần tự hóa, v.v.), nhưng về mặt lý thuyết, những thứ đó có thể được thực hiện bằng mã - nó chỉ là rất nhiều bản soạn sẵn và một số ràng buộc không thể được thực thi trong các lớp con (ví dụ: quy tắc phân lớp đặc biệt) nhưng điều mà bạn không bao giờ có thể thực hiện được nếu không có trạng thái riêng tư của một enum là đưa nó vào một câu lệnh switch.
  • Đối tượng - gốc của tất cả các đối tượng (và tôi sẽ thêm các phương thức sao chép và hoàn thiện của nó không phải là thứ bạn có thể thực hiện)
  • Tài liệu tham khảo : WeakReference, SoftReference, PhantomReference
  • Người Gởi - ngôn ngữ không cung cấp cho bạn một hướng dẫn cụ thể để bắt đầu một chủ đề, chứ không phải nó kỳ diệu áp dụng nó vào phương pháp start ().
  • Throwable - gốc của tất cả các lớp có thể hoạt động với ném, ném và bắt, cũng như hiểu biết về trình biên dịch về Exception so với RuntimeException và Error.
  • NullPointerException và các trường hợp ngoại lệ khác như ArrayIndexOutOfBounds có thể được ném bởi các lệnh bytecode khác ngoài điền kinh.

Giao diện

  • Iterable - giao diện duy nhất có thể được sử dụng trong một tăng cường cho vòng lặp

Những đề cập danh giá được chuyển đến:

  • java.lang.reflect. Mảng - không thể tạo một mảng mới như được xác định bởi một đối tượng Lớp.
  • Chú thích Chúng là một tính năng ngôn ngữ đặc biệt hoạt động giống như một giao diện trong thời gian chạy. Bạn chắc chắn không thể xác định một giao diện Chú thích khác, giống như bạn không thể xác định một giao diện thay thế cho Đối tượng. Tuy nhiên, bạn có thể triển khai tất cả các chức năng của chúng và chỉ có một cách khác để lấy chúng (và cả một loạt các bản ghi sẵn) thay vì phản ánh. Trên thực tế, đã có nhiều triển khai dựa trên XML và thẻ javadoc trước khi các chú thích được giới thiệu.
  • ClassLoader - nó chắc chắn có mối quan hệ đặc quyền với JVM vì không có cách ngôn ngữ nào để tải một lớp, mặc dù có một cách bytecode, vì vậy nó giống như Array theo cách đó. Nó cũng có đặc quyền đặc biệt là được gọi lại bởi JVM, mặc dù đó là chi tiết triển khai.
  • Serializable - bạn có thể triển khai chức năng thông qua phản chiếu, nhưng nó có từ khóa đặc quyền riêng và bạn sẽ mất nhiều thời gian để làm quen với SecurityManager trong một số trường hợp.

Lưu ý: Tôi đã loại ra khỏi danh sách những thứ cung cấp JNI (chẳng hạn như IO) vì bạn luôn có thể triển khai lệnh gọi JNI của riêng mình nếu bạn có khuynh hướng như vậy. Tuy nhiên, các cuộc gọi gốc tương tác với JVM theo những cách đặc quyền thì khác.

Mảng có thể gây tranh cãi - chúng kế thừa Đối tượng, có cấu trúc phân cấp dễ hiểu (Đối tượng [] là một siêu kiểu của Chuỗi []), nhưng chúng là một đặc điểm ngôn ngữ, không phải là một lớp xác định của riêng nó.


@Donal, rất đúng, tôi đã nghĩ đến chú thích thời gian chạy, nhưng chú thích cấp nguồn thực sự được thực hiện theo cách đó (xdoclet rõ ràng nhất, hoặc thậm chí trong java lõi với @deprecated)
Yishai

Tôi vừa đấu tranh theo cách của mình thông qua một tập mã ban đầu được viết bằng xử lý xdoclet và sau đó được chuyển đổi thành chú thích. Ồ, làm thế nào tôi thích chú thích hơn (mặc dù, với các câu thần chú phù hợp, hiệu ứng thực là như nhau).
Donal Fellows

@ KK_07k11A0585, Bộ sưu tập là một api tiêu chuẩn có thể được xây dựng bởi bất kỳ ai theo một cách khác (trên thực tế, có những cách triển khai thay thế hướng đến những điều nguyên thủy, cũng như một dự án rất nổi tiếng của Google nhằm nâng cao chúng). Điều duy nhất họ nhận được là đặc biệt là Iterable, được đề cập trong câu trả lời. Chắc chắn rằng chúng là bánh mì và bơ của lập trình java, nhưng chúng chỉ là các lớp học thông thường, không có đặc quyền đặc biệt.
Yishai

@Yishai Trong khi phát triển bất kỳ ứng dụng nào, điều quan trọng chính là QUẢN LÝ DỮ LIỆU. Tất cả chúng ta đều có thể thực hiện một tác vụ theo nhiều cách khác nhau, nhưng cách được tối ưu hóa là cách chiếm ít bộ nhớ hơn và ít sử dụng các tham chiếu không cần thiết hơn. Bằng cách sử dụng Bộ sưu tập, chúng tôi có thể sắp xếp, tìm kiếm và so sánh lượng lớn dữ liệu, cung cấp các thuật toán được xác định trước như Tìm kiếm nhị phân, Sắp xếp hợp nhất, v.v. Nó cũng cung cấp cho chúng tôi các Giao diện So sánh và So sánh để tùy chỉnh các kỹ thuật của chúng tôi. Lớp Collections có thể không phải là lớp tốt nhất trong java, nhưng nó chắc chắn là một lớp có phẩm chất được tôn vinh.
KK_07k11A0585,

1
Về SecurityManagerthì sao? Hoặc bất cứ điều gì liên quan đến phản ánh hoặc tuần tự hóa?
Antimony

19

Class, tất nhiên. Nó có các nghĩa riêng của nó (một sự khác biệt mà nó chia sẻ String, BTW) và là điểm khởi đầu của tất cả phép thuật phản chiếu đó.


Ah, điểm tốt. Vì vậy, một ví dụ về một lớp nghĩa đen là gì? Bạn đang đề cập đến MyClass.class?
aioobe

4
@aioobe: chính xác. Lưu ý rằng bạn cũng có int.class, char.class, v.v.
Michael Borgwardt


12
  1. Enum. Bạn không được phép phân lớp nó, nhưng trình biên dịch có thể.
  2. Nhiều thứ trong java.util.concurrent có thể được triển khai mà không cần hỗ trợ JVM, nhưng chúng sẽ kém hiệu quả hơn rất nhiều.

1
Bạn có thể ẩn danh phân lớp phụ (là cơ sở của mẫu khách truy cập cho giá trị enums). Nhưng có, bạn không thể phân loại hoàn toàn một enum ;-)
Thierry

11

Tất cả các lớp Số đều có một chút ma thuật ở dạng Autoboxing .


Ý của bạn là các lớp bao bọc các lớp nguyên thủy - cũng bao gồm Boolean và Character; nhưng loại trừ BigInteger.
emory

1
@emory: Đúng vậy, chỉ là các lớp trình bao bọc nguyên thủy. Thật không may, điều đó không loại trừ BigInteger.
Bill the Lizard

10

Vì các lớp quan trọng đã được đề cập, tôi sẽ đề cập đến một số giao diện:

Các Iterablegiao diện (từ 1.5) - nó cho phép một đối tượng tham gia trong một vòng lặp foreach:

Iterable<Foo> iterable = ...;
for (Foo foo : iterable) {

}

Các Serializablegiao diện có một ý nghĩa rất đặc biệt, khác với một giao diện chuẩn. Bạn có thể xác định các phương thức sẽ được tính đến ngay cả khi chúng không được xác định trong giao diện (như readResolve()). Các transienttừ khóa là yếu tố ngôn ngữ có ảnh hưởng đến hành vi của Serializablengười thực hiện.


Đúng, chúng là giao diện mặc dù, vì vậy chúng không yêu cầu triển khai "đặc biệt" mỗi lần xem. (Tương tự như Throwable.)
aioobe

Serializable thực sự yêu cầu triển khai đặc biệt. Đó là một giao diện mà bạn dự kiến ​​sẽ có hai phương thức (tôi quên tên ... Tôi có thể google nó ...) nhưng chúng không được yêu cầu hoặc xác định trong lược đồ giao diện chuẩn.
corsiKa

@glowcoder: tuy nhiên, có thể lập luận rằng tất cả sự đặc biệt của Serializable không liên quan đến ngôn ngữ Java, chỉ liên quan đến việc triển khai ObjectOutputStream và ObjectInputStream.
Michael Borgwardt

5
@Michael Borgwardt nó có - transienttừ khóa
Bozho

1
Tôi không nghĩ vậy - Comparablekhông tham gia vào bất cứ điều gì nội bộ. Bạn có thể dễ dàng viết NewComparablevà viết mới NewArrays.sort(..)với cùng chức năng
Bozho 11/10/10

6
  1. Throwable , RuntimeException, Error AssertionError
  2. Người giới thiệu WeakReference, SoftReference, PhantomReference
  3. Enum
  4. Chú thích

Danh sách đẹp. +1, Tuy nhiên, chú thích là một giao diện và không có triển khai.
aioobe

1
Các chú thích được trình biên dịch xử lý khác với các giao diện bình thường. Tương tự như enum, tất cả chúng đều mở rộng Annotation và trình biên dịch thực hiện điều đó một cách tự động. Từ JavaDoc of Annotation: Giao diện chung được mở rộng bởi tất cả các loại chú thích. Lưu ý rằng giao diện mở rộng thủ công này không xác định loại chú thích. Cũng lưu ý rằng bản thân giao diện này không xác định kiểu chú thích. Vì vậy, bạn không thể tạo chú thích bằng cú pháp thông thường, họ cần thay đổi trình biên dịch để thêm chúng.
Andrei Fierbinteanu



2

Không chắc chắn về điều này. Nhưng tôi không thể nghĩ ra cách thực hiện các đối tượng IO theo cách thủ công.


Bạn nói đúng, chúng không thể được triển khai bằng Java thuần túy. Chúng cần được thực hiện thông qua JNI (giống như bất kỳ lớp nào khác cần thực hiện các cuộc gọi hệ thống). Tuy nhiên, ngoài điều đó, chúng không cần hỗ trợ đặc biệt từ trình biên dịch hoặc jvm.
aioobe

2

Có một số phép thuật trong Systemlớp.

System.arraycopy là một móc nối vào mã gốc

public static native void arraycopy(Object array1, int start1, 
  Object array2, int start2, int length);

nhưng...

/**
 * Private version of the arraycopy method used by the jit
 * for reference arraycopies
 */
private static void arraycopy(Object[] A1, int offset1,
  Object[] A2, int offset2, int length) {
   ...
}

1
Ý bạn là gì trong phần thứ hai của câu trả lời?
Pacerier

1

Kể từ khi xử lý đặc biệt của khẳng định đã được đề cập. Dưới đây là một số loại Ngoại lệ khác được jvm xử lý đặc biệt:

  • NullPointerException
  • ArithmeticException.
  • StackOverflowException
  • Tất cả các loại OutOfMemoryErrors
  • ...

Các ngoại lệ không phải là đặc biệt, nhưng jvm sử dụng chúng trong các trường hợp đặc biệt, vì vậy bạn không thể tự thực hiện chúng nếu không viết jvm của riêng mình. Tôi chắc chắn rằng có nhiều ngoại lệ đặc biệt xung quanh.


0

Hầu hết các lớp đó không thực sự được triển khai với sự trợ giúp 'đặc biệt' từ trình biên dịch hoặc JVM. Đối tượng thực hiện đăng ký một số bản địa chọc ngoáy các cấu trúc JVM bên trong, nhưng bạn cũng có thể làm điều đó cho các lớp của riêng mình. (Tôi thừa nhận điều này phụ thuộc vào ngữ nghĩa, "các cuộc gọi bản địa được xác định trong JVM" có thể được coi là hỗ trợ JVM đặc biệt.)

Điều / là / đặc biệt là hành vi của các hướng dẫn 'mới' và 'ném' trong cách chúng khởi tạo các cấu trúc bên trong này.

Mặc dù vậy, chú thích và con số khá kỳ quặc.


4
aioobe đề cập đến các lớp mà bạn không thể tự triển khai, vì chúng có hỗ trợ xây dựng đặc biệt. Bạn không thể tạo lớp Đối tượng của riêng mình làm gốc của hệ thống kiểu mà không kế thừa biểu mẫu java.lang.Object. Đối tượng được hỗ trợ đặc biệt từ cả trình biên dịch và jvm để đảm bảo rằng nó là một lớp gốc. Các cuộc gọi riêng không đủ để giải quyết vấn đề này.
josefx
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.