Страницы

Поиск по вопросам

пятница, 14 декабря 2018 г.

Проблема с анонимными классами: как понимать создание объекта интерфейса? [дубликат]

На данный вопрос уже ответили: Использование анонимного класса 1 ответ Вот очень простой код:
item.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub
}
});
Вроде бы все легко. А я его не совсем понимаю. Даже немного стыдно из-за этого. В частности, не понимаю вот это выражение new ActionListener(). Здесь ведь есть и операция new и круглые скобки.. Как будто бы мы создаем объект. Но ведь нельзя создать объект интерфейса. Да и потом понятно что здесь создается анонимный класс, а не объект. Объясните пожалуйста, почему такой странный синтаксис и что же на самом деле тут происходит?
UPD: Написали что этот вопрос может являться дубликат: Использование анонимного класса Но там разбирается что в принципе происходит в строе new ActionListener(){} А я понимал, что там создается объект анонимного класса, мне было интересно почему для этого используется имя интерфейса.


Ответ

Когда ты создаешь новый объект, ты пишешь так:
new Foo();
Точка с запятой в конце важна, ты вызываешь непосредственно конструктор класса Foo.
В случае с анонимным классом ты делаешь так:
new ActionListener() { // Тело нового класса }
Обрати внимание на фигурные скобки. Это разница в синтаксисе. Теперь по смыслу: фактически ты создаешь наследника класса и одновременно вызываешь его конструктор без параметров, дополнительно в теле реализуя необходимые тебе методы. То есть такой себе одноразовый класс-наследник.
Ты мог бы сделать так в отдельном файле:
class MyActionListener implements ActionListener {
@Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub } }
А затем:
item.addActionListener(new MyActionListener());
по смыслу было бы аналогично, но в дальнейшем ты сможешь ещё создавать объекты MyActionListener, в то время как при использовании анонимного класса ты его описал, создал объект и забыл о его описании.

Как в java хранятся статические поля?

Как в java хранятся статические поля класса? Знаю что был такой вопрос. (JAVA) В какой области памяти хранятся статические поля класса? Но там сказано что они хранятся в Permanent Generation. А в java 8 ведь он заменен на MetaSpace? Хранятся ли они теперь в MetaSpace? Если да, объясните пожалуйста, почему так? Ведь MetaSpace это область, в которой хранятся метаданные? А статические поля не являются же метаданными.


Ответ

А в java 8 ведь он заменен на MetaSpace?
Да, если мы говорим о HotSpot jvm.
Хранятся ли они теперь в MetaSpace?
Да
Если да, объясните пожалуйста, почему так? Ведь MetaSpace это область, в которой хранятся метаданные?
MetaSpace - это та же PermGen, только с плюшкой в виде динамического расширения. В Permanent Generation предельный размер зависел от многих факторов: количество классов, методов, размер пула констант и т.п. Теперь размер мета пространства ограничен лишь размеров доступной памяти. Если хотим поменять, то юзаем флаг MaxMetaspaceSize
Таким образом исключили возможность выпадения java.lang.OutOfMemoryError. Ну да, если вы упрётесь в предел RAM, или в предел заданный в MaxMetaspaceSize, то исключение будет.
А статические поля не являются же метаданными.
Ммм. Если посмотреть книгу Java Data Objects, то там сказано, что статические поля - это мета данные.

Сравнение результата деления без остатка с нулём

Зачем тут сравнение с 0?
if (i % 3 == 0)
Я так понимаю, тут происходит деление без остатка, но не понимаю зачем потом сравнивать.


Ответ

Это проверка на то что остаток от деления числа i на другое число (3) равен 0.
Обычно так делается для того чтобы выполнять какое-то действие в цикле, но не каждый раз (в данном случае только каждый 3 раз).
Например:
раскрасить каждую 2 строку в списке другим цветом if(i % 2 == 0) ... показать на экране прогресс при каждой 10 итерации if(i % 10 == 0) ... разделить поток цифр, добавив пробел после каждых 3 if(i % 3 == 0) ... и т.п.

Проверить наличие CSS класса в javascript

Как проверить наличие или отсутствие класса у элемента на чистом javascript?
Необходимо добавить класс элементу по клику, но при этом проверить наличие у него этого класса перед добавлением, чтобы класс не дублировался.
вот код:
var cells = document.getElementsByTagName('td');
for(var i=0; iссылка на полный код jsfiddle


Ответ

сделала так - по клику добавляется класс и удаляется при повторном клике. вот код:
var cells = document.getElementsByTagName('td'); for(var i=0; ifunction selectDate(){ if(this.classList.contains('active')){ this.classList.remove('active'); }else { this.classList.add('active'); } }
ссылка на полный код: jsfiddle

Почему в int переменной странное число?

Почему переменная t выводит на экран не то?
#include #include
int a[7];
void vvoda(){ puts("Puts values for a array"); for(int i = 0; i < 7; i++) scanf("%i", &a[i]); }
void suma(){ int t; for(int i = 0; i < 7; i++){ t += a[i]; t = t/7; printf("%i
", &t); } printf("Average of a array is %i", &t); }
main(void){ vvoda(); suma(); }
Вот что выдает консоль:
Puts values for a array 4 5 45 4 54 5 4 2293272 2293272 2293272 2293272 2293272 2293272 2293272 2293272 Average of a array is 2293272 -------------------------------- Proccess exited after 2.143 seconds with return value 0 Для продолжения нажмите любую клавишу . . .


Ответ

Во-первых, у вас не инициализирована локальная переменная t
void suma(){ int t; ^^^^^^
Во-вторых, если вы используете выражение t = t/7;, то логично было бы объявить эту переменную, как число с плавающей запятой, например, имеющую тип double. Иначе у вас будет отбрасывание дробной части, то есть будет иметь место целочисленное деление. Например, при t равным 4 выражение t/7 будет равно 0
И, в-третьих, в данных предложениях вывода
printf("%i
", &t); ^^^^
printf("Average of a array is %i", &t); ^^^^
вы должны использовать саму переменную, а не указатель на нее.
printf("%i
", t); printf("Average of a array is %i", t);
Имейте в виду, что согласно стандарту C функция main без параметров должна иметь объявление
int main( void ) ^^^
Также вместо магического числа 7 было бы лучше ввести именованную константу, как, например,
#define N 7
и использовать это имя вместо числа.
Например
#define N 7
int a[N];
void vvoda(){ puts("Puts values for a array"); for(int i = 0; i < N; i++){ scanf("%i", &a[i]); } } // и т.д.
Также не было никакой необходимости объявлять массив a глобальным.
Заголовок можно исключить из программы, так как ни одно определение из этого заголовка не используется.

Java - путь исполняемого jar файла

Требуется достать полный путь исполняемого файла, но при этом вернуться на 1 каталог назад, к примеру
мой класс.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()
Возвращает
/C:/Users/Arturs/Desktop/DIV.jar
но мне нужно довести до /C:/Users/Arturs/ Есть ли какие то предусмотренные функции, что бы не приходилось обрезать строку, высчитывая количество символов справа.


Ответ

Попробуй так:
Path path = Paths.get(твой_класс.class.getResource(".").toURI()); System.out.println(path.getParent()); // <-- Parent directory System.out.println(path.getParent().getParent()); // <-- Parent of parent directory

Использование переменных объявленных в for

Почему недопустим такой вариант?
int sum=0; for(int j=0; jА такой компилируется:
int sum=0; int j=0; for( ; j(mas уже инициализирован)


Ответ

Я думаю, оба варианта компилируются, только первый выдаёт предупреждение из-за того, что этот код содержит undefined behaviour.
Переменную sum инициализировать за вас компилятор не будет. А использование неинициализировнной переменной есть даже не unspecified, а undefined behaviour. Это значит, что не только «начальное значение переменной может быть любым», но «при выполнении программы может произойти всё, что угодно, включая форматирование жёсткого диска».

Окей, вопрос отредактирован, теперь обе переменные инициализированы, ищем дальше.
Но я не заметил ещё одну ошибку. У вас написано for(int j=0; jВ результате в первом случае переменная j локальна в блоке и не видна за его пределами: этот код можно равносильно записать так:
for(int j=0; j{ sum+=mas[0][j]; sum+=mas[n-1][j]; }