Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I would like to get this inventory_ array from another class.
public class File {
Object[][] inventory=new Object[50][2];
//Reading file to the inventory array.
}
public class Stack {
//I want to copy inventory array to here
}
Lets assume I have 2 different classes and I have 2 different arrays.
public class inventory {
Object[][] inventory_=new Object[50][2];
}
public class bag {
Object[][] bag_=new Object[50][2];
}
So I want to compare inventory_'s items with bag_'s item in the bag class. How can I implement this.
Tehcnically it is possible to have a getter, that just returns the reference to the private Object[][] inventory array.
But this approach considered unsafe, because in this case, external code may change the internal state of your Fileclass via modifying the inventory array state.
For example:
class File {
Object[][] inventory=new Object[50][2];
public Object[][] getInventory() {
return inventory;
}
}
For this case, let's consider this example code:
class Stack {
private File file;
public Stack(File file) {
this.file = file;
}
void processSomething() {
Object[][] stackInventory = file.getInventory();
}
}
And in case you assign something to stackInventory[1][1] (for example), then inventory[1][1] array element into File class instance also will change its value.
And thus it is not considered a good design approach, because it may lead to hard-to-catch bugs in your project.
There are two solutions for this case.
The first one: make defensive copy of the array in your getter.
public Object[][] getInventory() {
Object[][] newInventory = new Object[50][2];
// copy inventory array contents to the newInventory array
return newInventory; // and returning safe copy of the array
}
In this case as you have Object, it is still possible to change internal state of the objects if they are mutable ones.
Either make your objects immutable, or employ deep copy approach upon making defensive copy of the array.
And another way to resolve this issue, which I recommend, is using the Iterator approach.
In your File class make a method that returns the Iterator over your inventory array. And use this iterator in the external code to iterate over the inventory elements.
Or you may make your File class iterable and use foreach operator to process the inventory elements.
Once again, upon designing your approach, keep in mind the mutable/immutable class types. And if it is possible, keep your classes immutable.
Also it is not recommended to name your classes likewise the standard java sdk classes. Your File class could be confused with java.io.File class by someone who will read your code later.
The same goes for your Stack class, which can be confused with java.util.Stack class. Please use other, more descriptive and unique names.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
The continuation of the question.
I need to statically and publicly storage data as arrays but I don't want somebody to modify my data. I need only ability to read from those arrays. Therefore I think I should use something like constant arrays which are presented in C++.
As far as I understand Collections.unmodifiableList(Arrays.asList(...)) prevents from modify the list at run-time but not at compile-time.
I've made the following class (code is updated). I suppose I'm not reinventing the wheel because I cannot have the same result using unmodifiableList.
/**
* Emulates constant arrays from C++.
*
* #param <E> Type of elements. Has to be immutable type.
*/
public final class ConstArray<E> {
/** Stores elements. */
private final E[] storage;
/**
* Constructs the object.
*
* #param storage Elements.
*/
public ConstArray(final E[] storage) {
this.storage = storage.clone();
}
/**
* Returns element at {#code idx}.
*
* #param idx Index of returning element.
* #return Element at {#code idx}.
*/
public final E get(final int idx) {
return storage[idx];
}
}
The size method and some other methods are omitted.
I've tested the class and it works.
To paraphrase, if I provide my library and somebody try to modify my data, I think it's better when he/she will know immediately that it's not possible (my class doesn't have a method to modify anything) and if I used unmodifiableList he/she will notice only a crash of the program.
What are advantages and disadvantages of this class? Is there a way to improve this class?
UPD:
I decided to use #Hoopje 's advice (see answers). It's based on experience that I don't have: I'm only a Java beginner.
If "reinventing the wheel" is not disadvantage enough, I see one major disadvantage to your approach:
Arrays.asList and Collections.ummodifiableList return List instances, so they are integrated in the Java Collections framework. This means that you can easily use them in enhanced for loops (for (E item : list) { }), as streams (list.stream()), use all List methods, pass them to methods which expect Collection or List subclasses, etc.
A minor point is that your class makes a copy of the array, whereas both Arrays.asList and Collections.ummodifiableList return views of their argument, so they do not copy the array.
By the way, creating a shallow copy of an array does not require "magic": you can do
this.storage = storage.clone();
Answer to UPD1:
Yes, it is unfortunate that Java does not provide interfaces for collections which cannot be modified. Thus, immutable List instances will have, for example, an add(E) method which simply throws an exception. So there is no compile-time guarantee for immutability.
However, in the Javadoc for your method you will of course write that the returned list is immutable. And if the user of your library tests his/her software, he will very deterministically see the exception and realize that he/she made a programming error.
And believe me, the users of your library will very much hate you if you take away their possibility to use the returned list in Collection-based APIs, just for the small advantage of not having any methods that look as if they would modify it.
Hi I'm trying to create a ArrayList which contains copies of the objects in the original ArrayList. Ive searched here but couldn't understans enough of earlier posts to get helped. Below is the ArrayList Im trying to make a copy of.
ArrayList<Stuff> originallist = new ArrayList<Stuff>();
Sorry if repost!
This isn't necessary something that can be answered in general, as it depends on how the objects can be copied.
Supposing that the object has a method called copyOf that returns a copy of the object, you would need to do
ArrayList<Stuff> copy = new ArrayList<Stuff>(originallist.size());
for (Stuff s : originallist) {
copy.add(s.copyOf());
}
There are many places that the "copyOf" function may come from. If an object implements the cloneable interface, that may be a source of this function (but there are various reasons that the interface is discouraged). Some classes contain a constructor that creates a copy from an existing instance, in which case you could do
ArrayList<Stuff> copy = new ArrayList<Stuff>(originallist.size());
for (Stuff s : originallist) {
copy.add(new Stuff(s));
}
in other cases, it may have to be done with an approach accessing fields (for example with a Person object that keeps a first and last name)
ArrayList<Person> copy = new ArrayList<Person>(originallist.size());
for (Person s : originallist) {
copy.add(new Person(s.getFirstName(),s.getLastName()));
}
To be certain of how to do it, you should look at the api guides to the "Stuff" object. The actual copying of the List itself, is easy.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I recently encountered code like the following:
public List<Item> getItems() {
if (items == null) {
items = new ArrayList<Item>();
}
return this.items;
}
and crucially, no setter method.
So if you wanted to add to the arrayList, you would have to do
foo.getItems().add(...)
rather than
foo.setItems(myArrayList)
I've not seen this idiom before, and I can't say I like it, but when I generated some mapping code using mapstruct.org (great tool by the way), mapstruct handles it fine and correctly generates code that uses the getter as a setter as well.
I'm just wondering - is this a common idiom that I've somehow missed? It seems pointless to me, but perhaps there is some wisdom behind it I'm not seeing?
It is common but it is not recommended.
The problem isn't with the lazy initialisation (that part is fine) but the exposure of what should be an implementation detail. Once you expose the actual, mutable(!) list object you store in your field, the caller of the code can do anything with the list, even things you don't expect.
They could for example remove objects when really all you want to allow is add(). They could modify it from different threads, making your code break in interesting and frustrating ways. They could even cast it to a raw List and fill it with entirely different types of objects, making your code throw ClassCastExceptions.
In other words, it makes it impossible to enforce class invariants.
Note that there are two things that work together to cause this problem:
The exposure of an object stored in a field.
And the fact the object is mutable.
If any of those two aren't true, there's no problem. So this is fine:
public String getFoo() {
return this.foo;
}
Because String is immutable. And this is fine too:
public List<String> getFooList() {
return new ArrayList<>( this.fooList );
}
Because now you're returning a defensive copy and not the actual object. (However, if the elements of the lists were mutable, you'd be in trouble again.)
There is a more subtle variation to this problem...
Imagine this scenario:
public class Foo {
private List<String> list;
public Foo( List<String> list ) {
this.list = list; // Don't do this
}
...
}
This looks perfectly harmless, and you see it in many places. However there is a hidden catch here too: by not making a copy before storing the list, you're in exactly the same situation. You can't stop someone from doing this:
List<String> list = new ArrayList<>();
list.add( "nice item" );
Foo foo = new Foo( list );
list.add( "hahahaha" );
list.add( "i've just added more items to your list and you don't know about it." );
list.add( "i'm an evil genius" );
So you should be making defensive copies both before assigning a mutable object to a field and when returning it.
If it's so dangerous to expose mutable fields of a class, why don't people make defensive copies all the time then?
Apart from simply not knowing why it isn't a good idea, there are two broad categories of excuses given.
Performance. Making a copy of an object every time you call a getter is expensive. This is of course true but it's not always as expensive as you'd think. And if you find yourself paying too high a cost for defensive copies, there are usually ways out: for example by designing your classes to be immutable. If all your classes are immutable, you won't need defensive copies, ever.
Only I will call this code and I won't abuse it. Promise. This is again something that could be valid depending on the situation. If you're writing a small standalone application on your own, it's probably true that you won't abuse it. Or if you're writing a small library but you only expose details of classes that aren't part of the public API. In most other cases though you simply can't be sure that someone somewhere won't abuse it. And when that happens, your code probably won't break with a bang. It usually just starts doing slightly...odd things occasionally. And that's the worst kind of bug to try to find.
There are two things in your code:
Lazy initialization, which is a common approach.
Returning a reference to a mutable inner ArrayList, which is not fine, because it breaks encapsulation. If you would like to add items to this list, you should expose addItem() method only.
This is a common idiom but I wouldn't recommend using it because the caller can do things like this:
final List<Item> items = bean.getItems();
final List notItems = (List) items;
notItems.add(new NotAnItem());
The caller can also maintain a reference to the List and accidentally mutate it later.
I would recommend steering clear of this particular idiom and providing immutable views from getters. This will lead to much more stable code in the long run.
So:
public List<Item> getItems() {
if (items == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(this.items);
}
And
public void setItems(final List<Item> items) {
if (items == null) {
throw new NullPointerException("items is null");
}
this.items = new ArrayList<>(items);
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I was just wondering if there is a way to rename the variable assigned to an ArrayList... Or if I just need to create another one, just making it exactly the same.
Just create a new reference with the name you want and assign it from the old reference:
ArrayList original = ...;
ArrayList newList = original;
I should point out that since ArrayList is a reference type, original and newList are both pointing to the same data in memory. If you add an item to original or to newList, it is going to affect both. It is not creating a second copy of the ArrayList. It is a little difficult to understand what you are asking for, though.
If you are talking about refactoring your code to rename the variable across the entire application, then it sort of depends on what IDE you are using, but any good IDE will have this capability.
First, I would just like to point out that 'renaming' a variable is not really a concept that bares any resemblance to the way that changing a 'reference' or 'identifier' works. You can't change a variables identifier (kind of like a variable's name), but you can pass the variable's value to another variable with a different identifier.
When a variable refers to an Object or child of the Object class (such as ArrayList), your reference type variable holds data indicating the position of that object in memory. So passing that reference's data to another reference just means there are now two Object references that 'refer' to the same object in memory.
Technically speaking, if you wanted to give that object a name that you could use to identify it later with, this is possible by creating a custom class that extends ArrayList (or whatever object). For example;
public class NamedArrayList extends ArrayList{
private String listName = "default_name";
public String getListName(){
return listName;
}
public void setListName(String listName){
this.listName = listName;
}
}
Alternatively, you could create a Wrapper class which holds an ArrayList as well as a name for identifying it. Apologies if the last part is a little off subject, but I hope it helps.
You can try this
List<Double> original =new ArrayList<Double>();
List<Double> copy = new ArrayList<Double>(original);
You can't rename any variable while the programm is running.
But you could rename it while developing. Then compile and run.
If you mean by renaming using a different reference than you can simply do
ArrayList newListRef = oldListInstance;
//use newListRef thereafter
If you mean to change some of the elements retaining the order then -
ArrayList is dynamic in size. You can add and remove elements to and from specific index and ordering in retained. So no need to create separate List. If you want to change a specific element simply remove it and add new element at that index.
APIs
public E remove(int index)
public void add(int index, E element)
I have a class, lets call it 'Words', that reads a file and creates a list of strings.
I then have a class, 'Items', that creates a list of 'description' objects, each description object needs access to the list from 'Words'.
Since the 'Word' list reads a file, I obviously don't want to create that list for each 'description' object. So what would be the best way of accessing that list?
Should I just create a function getList() from 'Words' and pass it to 'Items' constructor, then pass it again to each 'description'? or is there a better way? If I do that, then I would also want to make sure it is only a reference to the list and not a copy since the 'Words' list can get huge.
I am relatively new to java and any help would be appreciated.
I would try to resist the temptation to pass that List of words around. I don't see any encapsulation there.
I might give the class that initializes and manages the word list a method that would take an Item and an interface that would show how to populate or filter that word list for a given Item.
I'm guessing that the number of words associated with an item is a small subset of the larger whole, and the number of items is manageable.
I'd just want to see that you didn't turn objects into dumb structs or data transfer objects that revealed everything there was to know about their internal state. If you can, encapsulate behavior inside an object and hide details and complexity. Clients of that class will thank you.
UPDATE: Based on your comment below, I'd wonder if a relational database is what you really need. An Item needs a List of Descriptions; it's a simple JOIN in a relational database and mapping to objects.
Parsing and populating the tables is a one-time thing. Your Java application can just query for Item instances that have given Descriptions. You can ask it to tell you all the Items that have Description "foo", for example. That could be laborious and inefficient using an in-memory Java object. Let the relational optimizer speed it up for you. You don't have to have all the objects in memory at the same time that way, either. Just query for what you need.
You need to create a class that pupulate the List of String object (singleton), call that singleTon method in constructor of description class to assign reference of list to the description object.
public class Words
{
private static ArrayList<String> words;
public static ArrayList<String> getWords()
{
if(words==null)
{
words=new ArrayList<String>();
//read strings from the file and add them into list
}
return words;
}
}
In description class,
public class Description
{
private String desc;
private ArrayList<String> words;
public Description(String desc)
{
this.desc=desc;
this.words=Words.getList();
}
}
You have two choices:
You can retrieve the list from Words using getList() as you said. You then pass the list into the new description object via its constructor.
You can declare the List in Words as public static. This will allow you to reference the List by class reference; Words.list;
The first solution is probably your best option, as declaring static variables is usually undesirable.
I would like to do as below:
public class Words{
private static List words;
private Words();
public static List getInstance(){
if(words == null){
words = getFile();
}
return words;
}
private List getFile(){
//get file
}
}
public class Items{
public List items = Words.getInstance();
}
I'm sorry I haven't tested this code, hopes it will help you to think out a better way if it's wrong.