Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Обращение из внутреннего класса во внешний


Автор: ShurikA 26.1.2007, 23:29
Есть такое строение классов:
Код

public class A{
  public static class B{
  .
  .
  .
  }
}


из В обратиться в А?

во всяком слачае вот такой способ:
Код

A.this.someMethod();

Автор: Anklav 27.1.2007, 00:21
объяви класс B не статическим:
Код

public class A {
  public class B {
  }
}

статическому внутреннему классу ничего не известно о внешнем

Автор: powerOn 27.1.2007, 00:23
Из статического внутреннего класса нельзя обращаться к не статическим полям и методам внешнего класса. 
Чтобы из класса  B обратиться к не статическому методу или полю класса А нужно чтобы класс А был не статическим.
(А чтобы создать экземпляр внутреннего не статического класса необходимо прежде создать объект внешнего класса:

Код

public class Main
{
    public class Test 
    {
        public Test()
        {
            Main.this.test();
        }
    }

    public Main()
    {
    }
    
    public void test()
    {
        System.out.println("Test!");
    }

    public static void main(String[] args)
    {
        new Main().new Test();
    }
}
)

Автор: ShurikA 27.1.2007, 16:18
ОК, допустим я переделываю public static class B в public class B то с этим классом всё нормално.
Но как только я пытаюсь зодать обьект класса В, вот таким образом:
Код

dTmpl.AddImgTmpl(new ImgTmpl(rect));

когда ImgTmpl это В

то уже при работе проги (компиляцию она проходит хормално), вылетает ошибка:

Код

C:\Private\Java\JavaDev\ApisServer\src\apisserver\DBMgr\DBMgr.java:98: an enclosing instance that contains dataclasses.DataClasses.DesignTemplate.ImgTmpl is required


и как с этом бороться?

Автор: LSD 27.1.2007, 16:21
Цитата(ShurikA @  27.1.2007,  16:18 Найти цитируемый пост)
то уже при работе проги (компиляцию она проходит хормално), вылетает ошибка:

Как это при работе? smile  Ты запускаешь DBMgr.java (исходник)? smile 

Автор: ShurikA 27.1.2007, 16:39
Цитата(LSD @  27.1.2007,  15:21 Найти цитируемый пост)
Как это при работе?

Извиняюсь моя ошибка, при компиляции.

Добавлено @ 16:41 
вот этот кусок кода:

Код

import dataclasses.DataClasses.DesignTemplate;
import dataclasses.DataClasses.DesignTemplate.ImgTmpl;
import dataclasses.DataClasses.DesignTemplate.TextTmpl;
.
.
.
 public DesignTemplate BuildTemplate(int id, StringBuffer str) throws Exception {
        DesignTemplate dTmpl = new DesignTemplate(id);
        Rectangle rect = new Rectangle();
        String PICTURE = "picture";
        String TEXT = "text";
        String type;
        Statement statment = null;
        String sql = "SELECT apis_bg.id AS bg_id, apis_bg.`bgfile`, "+
                "apis_frames.`id` AS t_id, `x` , `y` , "+
                "`width`, `height` , apis_frames.`type` "+
                "FROM `apis_bg` LEFT JOIN `apis_frames` ON(apis_bg.id = apis_frames.bgid) "+
                "WHERE apis_bg.id =" + id;
        ResultSet rs = null;
        statment = this.GetConnection().createStatement();
        rs = statment.executeQuery(sql);
        if (rs.next()) {
            dTmpl.SetBgImagePath("http://photorakurs.net.ru/forum/sources/gallery/images/"+rs.getString("bgfile"));
            if(rs.getString("t_id") != null){
                rect.setBounds(rs.getInt("x"), rs.getInt("y"), rs.getInt("width"),
                        rs.getInt("height"));
                type = rs.getString("type");
                if (type.equals(PICTURE)) {
                    dTmpl.AddImgTmpl(new ImgTmpl(rect));
                } else if (type.equals(TEXT)) {
                    dTmpl.AddTextTmpl(new TextTmpl(rect));
                }
            }
        }
        
        while (rs.next()) {
            rect.setBounds(rs.getInt("x"), rs.getInt("y"), rs.getInt("width"), rs.getInt("height"));
            type = rs.getString("type");
            if (type.equals(PICTURE)) {
                dTmpl.AddImgTmpl(new ImgTmpl(rect));
            } else if (type.equals(TEXT)) {
                dTmpl.AddTextTmpl(new TextTmpl(rect));
            }
        }
        
        if (rs != null) {
            rs.close();
        }
        
        if (statment != null) {
            statment.close();
        }
        
        return dTmpl;
    }

Автор: ShurikA 27.1.2007, 16:58
Проблемма решилась, но правда каким то странным образом:
Создавать обьект нужно в таком слачае вот так:
Код

dTmpl.new ImgTmpl(rect);

когда dTmpl это типа класс А...

Работает, но я не понимаю почему именно так...
Кто то может пояснить, я явно тут чего то пропустил, в понимании.


P.S. 
Мне сразу эта тема кое что напомнила:
"У теоретиков ничего не работает, но они знают почему;
у практиков всё работает, но не могу понять почему...
У нас обычно ничего не работает, и мы не можем обьяснить почему!"   smile  

Автор: LSD 27.1.2007, 17:10
Цитата(ShurikA @  27.1.2007,  16:58 Найти цитируемый пост)
Работает, но я не понимаю почему именно так...
Кто то может пояснить, я явно тут чего то пропустил, в понимании.

В не статическом внутреннем классе есть ссылка на объект внешнего класса (enclosing instance). Эта ссылка всегда не null, если объект внутреннего класса создается в не статическом методе, то эта ссылка автоматом инициализируется указателем на объект в методе которого был вызван конструктор.
А вот если создание происходит в статическом методе, то ссылку на объект базового класса надо передать явно, что и делает такой код:
Код
dTmpl.new ImgTmpl(rect);


P.S. Если dTmpl будет null то будет сгенерированно исключение NullPointerException.

Автор: ShurikA 27.1.2007, 17:13
Да, но в данный момент мои внутрение классы не статические.

Добавлено @ 17:15 
и ещё одно, что это озночает:
http://www.thecatalog.biz/servlet/apisserver.ApisServer?act=get_template&tId=1

при этом компиляцию проходит без проблемм.

Автор: powerOn 27.1.2007, 17:17
Цитата(ShurikA @  27.1.2007,  16:58 Найти цитируемый пост)
Проблемма решилась, но правда каким то странным образом:
Создавать обьект нужно в таком слачае вот так:


Ну а мой пост выше ты читал? 

К статическим полям/методам любого класса можно обращаться по их именам (если конечно область видимости позволяет). Если поле - то по имени поля, если метод - то по имени метода, если внутренний статический класс, то создать его экземпляр можно используя конструкцию:
Код

new OutterClassName.InnerClassName(param...);


если же внутренний класс не является статическим, а создать его хочется, то необходимо сначала создать экземпляр внешнего класса, а потом только экземпляр внутреннего:
Код

new OutterClassName(param...).new InnerClassName(param...);


Из внутреннего статического класса нельзя получить доступ к нестатическим полям и методам внешнего класса. Из внутреннего нестатического класса можно, используя конструкцию:

Код

OutterClassName.this.outterNotStaticMetodt();

Автор: LSD 27.1.2007, 17:17
Значит ты или вызываешь конструктор внутреннего класса из статического метода, или из метода объекта который не является enclosing class для данного внутреннего класса.

Автор: ShurikA 27.1.2007, 17:17
Извините, но у меня уже руки опустились...
Проблеммы просто одна за другой. smile

Добавлено @ 17:23 
Цитата(powerOn @  27.1.2007,  16:17 Найти цитируемый пост)
если же внутренний класс не является статическим, а создать его хочется, то необходимо сначала создать экземпляр внешнего класса, а потом только экземпляр внутреннего:

код Java
1:

new OutterClassName(param...).new InnerClassName(param...);



правильно ли вместо new OutterClassName(param...) воспользоваться уже созданным обьектом этого класса?

Автор: powerOn 27.1.2007, 17:34
Цитата(ShurikA @  27.1.2007,  17:17 Найти цитируемый пост)
правильно ли вместо new OutterClassName(param...) воспользоваться уже созданным обьектом этого класса? 

Да, можно воспользоваться. 
Дополнительно, следует учесть, что один экземпляр внешнего класса может иметь много экземпляров внутреннего класса. А экземпляры внутреннего класса могут менять поля своего внешнего класса.

Автор: ShurikA 27.1.2007, 17:37
ну вот притакой конфигурации вилетает ошибка показанная по ссылке...

Автор: ShurikA 27.1.2007, 22:51
Код

java.lang.NoSuchMethodError: dataclasses.DataClasses.DesignTemplate$ImgTmpl.<init>(Ljava/awt/Rectangle;)V
    apisserver.DBMgr.DBMgr.BuildTemplate(DBMgr.java:98)


что бы это могло означать, при том что цтрока 98 это:
Код

dTmpl.AddImgTmpl(dTmpl.new ImgTmpl(rect));

Автор: ShurikA 28.1.2007, 01:58
Неужели ни кто незнает что это за хрень?

Цитата(ShurikA @  27.1.2007,  21:51 Найти цитируемый пост)
java.lang.NoSuchMethodError: dataclasses.DataClasses.DesignTemplate$ImgTmpl.<init>(Ljava/awt/Rectangle;)V
    apisserver.DBMgr.DBMgr.BuildTemplate(DBMgr.java:98)


Автор: powerOn 28.1.2007, 02:06
Цитата(ShurikA @  28.1.2007,  01:58 Найти цитируемый пост)
java.lang.NoSuchMethodError

Это хрень обычно вылетает когда с помощью рефлекшена пытаются дёрнуть метод который в классе отсутствует. Нужно под отладчиком смотреть что там происходит, так непонятно из-за чего....  smile 

Автор: ShurikA 28.1.2007, 02:17
Цитата(powerOn @  28.1.2007,  01:06 Найти цитируемый пост)
рефлекшена

 smile

Добавлено @ 02:19 
У меня есть небольшая проблемма с отладчиком.
Это сервлет, и он на серваке...
Мне просто MySQL нужен.

Добавлено @ 02:21 
Кроме того что за метод .<init> у меня его нету и я его и не пытаюсь вызвать...

Автор: powerOn 28.1.2007, 02:39
Цитата(ShurikA @  28.1.2007,  02:17 Найти цитируемый пост)
.<init>

Этот метод выполняет инициализацию полей класса. Он компилятором создаётся.

Рефлекшион - http://java.sun.com/docs/books/tutorial/reflect/index.html.  smile 

Автор: ShurikA 28.1.2007, 02:44
Цитата(powerOn @  28.1.2007,  01:39 Найти цитируемый пост)
Этот метод выполняет инициализацию полей класса. Он компилятором создаётся.

И каким таким образом его может не быть?

Добавлено @ 02:46 
и что за странность:
Код

Ljava/awt/Rectangle;

Автор: powerOn 28.1.2007, 12:49
Цитата(ShurikA @  28.1.2007,  02:44 Найти цитируемый пост)

И каким таким образом его может не быть?

Этот метод всегда есть. Тут в не его отсутствии ошибка. Ошибка внутри него... вероятно  smile 

Автор: ShurikA 28.1.2007, 13:32
Цитата(powerOn @  28.1.2007,  11:49 Найти цитируемый пост)
Ошибка внутри него... вероятно  

Как можно помять как он формируется?

Автор: LSD 29.1.2007, 11:05
Цитата(powerOn @  28.1.2007,  02:39 Найти цитируемый пост)
Этот метод выполняет инициализацию полей класса. Он компилятором создаётся.

Конструкторы тоже так обзываются.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)