JavaRush/Java блог/Архив info.javarush/Вопросы по пониманию Java
Hehabr
13 уровень

Вопросы по пониманию Java

Статья из группы Архив info.javarush
участников
Давно хотел спросить. Когда вижу код подобный этому: public class Solution { public Solution method1 (String s) { // bla-bla } } ... когда начинается описание класса и тут же внутри него описывается метод, имеющий тип этого же класса - мне всегда это кажется нелогичным. Ведь класс ещё не описан до конца и не создан, да и вообще как это можно так внутри самого себя свой же тип использовать для метода? Вот если бы было например 2 класса: один Solution, а другой скажем Answer. И метод Solution method1() объявлялся бы в классе Answer - тогда бы это казалось понятным и логичным. Т.е. сначала об"является новый класс (тип данных) Solution, а уже затем, когда он существует - его можно начинать использовать как тип для описания новых методов. Как бы разобраться с этим? Может кто объяснить или посоветовать что почитать по этому поводу?
Комментарии (55)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
gnev
Уровень 24
5 сентября 2015, 20:53
Потому что будет вот так
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

For example, the following code is correct:

short x = 3;
x += 4.6;
and results in x having the value 7 because it is equivalent to:

short x = 3;
x = (short)(x + 4.6);

т.е. в сокращенном варианте приведение все-таки неявно существует.
Hehabr
Уровень 13
5 сентября 2015, 19:10

        short s = 1;
        int i = 1;

        s += i ;    // a
        s = s+i ;   // b


Почему в строке «a» всё хорошо, а в строке «b» плохо?!
AndreGold
Уровень 28
5 сентября 2015, 21:04
Если в выражении используются переменные типов byte, short и int, то во избежание переполнения тип всего выражения автоматически повышается до int. Если же в выражении тип хотя бы одной переменной — long, то и тип всего выражения тоже повышается до long. Не забывайте, что все целые литералы, в конце которых не стоит символ L (или 1), имеют тип int.

Если выражение содержит операнды типа float, то и тип всего выражения автоматически повышается до float. Если же хотя бы один из операндов имеет тип double, то тип всего выражения повышается до double. По умолчанию Java рассматривает все литералы с плавающей точкой как имеющие тип double.

В вашем случае, во строке b есть int, соответственно тип всего выражения s+i повыситься до int, а дальше вы пытаетесь положить в short значения типа int, чего не сделать без приведения типов(сужение).

s = (short)(s+i)
Hehabr
Уровень 13
18 августа 2015, 16:05
class A
{
    void method a1()
    {
       
    }
}


IDEA подчеркивает а1 красным:
Invalid method declaration; return type required

Почему так, ведь void стоит же, значит никакого возвращаемого типа вообще не нужно? В чём здесь загвоздка?
hubert
Уровень 41
18 августа 2015, 16:09
А какой тип Вы возвращаете? МОжет method?
Или как метод называется: а1 или method?
а может void это вообще Ваш личный модификатор доступа?
hubert
Уровень 41
18 августа 2015, 16:12
visibility [static] return-type method-name (parameter-list)
{
        statements...
}
Hehabr
Уровень 13
18 августа 2015, 16:40
Спасибо. Всё понятно. Туплю. Перезанимался видимо. Надо сделать паузу.
Hehabr
Уровень 13
18 августа 2015, 16:41
Wow! Вот это классно! Давно хотел найти что-либо подобное. Спасибо большое.
hubert
Уровень 41
18 августа 2015, 16:45
Hehabr
Уровень 13
18 августа 2015, 17:06
Может тогда ещё
[throws ...]
добавить в конце 1-й строки?


visibility [static] return-type method-name (parameter-list) [throws ...]
{
        statements...
}
Hehabr
Уровень 13
25 июля 2015, 19:29
public class Test
{
    static { int a=5; }

    public static void main(String[] args)
    {
        System.out.println(a);    //  1
        Test t = new Test();
        System.out.println(t.a);  //  2
    }
}


Почему компилятор не дайт вывести значение переменной
a
ни в первом ни во втором случае?
Ipshin
Уровень 41
25 июля 2015, 20:21
Потому что " static { } " это блок статической инициализации.Из него нельзя просто так вытащить пеерменные, только инициализировать. Плюс к этому инициализировать в static{ } можно только статические переменные, для инициалиации обычных переменных используется обычный же блок { }.

Короче код должен быть таким:

public class Test
{
    int a;
    {  a=5; }

    public static void main(String[] args)
    {
        System.out.println(a);    //  1
        Test t = new Test();
        System.out.println(t.a);  //  2
    }
}
Hehabr
Уровень 13
25 июля 2015, 21:05
А если вот так написать:
public class Test
{
    static { int a=5; }
    public static void main(String[] args)
    {
    }
}

то всё работает, в том числе и строка
static { int a=5; }
. Что же тогда при этом в ней происходит? Где то же присваивается что а равна 5, хоть а и не статическая. Или как?
leshak
Уровень 27
26 июля 2015, 03:14
Это локальная переменная, она существует только в статическом блоке. В первом варианте то же самое было.
Hehabr
Уровень 13
22 июля 2015, 20:58
Спасибо за подсказки. Дошло когда представил проблемный кусок кода со скобками. Вот так:
else a = ( x ? 3 : 4 ) ; 
Hehabr
Уровень 13
22 июля 2015, 19:23
public class test
{
    public static void main(String[] args)
    {
        boolean x=false;
        int a;
        if(x) a = x ? 1 : 2;
        else a = x ? 3 : 4;
        System.out.println(a);
    }
}


Код работает и выводит 4
Что представляется несколько непонятным поскольку как мне думается код не должен компилироваться из-за присваивания
a = x

Ведь здесь переменной а типа int присваивается логическое значение false

Как тут разобраться?
AndreGold
Уровень 28
22 июля 2015, 20:35
разберитесь с тернарным оператором
Итак
boolean x=false;

Проверям, истина или ложь
if(x) a = x ? 1 : 2;

у нас x = false; Значит выполняется ветка else
else a = x ? 3 : 4;

а именно код
x ? 3 : 4

По тернарному оператору
(условие) ? истина : ложь

а так как у вас
x = false;
a = 4;
AndreGold
Уровень 28
22 июля 2015, 20:37
для тернарного оператора x это условие. И в зависимости, что там true или false. Соответственно a присвоится либо 3 либо 4
Hehabr
Уровень 13
19 марта 2015, 18:47
Подскажите если класс реализует интерфейс InterfaceName, то будет ли вложенный статический класс наследовать эту реализацию?
Или же во вложенном статическом классе надо будет тоже писать в сигнатуре: implements InterfaceName?
VovanZzZurka
Уровень 40
19 марта 2015, 20:55
По-поводу вложенного статического класса нужно помнить только 2 правила:
1. Его имя начинается с имени внешнего класса: Package.OuterClass.NestedClass.
2. Он делит одну и ту же область видимости, что и внешний класс. (private обьекты и методы видны друг другу в обе стороны).

В остальном же, внешний и вложенный класс никак не связаны.
Diana
Уровень 41
19 марта 2015, 14:37
Есть сущность(объект), которая хранит важные данные.
Эту сущность можно редактировать.

Есть пользователи, которые используют сущность для своих целей, например, изменяют ее.
Случаются неправильные обновления, например, оператор ошибся и затер важные данные.

Какие предложите архитектурные решения, чтобы можно было восстановить данные?
balu1973
Уровень 29
20 марта 2015, 10:06
Накопал про паттерн хранитель подходит?
Diana
Уровень 41
19 марта 2015, 14:26
Приложение постоянно падает с NPE.

Какой паттерн будете использовать, чтоб избавиться от этой ненавистной NPE?

Какую аннотацию используют многие фреймворки для параметров методов, чтобы не проверять аргументы на null?
balu1973
Уровень 29
19 марта 2015, 16:24
Аннотация @NotNull? почитал на javarush, нашел про паттерн Null-объекта. Вроде про фабрику еще где то говорилось)
Diana
Уровень 41
19 марта 2015, 14:20
В приложении есть Прогресс бар.

Предположим, приложение имеет список действий, которые выполняются последовательно. Каждый объект каждого действия имеет метод М, который показывает, сколько времени предположительно займет выполнение этого действия. Метод М используется прогресс-баром для подсчета продолжительности исполнения всех действий.

Какой паттерн будете использовать?