Một lớp tổng hợp trong Java là gì? Tại sao nó nên được sử dụng? Làm thế nào tôi có thể sử dụng nó?
Một lớp tổng hợp trong Java là gì? Tại sao nó nên được sử dụng? Làm thế nào tôi có thể sử dụng nó?
Câu trả lời:
Ví dụ: Khi bạn có câu lệnh switch, java sẽ tạo một biến bắt đầu bằng $. Nếu bạn muốn xem một ví dụ về điều này, hãy xem qua phản ánh java của một lớp có câu lệnh chuyển đổi trong đó. Bạn sẽ thấy các biến này khi bạn có ít nhất một câu lệnh switch ở bất cứ đâu trong lớp.
Để trả lời câu hỏi của bạn, tôi không tin rằng bạn có thể truy cập (ngoài phản ánh) các lớp tổng hợp.
Nếu bạn đang phân tích một lớp mà bạn không biết gì về (thông qua sự phản chiếu) và cần biết những điều rất cụ thể và ở mức độ thấp về lớp đó, thì bạn có thể sẽ sử dụng các phương thức phản chiếu Java phải làm với các lớp tổng hợp. "Sử dụng" duy nhất ở đây là lấy thêm thông tin về lớp để sử dụng nó một cách thích hợp trong mã của bạn.
(Nếu bạn đang làm điều này, có lẽ bạn đang xây dựng một khung gồm một số loại mà các nhà phát triển khác có thể sử dụng.)
Mặt khác, nếu bạn không sử dụng sự phản chiếu, thì không có cách sử dụng thực tế nào của các lớp tổng hợp mà tôi biết.
Java có khả năng tạo các lớp khi chạy. Các lớp này được gọi là Lớp tổng hợp hoặc Proxy động.
Xem http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html để biết thêm thông tin.
Các thư viện nguồn mở khác, chẳng hạn như CGLIB và ASM cũng cho phép bạn tạo các lớp tổng hợp và mạnh hơn các thư viện được cung cấp với JRE.
Các lớp tổng hợp được sử dụng bởi các thư viện AOP (Lập trình hướng đối tượng) như Spring AOP và AspectJ, cũng như các thư viện ORM như Hibernate.
Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
java.lang.reflect.Member#isSynthetic
biết: Trả về true nếu thành viên này được trình biên dịch giới thiệu; trả về sai khác.
java.lang.reflect.Member#isSynthetic
không liên quan đến câu hỏi ban đầu. Thành viên là các lĩnh vực, nhà xây dựng và phương pháp. Câu hỏi ban đầu là về các lớp tổng hợp , không phải thành viên tổng hợp. Trong Java 8, các biểu thức lambda làm phát sinh các lớp tổng hợp - Tôi không chắc chúng có thể phát sinh trường hợp nào khác.
Vâng, tôi đã tìm thấy câu trả lời cho câu hỏi đầu tiên trên google:
Một lớp có thể được đánh dấu là tổng hợp nếu nó được tạo bởi trình biên dịch, nghĩa là nó không xuất hiện trong mã nguồn.
Đây chỉ là một định nghĩa cơ bản nhưng tôi đã tìm thấy nó trong một chủ đề diễn đàn và không có lời giải thích. Vẫn đang tìm kiếm một thứ tốt hơn ...
lớp / phương pháp / trường tổng hợp:
Những điều này rất quan trọng đối với VM. Hãy xem đoạn mã sau:
class MyOuter {
private MyInner inner;
void createInner() {
// The Compiler has to create a synthetic method
// to construct a new MyInner because the constructor
// is private.
// --> synthetic "constructor" method
inner = new MyInner();
// The Compiler has to create a synthetic method
// to doSomething on MyInner object because this
// method is private.
// --> synthetic "doSomething" method
inner.doSomething();
}
private class MyInner {
// the inner class holds a syntetic ref_pointer to
// the outer "parent" class
// --> synthetic field
private MyInner() {
}
private void doSomething() {
}
}
}
Theo cuộc thảo luận này , mặc dù đặc tả ngôn ngữ mô tả một proprty "isSyy tổng hợp" cho các lớp, nhưng điều này bị bỏ qua khá nhiều bởi các triển khai và không được sử dụng cho các proxy động hoặc các lớp ẩn danh. Các trường tổng hợp và hàm tạo được sử dụng để triển khai các lớp lồng nhau (không có khái niệm về các lớp lồng nhau trong mã byte, chỉ có trong mã nguồn).
Tôi nghĩ rằng khái niệm về các lớp tổng hợp đơn giản đã được chứng minh là không hữu ích, tức là không ai quan tâm liệu một lớp có phải là tổng hợp hay không. Với các trường và phương thức, có lẽ nó được sử dụng ở một nơi chính xác: để xác định nội dung hiển thị trong chế độ xem cấu trúc lớp IDE - bạn muốn các phương thức và trường bình thường hiển thị ở đó, nhưng không phải là các phương thức tổng hợp được sử dụng để mô phỏng các lớp lồng nhau. OTOH, bạn muốn các lớp ẩn danh xuất hiện ở đó.
Chúng được tạo bởi JVM vào thời gian chạy khi chúng gọi các thành viên riêng của lớp bên trong cho mục đích gỡ lỗi
Các phương thức, các trường, lớp được tạo bởi JVM trong thời gian chạy cho mục đích thực thi của nó được gọi là Tổng hợp
http://www.javaworld.com/article/2073578/java-s-sy merg-method.html
http://javapapers.com/core-java/java-sy merg- class-method-field /
Ngoài ra Lớp tổng hợp hoặc Proxy động được EasyMock sử dụng để tạo các triển khai giao diện hoặc lớp trừu tượng khi chạy.
Khi trình biên dịch Java biên dịch các cấu trúc nhất định, chẳng hạn như các lớp bên trong, nó tạo ra các cấu trúc tổng hợp ; đây là các lớp, phương thức, trường và các cấu trúc khác không có cấu trúc tương ứng trong mã nguồn.
Sử dụng:
Các cấu trúc tổng hợp cho phép các trình biên dịch Java thực hiện các tính năng ngôn ngữ Java mới mà không cần thay đổi đối với JVM. Tuy nhiên, các cấu trúc tổng hợp có thể khác nhau giữa các triển khai trình biên dịch Java khác nhau, điều đó có nghĩa là các tệp. Class cũng có thể khác nhau giữa các triển khai khác nhau.
tham khảo: docs.oracle.com
Như các câu trả lời khác nhau đã chỉ ra, trình biên dịch được phép tạo ra các cấu trúc khác nhau (bao gồm các lớp) không tương ứng trực tiếp với một cái gì đó trong mã souce. Chúng phải được đánh dấu là tổng hợp:
Một biểu diễn nhị phân cho một lớp hoặc giao diện cũng phải chứa tất cả các điều sau đây:
[...]
11. Một cấu trúc được phát ra bởi trình biên dịch Java phải được đánh dấu là tổng hợp nếu nó không tương ứng với một cấu trúc được khai báo rõ ràng hoặc ẩn trong mã nguồn , trừ khi cấu trúc phát ra là một phương thức khởi tạo lớp (JVMS §2.9).
[...]
Như @Holger đã chỉ ra trong một bình luận cho một câu hỏi khác, các ví dụ có liên quan cho các cấu trúc như vậy là các đối tượng Class đại diện cho các tham chiếu phương thức và lambdas:
System.out.println(((Runnable) System.out::println).getClass().isSynthetic());
System.out.println(((Runnable) () -> {}).getClass().isSynthetic());
Đầu ra:
true
true
Trong khi điều này không được đề cập rõ ràng, nó diễn ra từ 15.27.4. Đánh giá thời gian thực của biểu thức Lambda :
Giá trị của biểu thức lambda là tham chiếu đến một thể hiện của một lớp với các thuộc tính sau: [...]
và từ ngữ gần như giống hệt nhau cho các tham chiếu phương thức ( 15.13.3. Đánh giá thời gian thực của các tham chiếu phương thức ).
Vì lớp này không được đề cập rõ ràng ở bất cứ đâu trong mã nguồn, nó phải được tổng hợp.
Nếu tôi hiểu đúng, một lớp tổng hợp là một lớp được tạo ra một cách nhanh chóng, mà không cần phải đặt cho nó một cái tên rõ ràng. Ví dụ:
//...
Thread myThread = new Thread() {
public void run() {
// do something ...
}
};
myThread.start();
//...
Điều này tạo ra một lớp con tổng hợp của Thread và ghi đè phương thức run () của nó, sau đó khởi tạo nó và khởi động nó.
Outer$1.class
.
Một lớp tổng hợp trong Java là gì?
Một synthetic
lớp là một .class
tệp được tạo bởi Java Compiler và nó không tồn tại trong mã nguồn.
Ví dụ sử dụng synthetic
lớp: Lớp bên trong ẩn danh
synthetic
lớp và nó là một lớp bên trong ẩn danh bên trong java.text.DigitListDigitList$1.java
nhưng nó là một tệp bên trongDigitList.java
Tại sao nó nên được sử dụng?
Đây là một cơ chế bên trong logic trình biên dịch Java để tạo .class
tệp
Làm thế nào tôi có thể sử dụng nó?
Không, nhà phát triển KHÔNG sử dụng nó trực tiếp.
Trình biên dịch Java sử dụng synthetic
để tạo .class
tệp và sau đó JVM đọc .class
tệp để thực thi logic chương trình.
Các cấu trúc tổng hợp là các lớp, phương thức, trường, v.v. không có cấu trúc tương ứng trong mã nguồn. Các cấu trúc tổng hợp cho phép các trình biên dịch Java thực hiện các tính năng ngôn ngữ Java mới mà không cần thay đổi đối với JVM. Tuy nhiên, các cấu trúc tổng hợp có thể khác nhau giữa các triển khai trình biên dịch Java khác nhau, điều đó có nghĩa là các tệp. Class cũng có thể khác nhau giữa các triển khai khác nhau.
Một lớp tổng hợp không xuất hiện trong mã của bạn: nó được tạo bởi trình biên dịch. Ví dụ: Một phương thức cầu được tạo bởi trình biên dịch trong java thường là tổng hợp.
public class Pair<T> {
private T first;
private T second;
public void setSecond(T newValue) {
second = newValue;
}
}
public class DateInterval extends Pair<String> {
public void setSecond(String second) {
System.out.println("OK sub");
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
DateInterval interval = new DateInterval();
Pair pair = interval;
pair.setSecond("string1");
}
}
Sử dụng lệnh javap -verbose DateInterval
, bạn có thể thấy một phương thức cầu nối:
public void setSecond(java.lang.Object);
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Điều này đã được tạo ra bởi trình biên dịch; nó không xuất hiện trong mã của bạn