• 0.00

  • 0.00

  • ,

Изменения в лекциях

Недавно в комментариях к какой-то теме один добрый человек выложил свои материалы, которые он писал, обучаясь тут. За что ему большое спасибо, но не помню, где это было, чтобы написать там.
Но дело не в этом. Произошла такая интересная история:
как и у многих, уровни начиная с 17 требуют много времени. Вот сижу, ковыряю. Доковыряла до задач 18ого уровня, прочитав лекции и половину доп.материалов. Смотрю задачу, понимаю, что решить ее можно несложно, но кажется велосипед. Думаю-думаю, ничего не придумывается кроме похожих на велосипед вещей. Думаю, а как ее решали до меня. Смотрю, все как один используют RandomAccessFile, о котором в лекциях ни слова. Только в доп.материалах. Мой велосипед на нем и основывался, но до некоторых вещей я своим умом не дошла. Думаю, надо получше почитать про это… где-то были тут материалы от доброго человека. Открываю, смотрю и понимаю, что раньше (похоже) это было в лекциях. А сейчас нет. А задача осталась.
Дело не в том, что непонятно как ее решать (хотя, конечно, некоторые непонятки могут возникать и иногда довольно сильно раздражают). Как-то грустно стало, что лекции урезали и я сейчас читаю эти урезанные лекции, а доп.информация впитывается не так хорошо, как лекции.

Если вдруг кто-то из администраторов сюда зайдет, было бы интересно узнать, почему так порезали лекции =(
  • ,

level16.lesson05.task03

Подскажите пожалуйста, зачем нужны, как и когда отрабатывают циклы while (в мейне и в методе run() класса Politic). Никак не могу понять.

package com.javarush.test.level16.lesson05.task03;

/* Продвижение на политических дебатах
1. Разберитесь, что делает программа.
2. Нужно сделать так, чтобы Иванов сказал больше всего речей на политических дебатах.
3. Подумай, какой метод можно вызвать у объекта ivanov, чтобы Иванов разговаривал, пока не завершится всё свободное время.
*/

public class Solution {
    public static int totalCountSpeeches = 200;
    public static int soundsInOneSpeech = 1000000;

    public static void main(String[] args) throws InterruptedException {
        Politic ivanov = new Politic("Иванов");

        Politic petrov = new Politic("Петров");
        Politic sidorov = new Politic("Сидоров");

        while (ivanov.getCountSpeaches() + petrov.getCountSpeaches() + sidorov.getCountSpeaches() < totalCountSpeeches) {
        }

        System.out.println(ivanov);
        System.out.println(petrov);
        System.out.println(sidorov);
    }

    public static class Politic extends Thread {
        private int countSounds;

        public Politic(String name) {
            super(name);
            start();
        }

        public void run() {
            while (countSounds < totalCountSpeeches * soundsInOneSpeech) {
                countSounds++;
            }
        }

        public int getCountSpeaches() {
            return countSounds / soundsInOneSpeech;
        }

        @Override
        public String toString() {
            return String.format("%s сказал речь %d раз", getName(), getCountSpeaches());
        }
    }
}
  • ,

level16.lesson05.task03

Подскажите пожалуйста, зачем нужны, как и когда отрабатывают циклы while (в мейне и в методе run() класса Politic). Никак не могу понять.

package com.javarush.test.level16.lesson05.task03;

/* Продвижение на политических дебатах
1. Разберитесь, что делает программа.
2. Нужно сделать так, чтобы Иванов сказал больше всего речей на политических дебатах.
3. Подумай, какой метод можно вызвать у объекта ivanov, чтобы Иванов разговаривал, пока не завершится всё свободное время.
*/

public class Solution {
    public static int totalCountSpeeches = 200;
    public static int soundsInOneSpeech = 1000000;

    public static void main(String[] args) throws InterruptedException {
        Politic ivanov = new Politic("Иванов");

        Politic petrov = new Politic("Петров");
        Politic sidorov = new Politic("Сидоров");

        while (ivanov.getCountSpeaches() + petrov.getCountSpeaches() + sidorov.getCountSpeaches() < totalCountSpeeches) {
        }

        System.out.println(ivanov);
        System.out.println(petrov);
        System.out.println(sidorov);
    }

    public static class Politic extends Thread {
        private int countSounds;

        public Politic(String name) {
            super(name);
            start();
        }

        public void run() {
            while (countSounds < totalCountSpeeches * soundsInOneSpeech) {
                countSounds++;
            }
        }

        public int getCountSpeaches() {
            return countSounds / soundsInOneSpeech;
        }

        @Override
        public String toString() {
            return String.format("%s сказал речь %d раз", getName(), getCountSpeaches());
        }
    }
}
  • ,

level16.lesson05.task03

Подскажите пожалуйста, зачем нужны, как и когда отрабатывают циклы while (в мейне и в методе run() класса Politic). Никак не могу понять.

package com.javarush.test.level16.lesson05.task03;

/* Продвижение на политических дебатах
1. Разберитесь, что делает программа.
2. Нужно сделать так, чтобы Иванов сказал больше всего речей на политических дебатах.
3. Подумай, какой метод можно вызвать у объекта ivanov, чтобы Иванов разговаривал, пока не завершится всё свободное время.
*/

public class Solution {
    public static int totalCountSpeeches = 200;
    public static int soundsInOneSpeech = 1000000;

    public static void main(String[] args) throws InterruptedException {
        Politic ivanov = new Politic("Иванов");

        Politic petrov = new Politic("Петров");
        Politic sidorov = new Politic("Сидоров");

        while (ivanov.getCountSpeaches() + petrov.getCountSpeaches() + sidorov.getCountSpeaches() < totalCountSpeeches) {
        }

        System.out.println(ivanov);
        System.out.println(petrov);
        System.out.println(sidorov);
    }

    public static class Politic extends Thread {
        private int countSounds;

        public Politic(String name) {
            super(name);
            start();
        }

        public void run() {
            while (countSounds < totalCountSpeeches * soundsInOneSpeech) {
                countSounds++;
            }
        }

        public int getCountSpeaches() {
            return countSounds / soundsInOneSpeech;
        }

        @Override
        public String toString() {
            return String.format("%s сказал речь %d раз", getName(), getCountSpeaches());
        }
    }
}
  • ,

level15.lesson12.home06

Товарищи, может кто-то может разъяснить следующий момент по задаче:
В нон-статик блоке мы вызываем метод printAllFields(), которому передаем this. Насколько я понимаю, this — это ссылка на объект. Но нон-статик блок мы вызываем до конструктора самого объекта, откуда появляется this (если вроде как объект ещё не создан) и что это значит? В какой момент он появляется?

место непоняток в коде отметила комментарием =))

package com.javarush.test.level15.lesson12.home06;

/* Порядок загрузки переменных
Разобраться, что в какой последовательности инициализируется.
Исправить порядок инициализации данных так, чтобы результат был следующим:
static void init()
Static block
public static void main
non-static block
static void printAllFields
0
null
Solution constructor
static void printAllFields
6
First name
*/

public class Solution {
    static {
        init();
    }

    public static void init() {
        System.out.println("static void init()");
    }

    static {
        System.out.println("Static block");
    }

    public static void main(String[] args) {
        System.out.println("public static void main");
        Solution s = new Solution();
    }

    {
        System.out.println("non-static block");
        printAllFields(this); //непонятно, какой this мы здесь берем, если объект ещё не создан (т.е. неизвестна пока ссылка
        //на готовый объект)
    }

    public static void printAllFields(Solution obj) {
        System.out.println("static void printAllFields");
        System.out.println(obj.i);
        System.out.println(obj.name);
    }

    public int i = 6;

    public String name = "First name";


    public Solution() {
        System.out.println("Solution constructor");
        printAllFields(this);
    }


}
  • ,

level15.lesson12.home06

Товарищи, может кто-то может разъяснить следующий момент по задаче:
В нон-статик блоке мы вызываем метод printAllFields(), которому передаем this. Насколько я понимаю, this — это ссылка на объект. Но нон-статик блок мы вызываем до конструктора самого объекта, откуда появляется this (если вроде как объект ещё не создан) и что это значит? В какой момент он появляется?

место непоняток в коде отметила комментарием =))

package com.javarush.test.level15.lesson12.home06;

/* Порядок загрузки переменных
Разобраться, что в какой последовательности инициализируется.
Исправить порядок инициализации данных так, чтобы результат был следующим:
static void init()
Static block
public static void main
non-static block
static void printAllFields
0
null
Solution constructor
static void printAllFields
6
First name
*/

public class Solution {
    static {
        init();
    }

    public static void init() {
        System.out.println("static void init()");
    }

    static {
        System.out.println("Static block");
    }

    public static void main(String[] args) {
        System.out.println("public static void main");
        Solution s = new Solution();
    }

    {
        System.out.println("non-static block");
        printAllFields(this); //непонятно, какой this мы здесь берем, если объект ещё не создан (т.е. неизвестна пока ссылка
        //на готовый объект)
    }

    public static void printAllFields(Solution obj) {
        System.out.println("static void printAllFields");
        System.out.println(obj.i);
        System.out.println(obj.name);
    }

    public int i = 6;

    public String name = "First name";


    public Solution() {
        System.out.println("Solution constructor");
        printAllFields(this);
    }


}
  • ,

Вопрос про инициализацию переменных

Сокурсники!
Подскажите пожалуйста, наткнулась тут на интересный комментарий от автора статьи.

Вопрос: В чем особенность инициализации локальных переменных?
Ответ: Локальные переменные не инициализируются автоматически пустым значением null. Локальную переменную необходимо явно инициализировать с помощью оператора new или присвоив ей пустое значение null.

Но вот тут есть такой момент:

На самом деле процесс инициализации проходит следующим образом:
  • Память, выделенная под новый объект, заполняется двоичными нулями.
  • Конструкторы базовых классов вызываются в описанном ранее порядке. В этот момент вызывается переопределенный метод draw() (да, перед вызовом конструктора класса RoundGlyph), где обнаруживается, что переменная radius равна нулю из-за первого этапа.

  • Вызываются инициализаторы членов класса в порядке их определения.
  • Исполняется тело конструктора производного класса.
У происходящего есть и положительная сторона — по крайней мере, данные инициализируются нулями (или тем, что понимается под нулевым значением для определенного типа данных), а не случайным «мусором» в памяти. Это относится и к ссылкам на объекты, внедренные в класс с помощью композиции. Они принимают особое значение null.

Проверила. Если не присваивать значение, то инициализируются действительно null-ом или значением по умолчанию для примитивных типов.
Что имел ввиду автор? Или это ошибка?
  • ,

Работа компилятора с импортами

На Интуите написано много всего интересного хоть и неинтересным языком =)

Импортирование пакетов и типов (классов и интерфейсов) пакетов создано для упрощения жизни. С импортированными пакетами доступ к переменным пакета может быть по простому имени. Можно и обойтись без импортов, но тогда каждый раз нужно будет писать полное имя переменной. Однако, при компиляции все имена приводятся к полным. И компилятор тут работает в следующей последовательности:

  • сначала просматриваются выражения, импортирующие типы;
  • затем другие типы, объявленные в текущем пакете, в том числе в текущем модуле компиляции;
  • наконец, просматриваются выражения, импортирующие пакеты.

Если у нас в пакете объявлен тип (класс):

package my_geom;

class Point {
}


а в другом модуле компиляции:

package my_geom;

import java.awt.Point;

class Line {
   void main() {
      System.out.println(new Point());
   }
}


то складывает неопределенная ситуация: какой Point создать и вывести: из пакета my_geom или импортированный java.awt.Point. И вот тут нужно руководствоваться приведенной выше очередностью. Т.к. мы импортировали тип java.awt.Point, то именно этот поинт будет создаваться. Если бы импорт был такой (не конкретный тип, а пакет):

import java.awt.*;


то результат был бы другой (использовался бы тип, объявленный в текущем пакете, т.е. в пакете my_geom)
  • ,

Конструкторы, процесс создания объекта

Интересный момент с Интуита:

можно использовать this не только как обращение к полям объекта класса, но и как обращение к конструктору (который вообще-то не имеет имени и извне доступен только с помощью ключевого слова new):


public class Vector {
   private int vx, vy;
   protected double length;

   public Vector(int x, int y) {
      super();
      vx=x;
      vy=y;
      length=Math.sqrt(vx*vx+vy*vy);
   }

   public Vector(int x1, int y1, 
                 int x2, int y2) {
      super();
      vx=x2-x1;
      vy=y2-y1;
      length=Math.sqrt(vx*vx+vy*vy);
   }
}


можно записать короче:


public class Vector {
   private int vx, vy;
   protected double length;

   public Vector(int x, int y) {
      super();
      vx=x;
      vy=y;
      length=Math.sqrt(vx*vx+vy*vy);
   }

   public Vector(int x1, int y1, 
                 int x2, int y2) {
      this(x2-x1, y2-y1);           //можно использовать даже this(), если существует такой конструктор в этом классе!!!
   }
}


Также первой строкой любого конструктора должно идти обращение к конструктору родительского объекта (super() ). Если такой строки нет, то компилятор по умолчанию ее добавляет с пустыми параметрами. Но! Если у родительского объекта нет конструктора с пустыми параметрами, то произойдет ошибка компиляции. Соответственно, создание любого объекта происходит как инициализация всех родителей, а затем возвращение ссылки на итоговый объект.
  • ,

Порядок объявления переменных

Ещё интересный момент отсюда: Интуит

Запрещается использовать поле в инициализации других полей до его объявления.

int y=x; //так нельзя
int x=3;


Однако, в остальном поля можно объявлять и ниже их использования:

class Point {
   int getX() {return x;}

   int y=getX();
   int x=3;
}
public static void main (String s[]) {
      Point p=new Point();
      System.out.println(p.x+", "+p.y);
}


Результатом будет:

3, 0
Данный пример корректен, но для понимания его результата необходимо вспомнить, что все поля класса имеют значение по умолчанию:

для числовых полей примитивных типов – 0;
для булевского типа – false;
для ссылочных – null.
Таким образом, при инициализации переменной y был использован результат метода getX(), который вернул значение по умолчанию переменной x, то есть 0. Затем переменная x получила значение 3.
  • ,

Модификаторы доступа

Интересный пример из доп.материалов (http://old.intuit.ru/department/pl/javapl/6/)

public class Point {
  private int x, y;

  public boolean equals(Object o) {
    if (o instanceof Point) {
      Point p = (Point)o;
      return p.x==x && p.y==y; //интересна эта строка
    }
    return false;
  }
}


в то время как

Human h = new getHuman();   // получаем ссылку
int i=h.age;   // ошибка!!


«private допускает обращения из любой точки класса, независимо от того, к какому именно объекту оно производится.» Т.е. внутри класса мы можем обращаться к private полям (и методам наверное) любых объектов этого класса.

Вообще в Java 4 модификатора доступа:
private
(none) default
protected
public
  • ,

Итератор. Чтобы не забыть + удаление объектов из map

Оставила себе несколько заданий, чтобы некоторые темы освежить в памяти после следующих уровней.
С итератором возникла проблема.
Пусть тут висит и напоминает, как с ним работать (если вдруг понадобится):


    public static void removeAllSummerPeople(HashMap<String, Date> map)
    {
        //напишите тут ваш код
        Iterator <Map.Entry<String,Date>> iterator=map.entrySet().iterator();

        while (iterator.hasNext()){
            Map.Entry<String,Date> pair=iterator.next();
            int month=pair.getValue().getMonth();
            if(month>=5&&month<8){
                iterator.remove();
            }
        }
    }


И ещё можно удалять объекты из map вот так (копируем map, чтобы не ломался итератор, а удаляем все в оригинальном map):

Map<String, String> map = new HashMap<>();
map.put("1", "2");
map.put("3", "4");

Map<String, String> mapCopy = new HashMap<>(map);
for(Map.Entry<String, String> pair : mapCopy.entrySet()) {
    map.remove(pair.getKey());
}