Извините за плохое название, но я не мог придумать лучшего.
У меня есть класс A и класс B, который является своего рода подклассом A, например:
(Есть ли для него правильное название? Разве «подкласс» не зарезервирован для наследования?)
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
B b = a.new B();
A c = ??? b ??? // get "a" back
}
}
Из B можно получить доступ к каждому свойству A, поэтому оба, a.i и b.i, возвращают 0. Теперь мне интересно, возможно ли каким-то образом получить исходный объект типа A из b, поскольку b содержит все, что содержит a? Очевидно, что простой кастинг не помогает.
Второй:
class A {
void print() {
System.out.println("This is class A.");
}
class B {
void print() {
// <--- How to access print() of class A (like this.A.print() or smth)?
System.out.println("This is class B.");
}
}
}
В качестве альтернативы вы также можете предоставить мне несколько хороших ресурсов по этой теме, так как я был слишком глуп, чтобы найти хороший.
Заранее спасибо. :)
Я считаю, что это дубликат этого вопроса (stackoverflow.com/questions/309737/…)
на самом деле я всегда снова забываю об этом синтаксисе "classname.this" :)
A c = b.this$0; работает? <- Не делай этого !!




[Обновлено: мой ответ подходит для программистов на C#, но я не могу гарантировать, что он применим к Java.]
B - это внутренний класс, а не подкласс A. Кроме того, B не содержит экземпляра A, поэтому ваш код как есть не может вернуть ни один экземпляр A.
Вам необходимо реструктурировать свои классы следующим образом:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
}
Теперь у вашего класса B есть поле «Родитель», которое возвращает своего родителя. Вы можете использовать эти классы следующим образом (это синтаксис C#, потому что я не знаю, есть ли в Java другой синтаксис для создания экземпляров внутренних классов):
public static void Main(String[] args)
{
A parent = new A();
A.B child = new A.B(child);
A backToParent = child.Parent;
}
Конечно, создание класса B таким способом кажется немного забавным: технически вы можете передать любого родителя. Вероятно, было бы лучше переписать ваш класс A с помощью метода, который возвращает B:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
public B getChild()
{
return new B(this);
}
}
public static void Main(String[] args)
{
A parent = new A();
A.B child = A.getChild();
A backToParent = child.Parent;
}
Фактически, он содержит экземпляр A. См. Также: stackoverflow.com/questions/309737/… Тем не менее, спасибо за ваш ответ. То, что вы описали, безусловно, является другим решением.
Кажется, что «внутренний класс» относится к другому понятию, чем в Java (примерно то, что Java назвала бы «вложенным классом»).
Кажется, нет способа получить доступ к внешнему классу извне. Но сделать это можно так:
class A {
int i = 0;
class B {
final A outer = A.this;
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = b.outer // get "a" back
}
}
ClassName.this будет экземпляром внешнего класса, связанного с экземпляром внутреннего класса.
Я думаю, что B b = ... неверно. Вы не можете объявить ссылку типа B без использования A. A.B b = ... Было бы лучше ..
Я бы сделал заявление final A outer = A.this; на всякий случай
Более элегантное решение - предоставить такой метод, как external (), для возврата A. this, чтобы сохранить добавление поля.
Добавление поля не только тратит впустую пространство, но и создает круговую зависимость, которую сборщику мусора гораздо сложнее очистить.
@ Питер Лоури: добавление final A external = A. это к внутреннему классу B в любом случае происходит неявно. Йоханнес просто разъясняет это прямо. Проверить дизассемблированный класс A $ B.class без конечной внешней переменной:> javap A $ B Скомпилирован из максимума класса "A.java". $ B расширяет java.lang.Object {int j; итоговая максима.А это $ 0; максим.A $ B (максим.A); }
@Max, я согласен, что вы получаете это поле $ 0 бесплатно, поэтому вам не нужно явное поле, чтобы делать то, что java делает для вас в любом случае. Не уверен, почему сделать поле явным более ясным, чем использование метода для возврата того же значения.
Спасибо за ваш вклад. Первый пример - это именно то, что я искал (доступ к оригинал) внешнего класса из внутреннего
Вы можете получить к нему доступ с помощью синтаксиса ParentClass.this из внутреннего класса.
например
public class Outter
{
class Inner {
public Outter getOutter()
{
return Outter.this;
}
}
public Inner getInner(){
return new Inner();
}
}
class Runner{
public static void main(String[] args){
Outter out = new Outter();
Outter.Inner inner = out.getInner();
System.out.println(inner.getOutter().toString());
}
}
это, казалось, сработало для меня
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = (A)b.getClass().getDeclaredField("this$0").get(b);
}
}
Я считаю, что правильное имя - внутренний класс.