|
Java форум JavaTalks форум программистов
|
|
|
|
| Предыдущая тема :: Следующая тема |
| Автор |
Сообщение |
initmax : 165 Новичок Откуда: Moon
|
Июн 21, 2011 9:21 |
|
|
Возникли рассуждения по поводу Inner classes и
Static inner classes в чём так сказать существенные различия. Благодаря Inner classes осуществляется агрегирование, что позволяет повысить инкапсуляцию за счёт скрытия реализации, НО почему просто не использовать методы а создавать вложенную сущность?
касательно же Static inner classes исходя из философии Java данные экзепляры создаются в момент компиляции и вызывать методы этих классов можно не создавая экзепляра объекта т.е. NameClass.NameMethod. это и вся разница, или есть какие-то ещё аспекты? _________________ Пишу дипломы, курсовые, лабары. Консультирую по скайпу до полного прозрения. Обращайтесь в личку. |
|
|
|
 |
Skipy : 4801 Я тут живу! Откуда: Москва, Россия
|
Июн 21, 2011 12:42 |
|
|
| initmax писал(а): |
НО почему просто не использовать методы а создавать вложенную сущность?
|
Сколько вариантов ActionListener-а Вы можете реализовать методами в текущем классе? А кнопок у Вас пять штук, и каждой нужен свой. _________________ С уважением,
Евгений aka Skipy
www.skipy.ru
P.S. Я НЕ решаю задачи ЗА других! |
|
|
|
 |
initmax : 165 Новичок Откуда: Moon
|
Июн 21, 2011 15:20 |
|
|
| Skipy писал(а): |
| initmax писал(а): |
НО почему просто не использовать методы а создавать вложенную сущность?
|
Сколько вариантов ActionListener-а Вы можете реализовать методами в текущем классе? А кнопок у Вас пять штук, и каждой нужен свой. |
Признаться откровенно, понял Вас весьма смутно и как минимум в двух вариантах Вы бы могли более подробно изложить свои мысли касательно данного вопроса? _________________ Пишу дипломы, курсовые, лабары. Консультирую по скайпу до полного прозрения. Обращайтесь в личку. |
|
|
|
 |
Skipy : 4801 Я тут живу! Откуда: Москва, Россия
|
Июн 21, 2011 17:20 |
|
|
У Вас есть класс. В нем нужно создать реализацию ActionListener. Варианты - либо в самом классе реализовать actionPerformed, либо сделать внутренний класс. Вопрос: сколько вариантов реализации ActionListener-а возможно в первом случае и сколько во втором? _________________ С уважением,
Евгений aka Skipy
www.skipy.ru
P.S. Я НЕ решаю задачи ЗА других! |
|
|
|
 |
initmax : 165 Новичок Откуда: Moon
|
Июн 21, 2011 17:23 |
|
|
| Skipy писал(а): |
| У Вас есть класс. В нем нужно создать реализацию ActionListener. Варианты - либо в самом классе реализовать actionPerformed, либо сделать внутренний класс. Вопрос: сколько вариантов реализации ActionListener-а возможно в первом случае и сколько во втором? |
создать реализацию ActionListener
Если я Вас верно понял требуется создать множество методов обработки нажатия кнопок, в чём разница где их создавать во вложеном классе или просто в классе. Вот в чём у меня недопонимание. _________________ Пишу дипломы, курсовые, лабары. Консультирую по скайпу до полного прозрения. Обращайтесь в личку. |
|
|
|
 |
oleg_v_ : 90 Новичок Откуда: Санкт-Петербург, Россия
|
Июн 21, 2011 17:35 |
|
|
Вот для примера два варианта реализации ActionListener для двух кнопок:
без Inner classes:
| Код: |
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TwoButtons implements ActionListener {
JFrame frame;
JLabel label;
JButton colorButton;
public static void main (String[] args) {
TwoButtons gui = new TwoButtons();
gui.go();
}
public void go() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton labelButton = new JButton("Change Label");
labelButton.addActionListener(this);
colorButton = new JButton("Change Circle");
colorButton.addActionListener(this);
label = new JLabel("I'm a label");
MyDrawPanel drawPanel = new MyDrawPanel();
frame.getContentPane().add(BorderLayout.SOUTH, colorButton);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.getContentPane().add(BorderLayout.EAST, labelButton);
frame.getContentPane().add(BorderLayout.WEST, label);
frame.setSize(420,300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event){
if (event.getSource() == colorButton){
frame.repaint();
}else{
label.setText("That hurt!");
}
}
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
g.fillRect(0,0,this.getWidth(), this.getHeight());
// make random colors to fill with
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color randomColor = new Color(red, green, blue);
g.setColor(randomColor);
g.fillOval(70,70,100,100);
}
} |
с Inner classes:
| Код: |
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TwoButtons {
JFrame frame;
JLabel label;
public static void main (String[] args) {
TwoButtons gui = new TwoButtons();
gui.go();
}
public void go() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton labelButton = new JButton("Change Label");
labelButton.addActionListener(new LabelButtonListener());
JButton colorButton = new JButton("Change Circle");
colorButton.addActionListener(new ColorButtonListener());
label = new JLabel("I'm a label");
MyDrawPanel drawPanel = new MyDrawPanel();
frame.getContentPane().add(BorderLayout.SOUTH, colorButton);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.getContentPane().add(BorderLayout.EAST, labelButton);
frame.getContentPane().add(BorderLayout.WEST, label);
frame.setSize(420,300);
frame.setVisible(true);
}
class LabelButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
label.setText("Ouch!");
}
} // inner class
class ColorButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
} // inner class
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
g.fillRect(0,0,this.getWidth(), this.getHeight());
// make random colors to fill with
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color randomColor = new Color(red, green, blue);
g.setColor(randomColor);
g.fillOval(70,70,100,100);
}
} |
Можно делать как в первом варианте и иногда может это оправдано, а если кнопок будет больше чем две? А если Вам нужно будет изменить обработку события от какого-нибудь из кнопок. |
|
|
|
 |
Skipy : 4801 Я тут живу! Откуда: Москва, Россия
|
Июн 21, 2011 18:11 |
|
|
| initmax писал(а): |
| Если я Вас верно понял требуется создать множество методов обработки нажатия кнопок, в чём разница где их создавать во вложеном классе или просто в классе. Вот в чём у меня недопонимание. |
Повторяю вопрос - сколько таких методов Вы можете сделать в одном классе? Напоминаю - у них у всех одинаковая сигнатура должна быть! Сколько методов с одинаковой сигнатурой можно сделать в классе? _________________ С уважением,
Евгений aka Skipy
www.skipy.ru
P.S. Я НЕ решаю задачи ЗА других! |
|
|
|
 |
initmax : 165 Новичок Откуда: Moon
|
Июн 21, 2011 19:15 |
|
|
| Skipy писал(а): |
| initmax писал(а): |
| Если я Вас верно понял требуется создать множество методов обработки нажатия кнопок, в чём разница где их создавать во вложеном классе или просто в классе. Вот в чём у меня недопонимание. |
Повторяю вопрос - сколько таких методов Вы можете сделать в одном классе? Напоминаю - у них у всех одинаковая сигнатура должна быть! Сколько методов с одинаковой сигнатурой можно сделать в классе? |
Одноимённых методов с одним и тем же кол. параметров 1 _________________ Пишу дипломы, курсовые, лабары. Консультирую по скайпу до полного прозрения. Обращайтесь в личку. |
|
|
|
 |
sgdread : 2184 JT Библиотекарь Откуда: USA
|
Июн 21, 2011 23:17 |
|
|
У Inner-классов есть одна большая проблема - они порождают утечки памяти. Случается это из-за того, что порождающий класс неявно передает ссылку на себя анонимному классу (просто декомпилируйте class-файлы и все увидите), а это значит, что пока мы держим ссылку на экземпляр внутреннего класса, внешний класс не может быть собран. Пруф.
Вот-тут типичный пример из Swing-а с утечкой памяти через ActionListener.
Static Inner-классы такой проблемы решены. По сути вторые ничем не отличаются от обычных классов. _________________
 |
|
|
|
 |
bomba_flanker : 1582 Завсегдатай Откуда: Мск/Ульяновск
|
Июн 22, 2011 9:08 |
|
|
| Хорстманн писал(а): |
Может случиться так, что вам нужно будет использовать внутренний класс просто для того, чтобы скрыть его внутри другого класса, а ссылка на объект внешнего класса окажется ненужной. Подавить генерацию этой ссылки можно, объявив внутренний класс статическим (static).
...
Разумеется, только внутренние классы можно объявлять статическими. Статический внутренний класс ничем не отличается от любого другого внутреннего класса, за исключением того, что его объект не содержит ссылку на создавший его объект внешнего класса. |
| Код: |
public class Outer {
private String value;
public Outer() {
value = "1";
}
private class Inner {
void doSomething() {
value = "2"; //нет проблем
}
}
} |
| Код: |
public class Outer {
private String value;
public Outer() {
value = "1";
}
private static class Inner {
void doSomething() {
value = "2"; //ошибка
}
}
} |
| sgdread писал(а): |
| Static Inner-классы такой проблемы решены. По сути вторые ничем не отличаются от обычных классов. |
Спасибо sgdread и <ТС>initmax</ТС>! Такие темы и ответы заставляют копнуть глубже, чтобы разобраться в тонкостях. _________________ Google Вам в помощь
 |
|
|
|
 |
Skipy : 4801 Я тут живу! Откуда: Москва, Россия
|
Июн 22, 2011 10:03 |
|
|
| sgdread писал(а): |
| Вот-тут[/url] типичный пример из Swing-а с утечкой памяти через ActionListener. |
Давайте все-таки отделять мух от котлет. Это не утечка памяти, это небрежность разработчика, не удосужившегося убрать слушателей. Да, такая конструкция весьма популярна, и очень многие не задумываются об утечках. Но считать это проблемой именно иннер-классов... Я вон видел утечку, сотворенную на Map-е. Из него просто не убирались обработанные объекты. Полчаса работы, гиг памяти в минус и OOM как следствие. Ну это же не проблема Map-а? _________________ С уважением,
Евгений aka Skipy
www.skipy.ru
P.S. Я НЕ решаю задачи ЗА других! |
|
|
|
 |
initmax : 165 Новичок Откуда: Moon
|
Июн 22, 2011 12:04 |
|
|
Благодарю за ответы, статические классы создаются в единственном экзепляре и избавляют от "утечек памяти" хотелось бы увидеть пример где невозможно обойтись без Static inner классов. _________________ Пишу дипломы, курсовые, лабары. Консультирую по скайпу до полного прозрения. Обращайтесь в личку. |
|
|
|
 |
Skipy : 4801 Я тут живу! Откуда: Москва, Россия
|
Июн 22, 2011 14:05 |
|
|
| initmax писал(а): |
| Благодарю за ответы, статические классы создаются в единственном экзепляре и избавляют от "утечек памяти" |
Вот именно таких выводов и хотелось избежать. Не вышло.
Статические классы создаются в любом количестве экземпляров. Их отличие от нестатических только в том, что они не имеют ссылки на внешний класс. И, соответстветственно, не могут обращаться к переменным "их" экземпляра внешнего класса, для них вообще не существует понятия "их" экземпляра.
Ни от каких утечек статические классы не избавляют и не могут избавить. Утечка - это не следствие (не)статичности класса, это следствие ошибки разработчика вследствие незнания им каких-либо фактов (типа неявного наличия ссылок на "свой" экземпляр внешнего класса). Если бы в приведенном примере сохранялась ссылка на создаваемый внутренний класс, так, что потом бы этот слушатель удалялся - утечки бы не было. _________________ С уважением,
Евгений aka Skipy
www.skipy.ru
P.S. Я НЕ решаю задачи ЗА других! |
|
|
|
 |
sgdread : 2184 JT Библиотекарь Откуда: USA
|
Июн 22, 2011 20:21 |
|
|
| Skipy писал(а): |
| Давайте все-таки отделять мух от котлет. Это не утечка памяти, это небрежность разработчика, не удосужившегося убрать слушателей. Да, такая конструкция весьма популярна, и очень многие не задумываются об утечках. Но считать это проблемой именно иннер-классов... |
Ну вы бы почитали сначала, что я написал. Даже если вы уберете слушатели через removeListener, утечка останется. Причина не в добавлении/удалении, а в том, что анонимный inner-класс неявно содержит ссылку на объект-родитель (возьмите декомпилируйте код с inner-классом и увидите своими глазами - в анонимный класс передается this объекта-родителя). В результате, если у вас есть кнопочка, которая создает новое модальное окно, слушатель на которой - анонимный класс, вы получити феерическую утечку памяти - все модальные окна, созданные таким ActionListener-ом будут храниться в памяти и не будут собраны, пока не будет собран компонент с кнопочкой. Проблема ИМЕННО в анонимных inner-классах.
| Skipy писал(а): |
| Я вон видел утечку, сотворенную на Map-е. Из него просто не убирались обработанные объекты. Полчаса работы, гиг памяти в минус и OOM как следствие. Ну это же не проблема Map-а? |
Утечки на Map-ах - это слишком банально. Достаточно сделать mutable-ключи, чтобы у них менялся hashCode. _________________
 |
|
|
|
 |
Vermut : 1062 Завсегдатай Откуда: Ростов-на-Дону
|
Июн 22, 2011 21:15 |
|
|
| sgdread писал(а): |
| В результате, если у вас есть кнопочка, которая создает новое модальное окно, слушатель на которой - анонимный класс, вы получити феерическую утечку памяти - все модальные окна, созданные таким ActionListener-ом будут храниться в памяти и не будут собраны, пока не будет собран компонент с кнопочкой. Проблема ИМЕННО в анонимных inner-классах. |
Что помешает собирать сборщику мусора создаваемые в листенере окна, ведь он же запоминает ссылку не на них, а на родительский объект? _________________ Познакомлюсь с привлекательной Ростовчанкой для совместного изучения Java |
|
|
|
 |
|
|
Страница 1 из 2 На страницу 1, 2 След. |
Список форумов
-> Разное |
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|