Изучаю Java, переписывая дельфевскую прогу.
Задача добавлять в динамический массив элеметы типа запись.( в дельфи реализуется очень просто)
В Java вместо записей использую объекты.
получается что мне нужно каждый раз создавать новый объект, чтобы добавить его в ArrayList, так как когда я создаю один объект, добавляю его, а потом меняю его свойства и снова добавляю в ArrayList. То все элементы ArrayList получаются одинаковыми и равными последнему объекты, так как в ArraList я так понимаю заносятся ссылки на один и тот же объект!
Так как же это реализовать то? (неужели создавать заранее неизвестное колличество объектов)
Заранее благодарен
Код:
import java.util.ArrayList;
class Fep
{
public static void main(String[] argv)
{
someclass c=new someclass(); // простой класс из одних свойств
someclass d=new someclass();
ArrayList al = new ArrayList();
c.setValue(1);
al.add(c);
c.setValue(2);
al.add(c);
d=(someclass) al.get(0);
System.out.println(d.Value); //выводит 2, а не 1
}
}
Сообщение от skyfish:
получается что мне нужно каждый раз создавать новый объект, чтобы добавить его в ArrayList
Да. Создавать новый экземпляр объекта.
Сообщение от skyfish:
неужели создавать заранее неизвестное колличество объектов
Да. Создавать нужное количество экземпляров объекта. Ссылки на них и будут хранится в списке.
[Ответ]
kurdt 14:48 20.05.2010
В Java всё кроме примитивов - ссылки.
Т.е. когда вы создаете штуку типа someclass d=new someclass();
то создается объект в памяти, а d - только ссылка на него.
Когда вы бросаете его в ArrayList, то в нем хранится ссылка, а не объект.
Т.е. если выполним al.add(c);
то al.get(0) и d будут одной и той же ссылкой на один объект.
работаю с ЛЮБОЙ их них мы меняем объект и после запроса по другой ссылке получим его в измененном виде.
В вашем случае надо создать 2 разных объекта.
И некоторые комменты по вашему коду
- сразу привыкайте называть имена классов с большой буквы (SomeClass), имена полей класса - с маленькой (value) и обращаться к ним не напрямую, а через методы get, set (getValue(), setValue())
- вместо вот этого ArrayList al = new ArrayList();
c.setValue(1);
al.add(c);
d=(someclass) al.get(0);
System.out.println(d.Value); //выводит 2, а не 1
будет лучше написать так ArrayList<SomeClass> al = new ArrayList<SomeClass>();
al.add(c);
System.out.println(al.get(0).getValue()); //выводит 2, а не 1[Ответ]
skyfish 09:29 21.05.2010
Всем спасибо за ответы. Во всем разобрался. В принципе так и думал, но вопрос еще остался.
Будет идти считывание с файла. При считывание новой строки понадобилось создать новый экземпляр класса:
Код:
SomeClass a = new SomeClass();
и заносим его в ArrayList
Потом нужно будет создавать и заносить следующий экземпляр в ArrayList.
Так как индентификатор а уже занят надо писать к примеру
Код:
SomeClass b = new SomeClass();
как решается этот вопрос, не перебирать же вес алфавит, причем программно)))))
[Ответ]
dn2k4 10:34 21.05.2010
ArrayList<SomeClass> al = new ArrayList<SomeClass>();
al.add( new SomeClass() );
конструктор возвращает нам ссылку на созданный объект. Вот пример:
// list - ссылка на список ArrayList list = new ArrayList();
// конструктор создал объект и вернул ссылку на него. Теперь a - ссылка на объект А MyClass a = new MyClass( "a" );
// теперь list.get(0) и a - 2 ссылки на объект А (значение одинаковое, но ссылки разные - меняя одну мы не затрагиваем list.add( a ); другую)
// конструктор создал НОВЫЙ объект и вернул НОВУЮ ссылку, теперь a - ссылка на объект B, но list.get(0) осталась ссылка на объект A a = new MyClass("b");
// теперь в списке 2 ссылки - на объект А и объект В list.add( a );
Отличие от самого первого вашего пример - меняется не объект по ссылке, а создается новый объект с новой ссылкой.
[Ответ]
skyfish 22:54 21.05.2010
Благодарен Вам. завтра продолжу убивать в себе лузера))))
[Ответ]
skyfish 09:46 27.05.2010
Не стал создавать новую тему. Появился еще вопрос на который пока сам не нашел ответа.
В Дельфи я мог передвать значение в функцию по ссылке:
Код:
function myFunction(var a:integer):boolean;
begin
a:=2;
result true;
end;
и теперь
Код:
i:=1;
myFunction(i);
writeln(i); // i=2;
Как такое сделать на яве, а то
Код:
public class StringOperation {
public static boolean myFunction(int a)
{
a=2;
return true;
}
}
Код:
int i=1;
StringOperation.myFunction(i);
System.out.println("i = " + i); // i = 1; Что и естественно!
Зная что можно и без этого обойтись, но все же интересует можно ведь такое сделать?
[Ответ]
skyfish 11:13 27.05.2010
Нашел решение! Передавать в качестве аргумента не примитивные тип, а объект.
[Ответ]
dn2k4 12:04 27.05.2010
Есть еще грязный хак - передавать как параметр массив с одним элементом =)
[Ответ]
adrenalin 15:36 27.05.2010
У всех примитивных типов есть обертки. К чему какие-то "грязные хаки"?
[Ответ]
skyfish 15:08 28.05.2010
adrenalin, заинтересовало. если не сложно пару слов с примерчиком!
И еще один вопрос:
У меня есть статический метод
Код:
public class MainFep {
public static void myRead() throws IOException {
//читает инфу из файла
}
}
я хочу его применить в GUI приложении при нажатии на кнопку
на что система ругается:
unreported exception java.io.IOException; must be caught or declared to be thrown
Как это обойти?
И еще один момент, мне нужно добавить в приложение мою библиотеку созданную с использованием package;
//package ru.somename.mylib;
В книжке написано что теперь
нужно поместить в переменную CLASSPATH директорию в которой лежит папка ru/
Но у меня в винде XP не нашел такой переменной в "Переменные среды", а занес эту директорию в переменную PATH, но при попытке импорта Java
не находит мою библиотеку(((
Вот такой всплыл косяк: я построчно считываю файл и парсю строки. считываю вот так
Код:
BufferedReader in = new BufferedReader(new FileReader("c://input.txt"));
String s;
while((s=in.readLine())!=null)
{
//парсинг
}
И все работает как "как у Верочки". Но когда работаю с файлом 32 Мб. то выдается
Код:
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3209)
at java.lang.String.<init>(String.java:216)
at java.io.BufferedReader.readLine(BufferedReader.java:331)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
и так далее
Хотя в дельфях мои проги летает и с 500 Мб файлами))))) как быть тут?
[Ответ]
zer0access 23:37 01.06.2010
Во-первых, после чтения всё таки стоит закрывать ридеры:
Код:
in.close();
Во-вторых, в Java есть понятие heap space, которая является памятью, выделяемой для динамических объектов. Задать можно через параметры JVM при запуске программы. Для этого надо добавить в командную строку параметры -Xms128m (начальный объём) и -Xmx128m (максимальный объём). Оба параметра необязательны, значения указаны в метрах оперативы. Любая среда разработки позволяет добавить эти параметры к строке запуска программы. Более подробно про эти опции на http://greenmice.info/ru/node/143 или ещё лучше http://java.sun.com/javase/technolog.../vmoptions.jsp
И наконец, не могли бы вы привести полный код примера? По идее файл в 32Мб должен спокойно читаться даже с размером кучи по умолчанию (64М).
[Ответ]
Glaz 22:20 16.06.2010
Сообщение от skyfish:
Тему пора переименовать в что-то типо "Учим яву".
Вот такой всплыл косяк: я построчно считываю файл и парсю строки. считываю вот так
Код:
BufferedReader in = new BufferedReader(new FileReader("c://input.txt"));
String s;
while((s=in.readLine())!=null)
{
//парсинг
}
И все работает как "как у Верочки". Но когда работаю с файлом 32 Мб. то выдается
Код:
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3209)
at java.lang.String.<init>(String.java:216)
at java.io.BufferedReader.readLine(BufferedReader.java:331)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
и так далее
Хотя в дельфях мои проги летает и с 500 Мб файлами))))) как быть тут?
Тупо - дай больше памяти при запуске программы - посмотри какие возможны аргументы запуска
Умно - разберись с размером буфера для чтения и закомментируй свой парсинг, сдается мне ты там экземпляры плодишь забивая ими память.
PS: а может у тебя там файл в одну строку?
[Ответ]