-
คลาสภายในที่ไม่เปิดเผยตัวตนคอมไพล์เพื่ออะไร?
คลาสภายในที่ไม่เปิดเผยตัวตนถูกรวบรวมเป็น
внешнийКласс$n.class
. แทนที่คลาสชั้นนอก ดังนั้น จึงเป็นชื่อของคลาสเฟรม ซึ่งภายในคลาสภายในที่ไม่ระบุตัวตนถูกอธิบายไว้ โดยที่ n คือตัวเลขตั้งแต่ 1 ถึงจำนวนคลาสที่ไม่ระบุชื่อ -
เป็นไปได้ไหมที่จะสืบทอดคลาสภายใน?
เป็นไปได้ที่จะสืบทอดคลาสภายในจากผู้อื่น
การสืบทอดจากคลาสภายในนั้นซับซ้อนกว่าปกติเล็กน้อย เนื่องจากตัวสร้างของคลาสภายในเชื่อมโยงกับการอ้างอิงถึงวัตถุภายนอกที่อยู่โดยรอบ ปัญหาคือว่าการอ้างอิงอ็อบเจ็กต์ "ซ่อน" ของคลาสภายนอกที่ปิดล้อมจะต้องเริ่มต้นได้ และไม่มีอ็อบเจ็กต์การปิดล้อมเริ่มต้นในคลาสที่ได้รับอีกต่อไป เพื่อระบุวัตถุภายนอกที่ล้อมรอบอย่างชัดเจน จะใช้ไวยากรณ์พิเศษ:
//: innerclasses/InheritInner.java // Наследование от внутреннего класса. class WithInner { class Inner {} } public class InheritInner extends WithInner.Inner { //! InheritInner() {} // He компorруется InheritInner(WithInner wi) { wi.super(); } public static void main(String[] args) { WithInner wi = new WithInner(); InheritInner ii = new InheritInner(wi); } }
ที่นี่คลาส
InheritInner
จะขยายเฉพาะคลาสภายในเท่านั้น ไม่ใช่คลาสภายนอก แต่เมื่อพูดถึงการสร้าง Constructor ค่า Constructor เริ่มต้นที่ให้มานั้นไม่เหมาะสม และคุณไม่สามารถส่งการอ้างอิงไปยังอ็อบเจ็กต์ภายนอกได้ คุณต้องรวมนิพจน์ไว้ในเนื้อความของตัวlinkНаОбъемлющийКласс.super();
สร้าง มันจะให้ลิงค์ที่หายไปและโปรแกรมจะทำการคอมไพล์ -
เป็นไปได้ไหมที่จะสืบทอดคลาสภายในที่ไม่เปิดเผยตัวตน?
โดยการอธิบายคลาสที่ไม่ระบุชื่อ เรากำลังสืบทอดมาจากบางคลาสหรือใช้งานอินเทอร์เฟซบางส่วนอยู่แล้ว คำว่าขยายหรือนำไปใช้ไม่สามารถนำไปใช้กับคลาสที่ไม่ระบุชื่อได้โดยตรง แต่ไม่มีใครรบกวนคุณในการเตรียมตัวล่วงหน้าและขยายอินเทอร์เฟซที่จำเป็น ซึ่งเราจะนำไปใช้โดยใช้คลาสที่ไม่ระบุชื่อ ตัวอย่างในโค้ดด้านล่าง
import java.awt.event.WindowListener; public class TestExtendAnonym { private interface MyInterface extends Runnable, WindowListener { } Runnable r = new MyInterface() { ... //Пример того How реализовать 2 и более интерфейса в анонимном классе }; }
คุณไม่สามารถสืบทอดจากคลาสที่ไม่ระบุชื่อได้
-
เป็นไปได้ไหมที่จะแทนที่คลาสภายใน?
การเอาชนะคลาสภายในราวกับว่ามันเป็นวิธีการอื่นของคลาสภายนอกจริง ๆ แล้วไม่มีผล:
//: innerclasses/BigEgg.java // Внутренний класс нельзя переопределить // подобно обычному методу, import static net.mindview.util.Print.*; class Egg { private Yolk y; protected class Yolk { public Yolk() { print("Egg.Yolk()"); } } public Egg() { print("New Egg()"); y = new Yolk(); } } public class BigEgg extends Egg { public class Yolk { public Yolk() { print("BigEgg.Yolk()"); } } public static void main(String[] args) { new BigEgg(); } }
บทสรุป:
New Egg() Egg.Yolk()
ตัวสร้างเริ่มต้นจะถูกสังเคราะห์โดยอัตโนมัติโดยคอมไพเลอร์และเรียกตัวสร้างเริ่มต้นจากคลาสพื้นฐาน คุณอาจคิดว่าเมื่อสร้างอ็อบเจ็กต์
BigEgg
ควรใช้คลาส "ที่ถูกแทนที่"Yolk
แต่ไม่ได้เป็นเช่นนั้น ดังที่เห็นได้จากผลลัพธ์ของโปรแกรมตัวอย่างนี้แสดงให้เห็นเพียงว่าเมื่อคุณสืบทอดมาจากคลาสภายนอก จะไม่มีอะไรพิเศษเกิดขึ้นกับคลาสภายใน คลาสภายในทั้งสองนั้นเป็นเอนทิตีที่แยกจากกันโดยสิ้นเชิง โดยมีเนมสเปซที่เป็นอิสระ กล่าวอีกนัยหนึ่งมันเป็นไปไม่ได้
-
ข้อจำกัดของคลาสท้องถิ่นมีอะไรบ้าง?
ก่อนอื่น เรามาจำไว้ว่าชั้นเรียนในท้องถิ่นคืออะไร นี่คือคลาสที่อธิบายไว้ในบล็อกของโค้ด กล่าวคือ ในรูปแบบง่ายๆ - ระหว่างเครื่องหมายคำ
{}
พูด ส่วนใหญ่คำพูดเหล่านี้มักเป็นส่วนเนื้อหาของวิธีการ แต่ยังสามารถเป็นเพียงบล็อก บล็อกแบบคงที่ เนื้อความif
ของ -s ลูป ฯลฯคลาสท้องถิ่นนั้นมีคุณสมบัติของคลาสภายใน แต่มีคุณสมบัติที่โดดเด่น กล่าวคือ:
- он имеет доступ только к финальным полям и аргументам обрамляющего метода, а также ко всем полям обрамляющего класса, в том числе приватным и статическим;
- локальный класс виден и может создаваться только в блоке, в котором описан;
- у локального класса не ставится модификатор доступа;
- не может иметь статических полей, методов, классов (за исключением финальных);
- локальный класс, объявленный в статическом блоке может обращаться только к статическим полям внешнего класса.
Но! Начиная с Java8 мы можем обращаться в локальных классах к не финальным локальным переменным, если они не были изменены до момента инициализации класса. Также теперь стало возможным обращение к не финальным параметрам метода.
-
Может ли анонимный внутренний класс содержать статические методы?
Нет. У Анонимных внутренних классов, How и у внутренних классов не может быть статических полей, методов. (вспомним, что анонимные классы компorруются в обычные внутренние, а те, в свою очередь, связаны с an objectом обрамляющего класса)
-
Можно ли создать an object внутреннего класса, если у внешнего класса только
private
конструктор?Имея подобный code:
public class PrivateConst { private PrivateConst() {} public class InnerClass{ public void f(){ System.out.println("hello"); } } }
Напрямую, в другом классе (вне обрамляющего), конечно, создать an object
InnerClass
следующим способом не получится:PrivateConst.InnerClass priv = new PrivateConst().new InnerClass();
Но! What если у нас есть метод, возвращающий экземпляр
PrivateConst:public class PrivateConst { private static PrivateConst instance; private PrivateConst() {} public static PrivateConst getInstance(){ instance = new PrivateConst(); return instance; } public class InnerClass{} }
В этом случае приватный конструктор нам не помеха для создания an object
InnerClass
. Так же мы без проблем сможем создавать его в методах и в других внутренних классах, принадлежащихPrivateConst
. Ответ — можно, если Howим-либо способом нам удастся получить an object обрамляющего класса. -
Можно ли объявлять внутренние классы
private
?Да, можно.
PS Обоснования так и не нашел, но на философии java встречались подобные примеры. Плюс IDE не ругается. Буду признателен за обоснование, но предположу, что в этом плане внутренний класс ничем не отличается от обычного класса.
-
Можно ли объявлять анонимные внутренние классы
private
?Аналогично (в плане не нашел обоснования). Можно объявить
private
переменную от типа которой наследуется наш анонимный класс. -
Сколько у класса максимально может быть внутренних классов?
Сколь угодно много. Ограничение особенности ОС и длинны имени файлов.
GO TO FULL VERSION