คลาสสังเคราะห์ใน Java คืออะไร ทำไมจึงควรใช้ ฉันจะใช้มันได้อย่างไร
คลาสสังเคราะห์ใน Java คืออะไร ทำไมจึงควรใช้ ฉันจะใช้มันได้อย่างไร
คำตอบ:
ตัวอย่างเช่นเมื่อคุณมีคำสั่ง switch, java จะสร้างตัวแปรที่ขึ้นต้นด้วย $ หากคุณต้องการดูตัวอย่างของสิ่งนี้ให้มองเข้าไปในการสะท้อน java ของคลาสที่มีคำสั่ง switch อยู่ คุณจะเห็นตัวแปรเหล่านี้เมื่อคุณมีคำสั่งสวิตช์อย่างน้อยหนึ่งคำสั่งที่ใดก็ได้ในชั้นเรียน
เพื่อตอบคำถามของคุณฉันไม่เชื่อว่าคุณสามารถเข้าถึง (นอกเหนือจากการสะท้อน) ชั้นสังเคราะห์
หากคุณกำลังวิเคราะห์คลาสที่คุณไม่ทราบอะไรเกี่ยวกับ (ผ่านการสะท้อนกลับ) และจำเป็นต้องรู้สิ่งที่เฉพาะเจาะจงและระดับต่ำเกี่ยวกับคลาสนั้นคุณอาจสิ้นสุดด้วยการใช้ Java reflection method ที่เกี่ยวข้องกับคลาสสังเคราะห์ "ใช้" เท่านั้นที่นี่รับข้อมูลเพิ่มเติมเกี่ยวกับชั้นเรียนเพื่อใช้ในรหัสของคุณอย่างเหมาะสม
(ถ้าคุณทำเช่นนี้คุณอาจสร้างกรอบบางประเภทที่ผู้พัฒนารายอื่นสามารถใช้)
มิฉะนั้นถ้าคุณไม่ได้ใช้การสะท้อนก็ไม่มีประโยชน์ในการใช้คลาสสังเคราะห์ที่ฉันรู้จัก
Java มีความสามารถในการสร้างคลาสที่รันไทม์ คลาสเหล่านี้เรียกว่า Synthetic Classes หรือ Dynamic Proxies
ดูhttp://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.htmlสำหรับข้อมูลเพิ่มเติม
ไลบรารีโอเพ่นซอร์สอื่น ๆ เช่นCGLIBและASMยังอนุญาตให้คุณสร้างคลาสสังเคราะห์และมีประสิทธิภาพมากกว่าไลบรารีที่จัดเตรียมไว้พร้อมกับ JRE
คลาสสังเคราะห์ถูกใช้โดยไลบรารี AOP (Aspect Oriented Programming) เช่น Spring AOP และ AspectJ รวมถึงไลบรารี ORM เช่น Hibernate
Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
java.lang.reflect.Member#isSynthetic
พูดว่า: คืนค่าจริงถ้าสมาชิกนี้ได้รับการแนะนำโดยคอมไพเลอร์; ผลตอบแทนที่ผิดพลาดเป็นอย่างอื่น
java.lang.reflect.Member#isSynthetic
นั้นไม่เกี่ยวข้องกับคำถามเดิม สมาชิกคือเขตข้อมูลผู้สร้างและวิธีการ คำถามเดิมเป็นเรื่องเกี่ยวกับคลาสสังเคราะห์ไม่ใช่สมาชิกสังเคราะห์ ใน Java 8 นิพจน์แลมบ์ดาทำให้เกิดคลาสสังเคราะห์ขึ้น - ฉันไม่แน่ใจว่าสถานการณ์อื่น ๆ ที่พวกเขาสามารถเกิดขึ้นได้
ฉันพบคำตอบสำหรับคำถามแรกใน google:
ชั้นอาจถูกทำเครื่องหมายเป็นสังเคราะห์ถ้ามันถูกสร้างขึ้นโดยคอมไพเลอร์นั่นคือมันจะไม่ปรากฏในรหัสที่มา
นี่เป็นเพียงคำจำกัดความพื้นฐาน แต่ฉันพบในกระทู้ในฟอรัมและไม่มีคำอธิบาย ยังคงมองหาสิ่งที่ดีกว่า ...
คลาสสังเคราะห์ / วิธี / ฟิลด์:
สิ่งเหล่านี้มีความสำคัญสำหรับ VM ดูตัวอย่างโค้ดต่อไปนี้:
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() {
}
}
}
จากการอภิปรายนี้แม้ว่าข้อกำหนดทางภาษาจะอธิบายถึง "isSynthetic" สำหรับคลาส แต่ก็ไม่สนใจการใช้งานและไม่ได้ใช้สำหรับพร็อกซีแบบไดนามิกหรือคลาสที่ไม่ระบุชื่อ ฟิลด์สังเคราะห์และคอนสตรัคเตอร์ใช้เพื่อสร้างคลาสที่ซ้อนกัน (ไม่มีแนวคิดของคลาสที่ซ้อนในโค้ดไบต์เฉพาะในซอร์สโค้ด)
ฉันคิดว่าแนวคิดของคลาสสังเคราะห์ได้พิสูจน์แล้วว่าไม่มีประโยชน์นั่นคือไม่มีใครใส่ใจว่าคลาสนั้นเป็นสังเคราะห์หรือไม่ ด้วยเขตข้อมูลและวิธีการก็อาจใช้ในที่เดียว: เพื่อกำหนดสิ่งที่จะแสดงในมุมมองโครงสร้างคลาส IDE - คุณต้องการวิธีการปกติและสาขาที่จะปรากฏขึ้นที่นั่น แต่ไม่ใช่คนสังเคราะห์ที่ใช้ในการจำลองชั้นเรียนที่ซ้อนกัน OTOH คุณต้องการให้คลาสนิรนามปรากฏขึ้นที่นั่น
พวกเขาถูกสร้างขึ้นโดย JVM ในเวลาทำงานเมื่อพวกเขาเรียกสมาชิกส่วนตัวของชั้นในสำหรับวัตถุประสงค์ในการแก้จุดบกพร่อง
เมธอดฟิลด์คลาสที่สร้างโดย JVM ระหว่างเวลารันเพื่อวัตถุประสงค์ในการเรียกใช้งานเรียกว่า Synthetic
http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html
http://javapapers.com/core-java/java-synthetic-class-method-field/
นอกจากนี้ Synthetic Classes หรือ Dynamic Proxies จะถูกใช้โดย EasyMock เพื่อสร้างการใช้งานของอินเตอร์เฟสหรือคลาสนามธรรมที่รันไทม์
เมื่อคอมไพเลอร์ Java รวบรวมโครงสร้างบางอย่างเช่นการเรียนภายในจะสร้างโครงสร้างสังเคราะห์ ; นี่คือคลาสวิธีการฟิลด์และโครงสร้างอื่น ๆ ที่ไม่มีโครงสร้างที่สอดคล้องกันในซอร์สโค้ด
ใช้:
โครงสร้างสังเคราะห์เปิดใช้งานคอมไพเลอร์ Java เพื่อใช้คุณลักษณะภาษา Java ใหม่โดยไม่เปลี่ยนแปลง JVM อย่างไรก็ตามโครงสร้างสังเคราะห์อาจแตกต่างกันระหว่างการใช้งานคอมไพเลอร์ Java ที่แตกต่างกันซึ่งหมายความว่าไฟล์. class สามารถแตกต่างกันระหว่างการใช้งานที่แตกต่างกันเช่นกัน
การอ้างอิง: docs.oracle.com
ตามคำตอบที่หลากหลายได้ชี้ให้เห็นแล้วคอมไพเลอร์ได้รับอนุญาตให้สร้างโครงสร้างต่าง ๆ (รวมถึงคลาส) ที่ไม่ตรงกับบางสิ่งบางอย่างในรหัส souce สิ่งเหล่านี้จะต้องมีการทำเครื่องหมายเป็นสังเคราะห์:
การเป็นตัวแทนไบนารีสำหรับคลาสหรือส่วนต่อประสานต้องประกอบด้วยสิ่งต่อไปนี้ทั้งหมด:
[... ]
11. โครงสร้างที่ปล่อยออกมาโดยคอมไพเลอร์ Java จะต้องทำเครื่องหมายเป็นสังเคราะห์ถ้าไม่สอดคล้องกับโครงสร้างที่ประกาศอย่างชัดเจนหรือโดยปริยายในซอร์สโค้ด ยกเว้นว่าการสร้างที่ปล่อยออกมาเป็นวิธีการเริ่มต้นเรียน (JVMS §2.9)
[ ... ]
ตามที่ระบุโดย@Holgerในความคิดเห็นคำถามอื่นตัวอย่างที่เกี่ยวข้องสำหรับการสร้างดังกล่าวเป็นวัตถุคลาสที่แสดงวิธีการอ้างอิงและ lambdas:
System.out.println(((Runnable) System.out::println).getClass().isSynthetic());
System.out.println(((Runnable) () -> {}).getClass().isSynthetic());
เอาท์พุท:
true
true
แม้ว่าสิ่งนี้จะไม่ได้กล่าวถึงอย่างชัดเจน แต่ก็มีตั้งแต่ 15.27.4 การประเมินเวลาทำการของแลมบ์ดานิพจน์ :
ค่าของนิพจน์แลมบ์ดาเป็นการอ้างอิงถึงอินสแตนซ์ของคลาสที่มีคุณสมบัติต่อไปนี้: [... ]
และถ้อยคำที่เกือบเหมือนกันสำหรับการอ้างอิงวิธีการ ( 15.13.3. การประเมินเวลาทำงานของการอ้างอิงวิธีการ )
เนื่องจากคลาสนี้ไม่ได้กล่าวถึงอย่างชัดเจนทุกที่ในซอร์สโค้ดจึงต้องมีการสังเคราะห์
ถ้าฉันทำให้ถูกต้องคลาสสังเคราะห์เป็นคลาสที่สร้างขึ้นโดยไม่ต้องตั้งชื่อให้ชัดเจน ตัวอย่างเช่น:
//...
Thread myThread = new Thread() {
public void run() {
// do something ...
}
};
myThread.start();
//...
สิ่งนี้สร้างคลาสย่อยสังเคราะห์ของ Thread และแทนที่เมธอด run () ของมันจากนั้นเริ่มต้นอินสแตนซ์และเริ่มต้นมัน
Outer$1.class
พวกเขาสร้างการเรียนไม่ใช่สังเคราะห์แยกต่างหากที่มีชื่อของประเภท
คลาสสังเคราะห์ไม่ปรากฏในรหัสของคุณ: ประกอบด้วยคอมไพเลอร์ เช่นวิธีการบริดจ์ที่สร้างขึ้นโดยคอมไพเลอร์ใน Java มักจะสังเคราะห์
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");
}
}
ใช้คำสั่งjavap -verbose DateInterval
คุณสามารถดูวิธีการสะพาน:
public void setSecond(java.lang.Object);
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
สิ่งนี้ถูกสร้างขึ้นโดยคอมไพเลอร์; มันไม่ปรากฏในรหัสของคุณ
คลาสสังเคราะห์ใน Java คืออะไร
synthetic
ระดับเป็น.class
ไฟล์ที่สร้างโดยJava คอมไพเลอร์และมันไม่ได้อยู่ในรหัสที่มา
ตัวอย่างการใช้synthetic
คลาส: คลาสภายในที่ไม่ระบุชื่อ
synthetic
คลาสและเป็นคลาสภายในแบบไม่ระบุชื่อในjava.text.DigitListDigitList$1.java
แต่มันเป็นไฟล์ภายในDigitList.java
ทำไมจึงควรใช้
มันเป็นกลไกภายในตรรกะของคอมไพเลอร์ Java เพื่อสร้าง.class
ไฟล์
ฉันจะใช้มันได้อย่างไร
ไม่นักพัฒนาไม่ได้ใช้งานโดยตรง
คอมไพเลอร์ Java ใช้synthetic
เพื่อสร้าง.class
ไฟล์จากนั้น JVM จะอ่าน.class
ไฟล์เพื่อดำเนินการตรรกะของโปรแกรม
โครงสร้างแบบสังเคราะห์คือคลาส, วิธีการ, ฟิลด์อื่น ๆ ที่ไม่มีโครงสร้างที่สอดคล้องกันในซอร์สโค้ด โครงสร้างแบบซินเทติกเปิดใช้งานคอมไพเลอร์ Java เพื่อใช้งานคุณสมบัติภาษา Java ใหม่โดยไม่มีการเปลี่ยนแปลงกับ JVM อย่างไรก็ตามโครงสร้างสังเคราะห์อาจแตกต่างกันระหว่างการใช้งานคอมไพเลอร์ Java ที่แตกต่างกันซึ่งหมายความว่าไฟล์. class สามารถแตกต่างกันระหว่างการใช้งานที่แตกต่างกันเช่นกัน