Java. Проблема с инициализацией переменной
public static void main(String[] args) {
int n = 100;
double[] array = new double[n];
for (int i = 0; i < array.length; i++) {
array[i] = Math.random();
}
double max = array[0]; // Массив не должен быть пустым
double min = array[0];
double avg = 0;
for (int i = 0; i < array.length; i++) {
if(max < array[i])
max = array[i];
if(min > array[i])
min = array[i];
avg += array[i]/array.length;
}
System.out.println("max = " + max);
System.out.println("min = " + min);
System.out.println("avg = " + avg);
}
Вот такое вот код,извините меня за дурость конечно,но не могли бы вы мне подсказать ,почему в третьей строчке,компилятор запрашивает инициализацию переменной " array",хотя она уже инициализирована.Еще раз извиняюсь,решил стать на путь Java разработчика....
44 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарівpublic static void main(String[] args) { IntStream arr = new Random().ints(100); System.out.println("min = " + arr.min().getAsInt()); System.out.println("max = " + arr.max().getAsInt()); System.out.println("avg = " + arr.average().getAsDouble()); }от тільки ваш код робить 3 проходи по колекції, а у топікстартера за один) єдине, що там змінити — це розрахунок avg, бо можна ділення зробити за циклом. А взагалі для навчання використання таких методів тільки шкодить навчанню, бо люди починають забагато надіятись на те, що все вже написано, можливо і так, але поки людина не розуміє, як воно працює під капотом, я би не радив давати такі поради
для 99.9% проектов лучше в таком случае 3 прохода в угоду удобства чтения кода.
А так да, скорее для фана коммент добавлен
public static void main(String[] args) { var stat = new Random().ints(100).summaryStatistics(); System.out.println("min = " + stat.getMin()); System.out.println("max = " + stat.getMax()); System.out.println("avg = " + stat.getAverage()); }min, max, average терминальные операции, не? После любого из них стрим уже будет закрыт.
Нижевыше лучше версия.а, наверное да, я не запускал )
Учебные версии в принципе не стоит оптимизировать по функционалу. Человека учат как делать, на основе примитивных операций. В боевом коде обработка данных уже не будет столь простой, равно как и сами данные.
В конце концов, есть те же самые Collections.min, Collections.max... и привет ручное написание компаратора в отдельный класс для данных твоего класса, вместо того чтобы наглядно всё показать в простеньком for each цикле.
С твоим кодом всё норм: ideone.com/KKkbXE
Ищи проблему в другом месте. Возможно, IDE что-то не то пытается собирать.
щаз окажется что компилится совсем другой проект
И вообще, он тебе ошибку даёт, или warning? С ворнингом как раз всё понятно: ты используешь примитивный тип, который не допускает null значений. Подкинь ему Double вместо double как тип массива, и этим упростишь реальный исполняемый код. В любом случае там будет Double, у Java давно уж нет примитивов (разве только в sun.misc.Unsafe, куда ты вряд ли полезешь за всю карьеру).
Что здесь немножко некошерно:
1) Ты не позволяешь компилятору оптимизировать код. Генеря массив от переменной, ты задерживаешь инициализацию до времени исполнения. Ничего особо проблемного, просто ты ещё и чтение кода человеком задерживаешь: ты не хочешь сразу вписать 100 в код (это было бы понятно с ходу), и ты не хочешь дать переменной правильное имя, и сказать const (это тоже понятно, что возможно в дальнейшем ты планируешь откуда-то брать эту переменную, например из аргумента командной строки).
2) Ты обращаешься к array[0], и сам пишешь, что он к тому времени должен быть. Но компилятор в этом не уверен ни разу, потому получай ворнинг. Как правильно:
Double min, max;
И уже в коде ты проверяешь, не null ли они. Почему так? Потому что размерность массива у тебя вынесена в переменную, а там вероятно и за пределы твоего кода. Прилетит 0 — получишь RuntimeException.
3) Сложение строки с числом. Тем более с Double. Как думаешь, сколько будет (1/3)*3? Учи мат.часть по работе с плавающей точкой, и запомни: ВСЕГДА нужно форматировать вывод, если не хочешь чтобы в реальных данных потом торчали краказяблы. Здесь соответственно тоже проверишь на null.
так стоп, а це як?
А отак. Все є об′єкти, і double породжується конструктором Double.
String то взагалі досить унікальний клас:
String aziat1 = «Ja kitaec»;
String aziat2 = «Ja kitaec»;
if(aziat1== aziat2) System.out.print («Та вони всі однакові!!!»);
че, открыл для себя стринг пул?
дурак
да ладно, не стоит себя так критиковать, у всех ошибки случаются. Зря ты на себя так
Ну зі стрінгами ясно, тут все ок.
Але з Double все одно не шарю.
- А з якої версії вже нема? Бо я на 8 пишу
Примітиви є в мові, але їх нема в самій JVM, притому дууже давно, значно довше за 8. Якщо цікаво, візьми reflect та подивися, що насправді чим є. Якщо не цікаво, просто знай, що примітиви є де-факто полями відповідних об′єктів. Інакше б це не дозволило з ними ефективно працювати самій JVM. Колись дуже давно ця наявність примітивних типів навіть створила серйозну проблему безпеки.
Зараз краще за все не використовувати примітиви зовсім, хіба що int в ітераторах, якщо так хочеться робити олдскульні цикли, які звично виглядають. Але для всього іншого — погодься, краще мати null там де ти забув дати значення чи допустив помилку (і NullPointerException відповідно), замість того щоб мати чесний 0 та пропустити помилку в дані.
Коли тобі насправді буде потрібен рефлект:
— коли ти робиш свою трансляцію даних, наприклад, хочеш щоб дані із одного формата із завданими полями — стали відповідними полями класа, і ти не хочеш все це переписувати щоразу.
— коли тобі треба міняти обмеження доступу до полів об′єкта, наприклад, зняти заборону запису даних в поле.
— коли тобі потрібно створювати клас прямо з коду.
Вивчати його до того вигоди особливої нема, десь половина програмістів на java ніколи з ним не матимуть справу й за 10 років досвіду. Але про наявність цієї технології варто знати, що замість геморойних get та set можна працювати із об′єктами через reflect.
Основна вигода — коли треба мати справу із класами, які створив не ти, але тобі аж ніяк не хочеться декомпилити та заново компилити сторонні бібліотеки. Особливо корпоративні. Наприклад, улюблена «фіча» корпоративних кодерів великих компаній — приховати інформацію про реально помилку, замінивши її на дибільний номер, який нічого не значить — і от тоді ти можеш влізти напряму в чужий код, і замінити поведінку лише одного метода так, щоб він працював як тобі треба. Або ж коли якесь поле прихованих опцій роблять приватним з «магічним» значенням, а тобі конче потрібно ним керувати.
Хм, цікаво.
Про рефлексію знав і пробував юзати на рівні аля «написати 1 POJO і просто подивитись, що ж вона вміє робити з ним».
Дякую за інфу!
Я так і сказав: рефлексія потрібна в досить небагатьох випадках. Але може бути дуууже корисною при написанні тестів.
Ну і вишенька на тортику — рефлексія вміє працювати з анотаціями, а це дозволяє творити досить цікавий синтаксичний цукор.
смешать в кучу рефлексию и примитивы это надо точно сидеть на чем-то забористом
Да не слушай ты его. Чувак, похоже, вообще не понимает о чем говорит
Якого *** тут відбувається? Це ти тіпа тролиш, шкодиш чи реально тупий?
doubleНЕ породжується конструкторомDouble.Код 1:
public class A { public static void main(String[] args) { double x = 1.1; x += 10; System.out.println(x); } }Дає такий байткод:
Compiled from "A.java" public class A { public A(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: ldc2_w #7 // double 1.1d 3: dstore_1 4: dload_1 5: ldc2_w #9 // double 10.0d 8: dadd 9: dstore_1 10: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream; 13: dload_1 14: invokevirtual #17 // Method java/io/PrintStream.println:(D)V 17: return }Нема ніякого виклику конструкторівDouble. Нема!Код 2:
public class A { public static void main(String[] args) { Double x = 1.1; x += 10; System.out.println(x); } }Дає такий байткод:Compiled from "A.java" public class A { public A(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: ldc2_w #7 // double 1.1d 3: invokestatic #9 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 6: astore_1 7: aload_1 8: invokevirtual #15 // Method java/lang/Double.doubleValue:()D 11: ldc2_w #19 // double 10.0d 14: dadd 15: invokestatic #9 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 18: astore_1 19: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream; 22: aload_1 23: invokevirtual #27 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 26: return }Поясню що відбувається: для ініціалізації об’єкту
Doubleпримітивне значення 1.1 передається вDouble.valueOf(а не конструктор). Потім з цього ж об’єкту викликаєтьсяx.doubleValue()щоб перетворити в примітивне значення, потім до нього додається примітивна 10.0, потім це примітивне значення назад перетворюється вDoubleі зберігається вx.Тут дофіга більше роботи.
Мало того, з точки зору компілятора:
(1), (2), і (3) не мають сенсу. (1) і (3):(2):
Тобто тобі сам компілятор каже що
xце неreferenceна об’єкт, а тупо примітив (double).Може замість того щоб сіяти дезінформацію іди краще літкод порішай. На тобі промокод на −25%:
LIBEDAY.Ну тільки на літ-код і є надія, бо без нього тут щось дивне відбувається. Тут або:
1. Олексій ідіот і тоді літкод не нашкодить
2. це навмисний тролінг/дезінформація, тоді завдяки літкоду просто не буде створювати шуму
3. це ми всі ідіоти, а Олексій має якісь супер глибокі і унікальні знання внутрішностей і оптимізацій JVM, згідно якими JVM може там примітивні типи перетворювати в об’єкти.
От якась імовірність (3) є, але взагалі практично нереально мала:
це неправда, які на*** поля в тих прикладах, що я приводив?
Або аналогічно він вважає що різниця між
for (int i = 0; i < 10; i ++) {іfor (Integer i = 0; i < 10; i ++) {всього лиш в тому, щощо взагалі тривіально провіряється:
public static void main(String[] args) { long sum = 0; for (Integer i = 0; i < 1000000000; i++) { sum += i; } System.out.println(sum); }в 6+ раз повільніше за:public static void main(String[] args) { long sum = 0; for (int i = 0; i < 1000000000; i++) { sum += i; } System.out.println(sum); }я надеюсь что он таки просто идиот. Хуже если это троллинг, т.к. начитаются джуны вот такого а потом на собесе ляпнут и останутся без офера. Желание сделать другим людям плохо это хуже чем быть просто идиотом
class Scratch { public static void main(String[] args) { final Foo foo = new Foo(); for (Field field : foo.getClass().getDeclaredFields()) { System.out.println(field.getName() + " has type: " + field.getType()); } } static class Foo { double a = 0.0; Double b = 0.0; } }Если примитивов нет, то почему результатом выполнения будет?И что это меняет. В JVM это всё равно объекты. Реализация примитивов полностью объектная, грубо говоря, это эмуляция.
А ещё в JVM нет массивов, надеюсь для тебя тоже не будет новостью, что массивы — полноценные объекты, с которыми можно делать вполне объектные чудеса на кшталт прототипирования новых классов на их основе, скажем, с ленивым поведением. Или добавлением статик-методов. А то и подменой классов (салют создателям JRebel)
Я правильно понял, что в использовании double нет никаких преимуществ ни по памяти, ни по скорости по сравнению с Double?
нет, неправильно. Чувак несет полнейшую чушь. Вопрос. Какая разница между этими двумя кусками кода:
for (int i = 0; i < 10; i ++) { // do something }и
for (Integer i = 0; i < 10; i ++) { // do something }Буков больше.
ясно. Модель организации памяти в JVM точно не твое, мы уже поняли. Заканчивай уже
Ни разницы. Конечно, теоретики «по учебнику» будут не согласны, но факт остаётся фактом: за переменной типа double стоит объект типа Double.
Чувак, реально, не порти людям прохождение собеседований. Ты говоришь глупости. Хоть бы почитал документацию что ли
Очень надеюсь, что мсье не относит себя к «теоретикам „по учебнику“». Предложу еще немного практики. Дано два класса
public class Primitive { public static void main(String[] args) { double[] array = new double[1000000]; for (int i = 0; i < array.length; i++) { array[i] = 1.0 * i; } System.out.println("Ok"); } } public class Reference { public static void main(String[] args) { Double[] array = new Double[1000000]; for (int i = 0; i < array.length; i++) { array[i] = 1.0 * i; } System.out.println("Ok"); } }И два вызоваВопрос: что произойдет в каждом из вызовов и почему?
Если jdk < 11, то запускать классы чуть по-другому надо. Но практик, думаю, разберется)
Слушай, ты хочешь чтоб никто из этих людей не прошел собеседование?
Вот здесь ты прав, на собесе нужно отвечать «по учебнику», потому что те кто спрашивает, зачастую сами не умеют, но учат. Перед собесом надо всегда повторять теорию, особенно практикам. Уже только по той причине, что теория и практика дают сильно разно звучащие ответы на один и тот же вопрос.
о, хорошо что ты о себе написал. Теперь мне все понятно зачем ты тут столько глупостей понаписывал
Есть какая-то ссылка на источник?
Для SE8
Проверь написание. Может где русскую а вставил или ещё какой примитивный косяк. По написанию всё правильно. Действительно, перечитай сообщение ошибки, или сюда кинь.
Кстати, мне вассаби предлагают переписать на j2ee. Что скажешь?
Если у тебя куча время-денег, можешь писать что хочешь. Если мало — ищи слабые места и начинай с них. В твоём случае слабым местом является гуманитарная часть продукта, то есть ты вообще ещё не нашёл ДЛЯ КОГО ты пишешь, КТО является потребителем, а потому и вопрос ЧТО писать — не имеет ответа. Так какая разница на чём?
Сделай сначала чучело, в смысле код, каждый раз возвращающий одно и то же. Прототип. И уже с ним играйся. А уже тогда напишешь логику, и перепишешь её столько раз, сколько надо. Потому что переписывать проще, чем писать с нуля: на каждом этапе отсеивается куча мусора.
Как по мне, ты вообще с продуктом упускаешь очевидный путь. Ты считаешь, что должен сделать всё сам, своими ресурсами. В то время как успешные продукты вполне себе делаются совместно. Пока ты не научился работать совместно, работа самостоятельно не принесёт тебе ничего кроме усталости и депрессии. НАЙДИ продукт с теми технологиями, которые хочешь выучить, НАУЧИСЬ делать то, что там надо, и войди в разработку. Проще всего найти медленно развивающийся или не сильно популярный (до 1000 юзеров) продукт — там тебя не будут сильно пинать, у тебя будет время и возможность прокачать скиллы.
Почему так? Жизнь короче, чем ты думаешь. Нет смысла учиться делать всё и браться за всё. Да, у тебя получится. Но насколько лучше других у тебя получится? Сколько времени ты потратишь безвозвратно? Кому ты потом нужен на том уровне, до какого у тебя получилось? Куда дороже ценится ОПЫТ РАБОТЫ в команде. Потому что он даёт больше профита за единицу времени.
Если коротко, то нет, j2ee достаточно геморная для изучения штука, с кучей маразма внутри, и всё это моментально забывается если его не используешь по назначению. А назначение у него — бизнес-логика, столь же тупая и невообразимо нелогичная. Именно приведение нелогичности в бюрократические рамки бизнес-логики и есть программирование на энтерпрайз-фреймворках и платформах. Когда оно тебе будет НАДО — особой сложности не будет. Опять же, когда ты ПОЧИТАЕШЬ чужой код завершённых проектов, прежде чем писать свой. Именно завершённых, а не учебные кусочки, по кусочкам ты эту дуристику не поймёшь.
Я с тобой потому общаюсь, что ты читаешь мои мысли. Я еще не успел задать вопрос, а ты уже ответ дал. Вот ты не веришь, а телепатия такого рода возможна. Я умею замечать такие вещи. Общаются два человека постами. И один другому пишет короткие вопросы, а другой ему в ответ простыни. И вот первый я — начинаю читать простыню и у меня формируется вопрос. И вдруг бах! я уже в этой же простыне читаю ответ. Ок. И я читаю дальше и снова у меня появляется вопрос. И вдруг — да, да, в той же простыне новый ответ. Словно тот другой — ты, телепат. Тебе часто такое говорят? Иначе не платили бы столько. Хотя это выглядит словно ты перерабатываешь — не даешь мне возможности сначала задать тебе вопрос. Такое знаешь как выглядит? Словно ты из какой-то паралельной реальности прочитал мой вопрос, где я его все таки успел отправить раньше.
Все это легко, если учитывать поведение информации во всех 4 измерениях. Это знание древнее, оно либо утрачено либо скрыто.
Что касается j2ee и вассаби спасибо за развернутый ответ. Твои советы очень ценные для меня. Я всегда ищу провидцев и следую их советам. По крайней мере стараюсь.
В мене теж все працює.
Яка в вас версія JDK?
І скиньте повний стектрейс, щоб краще розібратись
1) stackoverflow.com/questions/tagged/java
2) Просит ли? www.tutorialspoint.com/compile_java_online.php выдает
$javac HelloWorld.java $java -Xmx128M -Xms16M HelloWorld max = 0.9969690961547211 min = 5.236547651865653E-4 avg = 0.5112746316201295