Большой Воронежский Форум
» Программирование>Java. Создание динамического массива.
skyfish 14:21 19.05.2010
Изучаю 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


}
}
[Ответ]
dn2k4 21:52 19.05.2010

Сообщение от 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() );

...

SomeClass d = al.get(0); [Ответ]
kurdt 11:09 21.05.2010
конструктор возвращает нам ссылку на созданный объект. Вот пример:


// 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 приложении при нажатии на кнопку


Код:
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        

MainFep.myRead() ;
}
на что система ругается:
unreported exception java.io.IOException; must be caught or declared to be thrown

Как это обойти?


И еще один момент, мне нужно добавить в приложение мою библиотеку созданную с использованием package;
//package ru.somename.mylib;
В книжке написано что теперь
нужно поместить в переменную CLASSPATH директорию в которой лежит папка ru/
Но у меня в винде XP не нашел такой переменной в "Переменные среды", а занес эту директорию в переменную PATH, но при попытке импорта Java
не находит мою библиотеку(((

Заранее благодарю! [Ответ]
skyfish 21:14 28.05.2010
Тему пора переименовать в что-то типо "Учим яву".

Вот такой всплыл косяк: я построчно считываю файл и парсю строки. считываю вот так
Код:
  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: а может у тебя там файл в одну строку? [Ответ]
Вверх