Why doesn't Java initialize Array Objects? - java

If one runs the following code in java:
public class Testing {
public static void main(String[] args) {
TestObject[] array = new TestObject[4];
//array[0] = new TestObject();
System.out.println(Arrays.asList(array));
}
}
class TestObject {
String aString;
public TestObject() {
aString = "This has been initialized.";
}
}
It will print (null, null, null, null), and if array[0] = new TestObject(); is uncommented, then the first object will have a memory address (and not be null). I'm just confused to as to why Java wouldn't automatically call the constructor for each Object in an array when the array is first initialized properly. What are the advantages of the way it works right now? Is it a space issue (as in it would be too costly to do so)?
Maybe I've just overlooked something silly or I'm simply mistaken. This is not directly related to a problem I'm having, so if it's the wrong forum I apologize.

What happens if you want to fill up your array with real objects that are subclasses of TestObject, or which are constructed with non-default constructors? In the real world, you rarely want an array with a bunch of identical objects.

With new TestObject[4] you create an array, wich can hold 4 references to TestObject.
So understand the difference between TestObject[] and TestObject:
TestObject[] is a reference store for TestObject - objects. If you create a List<TestObject> you'll have to fill up the list with references too.

Related

Do arraylist needs to be specified as return type in method after modification?

I would like to know what is the best practice to return 'updated' ArrayList?
For example, if I am adding in a new element, it seems that whether if I did or did not specify the return type (see the addNewA() and addNewB()), the ArrayList in my main() method will still be 'updated' nonetheless.
Should I or should I not specify the return type?
Currently in my client program, most of the methods, I have specified it as void (no return type) and while the overall program still does works as intended, thought I would like to get this clarified and make the necessary changes if necessary.
public class MyClient
{
public static ArrayList<Person> addNewA(ArrayList<Person> myArray)
{
Person jack = new Person("jack", 24);
myArray.add(jack);
return myArray;
}
public static void addNewB(ArrayList<Person> myArray)
{
Person ben= new Person("ben", 19);
myArray.add(ben);
}
public static void main(String[] args)
{
ArrayList<Person> personArray= new ArrayList();
addNewA(personArray); // will return me an array size of 1
addNewB(personArray); // will return me an array size of 2
}
}
In a case like this, you should not return the list and should make your method void.
Different languages have different conventions, but one of Java's is that methods that operate by modifying their arguments (or the object they're called on) should not return values. Returning a value implies to someone using your code that a different object is being returned, since otherwise there is no use in returning an object the caller already has1. A method that is void, on the other hand, couldn't possibly be returning a copied-and-extended list, so it's very clear that it's intended to operate by modifying the list that you give it in the first place.
(By the way, you should also just use List<Person>, and you should pay attention to the warning you get about using new ArrayList() instead of new ArrayList<>().)
1 There is a specific exception to this, called the fluent builder pattern, but it's not easily confused with general code like this.
In java (and most high level strict type languages) Objects are passed by reference and primitives passed by value.
When using the new keyword you create an object.
While primitives (like int, char, double ect) are passed by value (meaning that a copy of the value of the variable will be sent to the invoked function), Object types are passed by reference, meaning that the actual original object is passed to the function.
To sum up - since you are using object here (ArrayList), you don't need a return type since the original object is changing.

Question about the Java documentation and its implementation

I'm currently sitting at an exercise, which wants me to create a Java program based on an already finished documentation HTML sheet.
For example, one entry states
reversedArray
public static Object[] reversedArray(Object[] array)
Based on the name, we can assume the method should return an array in the reversed order of array.
Now my question isn't about how to create the said array, but more about the Object[] terminology. What does it mean? Should I create a bunch of methods through overloading each with a specific array type (e.g. String[], int[], ...) or literally an Object[]?
It's the latter, how does an object array work? Based on the name, I assume it's an array that can hold objects, but I'm unsure what this means in practice.
Object[] is basically just an array of objects (best explanation award right here please ----> ☐ )
Jokes aside, in Java, any object is derived from the class Object so basically, this array can store any object of any class. It's mostly useful when you just want to carry an instance (or several instances) of different classes, but the type of said instance is not important.
Let's say you have multiple classes that are not necessarily related :
Class Dog {
String name;
public Dog(String name) {
this.name = name
}
public String toString() {
return "Hello! I am a dog called " + this.name;
}
}
Class Refrigerator {
public Refrigerator() {
}
public String toString() {
return "I am a refrigerator";
}
}
Since both classes are implicitly derived from Object and that Object implements the method toString() you can override that method in both of you class declarations.
Then you can store any instance of these in a Object and call the method toString(), like so :
Dog myDog = new Dog("Spike");
Object anyObject = myDog;
System.out.println(anyObject.toString()); //would print the result of your "toString()" method in the Dog class :
//"Hello! I am a dog called Spike"
Refrigerator myFridge = new Refrigerator();
Object secondObject = myFridge;
System.out.println(secondObject.toString()); //would print the result of your "toString()" method in the Refrigerator class :
//"I am a refrigerator"
This allows you to create a method that accepts any object and treats them the same and assign any object in argument :
public void printWhatYouAre(Object o) {
System.out.println(o.toString());
}
public void doingSomething() {
Dog myDog = new Dog("Spike");
Refrigerator myFridge = new Refrigerator();
printWhatYouAre(myDog);
printWhatYouAre(myFridge); //would print the same as above
}
In your case, your method only needs to rearrange an array, which means it doesn't even need the method toString nor does it need to know what the objects are. It just needs to store an array of something into an other array of something in a different order.
Here is a nice reading about polymorphism in Java, which is basically applicable in any language, but the examples that are used are wrote in Java. The whole site actually is a pretty good reference, so it's worth taking a look, especially the OOP sections which are the most related to your post. ;)
As the name already states, the method should create a new array in
the reversed order of "array".
The method name only says to "reverse" the array; whether it's just a matter of modifying the actually supplied array or constructing a new one is something you'll need to clarify with the author of the requirement if it's not clear.
Now my question isn't about how to create said array, but more about
the "Object[]" terminology. Basically, I'm unsure what to do. Does
said "Object[]" mean, I should create a bunch of methods through
overloading each with a specific array type (e.g. String[], int[],...)
or literally an Object[] array?
No, you only have to create overloads for the primitive types i.e. int[], long[] etc and that's only if your requirement says so. the aforementioned method should be able to consume Object[], String[] , Integer[] , Double[] etc...
It it's the latter, how does an object array work? Based on the name I
assume, it's an array that can hold objects, but I'm unsure what this
means in practice.
The method name has nothing to do with what an array can hold, the method argument is an array of Object's and it's as simple as that.
Reading you might find useful:
Arrays

Reference new object through void method

I'm working on an assignment that deals with array manipulations for Java. Right now I have to delete elements inside the middle of an array. Now I know that arrays, once they're created cannot be changed in length. So I decided to make a new object, and have the former reference point to my new array.
public class A{
public static void main(String[] args){
B test = new B(val);
test.cut(2,4);
test.display();
}
class B{
private Obj[] array;
B(Obj val){
construct something
}
public void cut(int i, int j){
B newObject = new B(val);
...
newObject.array = this.array;
newObject = this;
}
}
The issue is that when I display the test object, it will only show me the original test object contents rather than newObject contents. Since this is a void method, I can't return an object. How do I reference the new object then? The last two lines for my cut method seem to have no effect at all. I know that ArrayList would be preferable for things like this, but this being a homework assignment we are forced to use arrays.
Now I know that arrays, once they're created cannot be changed in length.
This is true.
But the reference pointing to an array inside the B object instance can be changed (as you didn't declare it final):
public void cut(int i, int j){
Object[] newArray = new Object[len];
//... copying array content ...
this.array = newArray;
}
Beware of the thread safety issues such mutability causes. Mutable objects are usually frowned upon...
If the rules of assignment allow the use of class Arrays, this is what you can use instead of your own cut method:
newArray = Arrays.copyOfRange(oldArray, from, to);
In the method cut you create a new object of B then assign the the this reference to it. This has not effect as you have found because the this reference (the actual object) is not changed at all, The newObject is visible only inside this method, once it is terminated, the object is gone.
While you are in the same class B you dont have to create a new Object of it just for the purpose of altering the data it holds. You could just create a new array and copy the original content to it.
For copying the content you could use the method System#arraycopy. If you are not permited to use any jdk helping functionalities, then you could just loop over the original array and copy elements into the new one as you want.

ArrayList references behavior

I am totally confused with ArrayList behavior. Wrote really long post, then realized no one is going to analyse huge code, so just core of the problem. Numbers are for convenience, but in my app these 0 and 24 are dynamic values.
ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();
VoipBlock vb3 =new VoipBlock();
vb3=sortedBlocks.get(0);
vb3.setPacketNumber(24);
Essentially my final aim is to: modify and add back to arrayList as new value. However when I do that the guy at position 0 in ArrayList -> unsortedBlocks.get(0); replicates all the changes done to vb3 which of course is not what I want. I want vb3 acquire same values as VoipBlock inside of ArrayList, but I want it to be detached.
This is yet another case of passing by reference. I hate technical explanations - Java passes everything by value, BUT in some cases it passes references by values - this is same as saying not-oily oil. Please help.
It reminds me my start of learning JavaScript - I hated the language - until I watched proper materials at lynda.com - JavaScript Good Practices? - Diagrams killed me. It is the lazy description that turns us-youth away from brilliant technology, not the technology itself.
Please don't let it bother my stress and don't be in any way offended by me, it is just general complaining, maybe someone will look at it and make life better :-)
Thanks for Your time,
Desperately awaiting for help :-)
To achieve your objective you can use clone method. you have to override this method in VoipBlock class
Lets say VoipBlock is as follows
public class VoipBlock {
private int packetNumber;
private String type;
public int getPacketNumber() {
return packetNumber;
}
public String getType() {
return type;
}
public void setPacketNumber(int value) {
packetNumber = value;
}
public void setType(String value) {
type = value
}
public VoipBlock clone() {
VoipBlock clone = VoipBlock();
clone.setType(this.getType());
clone.setPacketNumber(this.getPacketNumber());
return clone;
}
}
So, using the same code you can do like as follows
ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();
VoipBlock vb3 =new VoipBlock();
sortedBlocks.add(vb3);
vb3=sortedBlocks.get(0).clone();
vb3.setPacketNumber(24);
Note that upon calling clone method in above code segment, vb3 get assigned with a new VoipBlock instance. And already inserted VoipBlock to the array remains unchanged.
if you are looking to have kind of sample instances of VoipBlock instances which you later wanted to use in creating similar instances like them. check on immutability/mutability aspect of the code. check "Effective Java" by Joshua Blouch
The following will always copy the reference of b to a:
AnyClass a = ...;
AnyClass b = ...;
a = b;
What you want is probably to clone the object:
a = b.clone();
If I understand correctly, you're a bit unsure about how references and values work. I think the rule of thumb is that primitive types like int, char, boolean and maybe String are copied but Objects just have their reference passed.
The line vb3=sortedBlocks.get(0); completely replaces whatever vb3 used to be with the first thing in the ArrayList. And yes, it won't be a copy, it will be a reference to the same object in memory. So whatever you do will affect both of them. You need to either manually copy over all the information you need or to use a clone() or copy() function.
So for example, in your code, the line VoipBlock vb3 =new VoipBlock(); is a bit redundant because you're overwriting the new instance straight away.
What you really need here is to either use a copy constructor or declare VoipBlock to be Clonable so you can use the clone() method.
What you are interpreting as passing by reference is not actually passing by reference. Java objects are really pointers. Because of this you are passing the value of the pointer. So when you do:
vb3=sortedBlocks.get(0);
you are really assigning vb3 to point to the same locations in memory as sortedBlocks.get(0). Therefore when you manipulate vb3 properties through their setters, the result is seen in both.
If you want two separate pointers you need to use the new keyword or use the clone() method which does this under the hood.
An example to prove this is:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class Main {
public void doSomething(Person p) {
p = new Person("Bob");
System.out.println(p.getName());
}
public static void main(String[] args) {
Person p = new Person("Billy");
System.out.println(p.getName());
doSomething(p);
System.out.println(p.getName());
}
}
Since Java is pass by value the output will be: Billy, Bob, Billy. If Java were pass by reference it would be Billy, Bob, Bob. If I did not do the new Person in the doSomething() method and instead used the setName() method I would end up with Billy, Bob, Bob also but this is due to the fact I'm now modifying off the same pointer not that I passed by reference as the example above proves that's not the case.

Java Object Reference and Java Methods

I am unable to understand how this works
public void addToRule(Rule r) {
if (!getRuleList().contains(r)) {
getRuleList().addElement(r);
}
}
If I run this code:
obj.addToRule(r);
System.out.println(getRuleList().contains(r));
it prints out true how can this happen?
btw ruleList is a vector member of the main class and is not a static variable(don't think this matters but sharing anyway).
import java.util.Vector;
public class RuleEngine{
private Vector ruleList = new Vector();
public Vector getRuleList(){
return ruleList;
}
public void addToRule(Rule r){
if(!getRuleList().contains(r))
getRuleList().addElement(r);
}
public static void main(String args[]){
RuleEngine re = new RuleEngine();
Rule r = new Rule("Rule1");
re.addToRule(r);
System.out.println(re.getRuleList().contains(r));
}
}
class Rule{
public String name = "";
public Rule(String nam){
this.name=nam;
}
}
OK people have told me that this works because of the pass by reference in java. I get it. but what can i do to get a copy of that object instead of its reference?
I'm guessing getRuleList() is returning a reference to a List (or something similar). Think of it as a pointer (or more specifically, a copy of a pointer) if you're familiar with C. You're working on the same underlying instance of the object when you call getRuleList().
For proof, try: System.out.println(getRuleList() == getRuleList()); The == operator will only compare if the two references are pointing to the same object (not a deep equal like .equals). You'll see that until you call setRuleList() with a different object reference that the statement holds true.
These assumptions are of course without seeing your full code.
So, to answer your questions you have to at first know how Java passes Variables.
a Variable has a value:
int i = 1234;
Person p = new Person("Peter");
Now, the Variable i contains exactly 1234, while the Variable p contains the Memory Adress of the created Person.
so i contains 1234 and p contains the adress (let's say a4dfi3).
anyMethodYouLike(p);
System.out.println(p.getName());
public void anyMethodYouLike(Person somePerson) {
somePerson.rename("Homer");
}
so in this example, we give the Method anyMethodYouLike the Variable p... wait! we give the Method the value of the Variable (a4dfi3). The Method then calls rename on this Variable (which still has the same adress as p has, hence it modifies the same Person that p points to).
So, after the Method, the Name of the Person p points to, gets printed, which results in "Homer".
someOtherMethod(p);
System.out.println(p.getName());
public void someOtherMethod(Person somePerson) {
somePerson = new Person("Walter");
}
In THIS example we still give the adress of our Person called "Peter" to the Method. But this time, the Method creates a new Person in somePerson (therefore overriding the adress in somePerson to.. let's say 13n37s.
BUT! the Person at a4dfi3 wasn't changed! The print call still outputs "Peter" and not "Walter".
Now, let's see how this behaves with primitives:
someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
someInt++;
}
So, the Value of i (1234) gets passed to someInteger. Then someInteger gets incremented to 1235. But i is still 1234.
This is the big difference between Objects and primitives in Java.
Hope I could help,
Ferdi265
From your comments it looks like you have not completely understood what the difference is between a value and a reference in Java. Basically, objects are always passed around as references in Java.
Consider
class Test {
private List list = new ArrayList();
public List getList() {
return list;
}
}
The getList() method will return a reference to the list object. It will not return a copy of the list object. Doing something like
Test test = new Test();
String s = "ABC";
test.getList().add(s);
System.out.println(test.getList().contains(s));
Will return true since the first time getList() is called, a referece to the list is returned, on which add(s) is invoked. The second time getList() is called, it returns a reference to the same list, not a copy of it, not a new list - the same reference. Calling contains(s) will return true since it the same list onto which the object s was added.
Consider this, however.
Test test1 = new Test();
Test test2 = new Test();
String s = "ABC";
test1.add(s);
System.out.println(test2.getList().contains(s));
This will print out "false". Why? test1.getList() returns a reference to the list inside test1 and test2.getList() returns a reference to the list inside test2. Here, s was added to test1:s list, so it will not be contained inside test2:s list.
It should always print true, because you add the rule to the rule list in case it is not there. What happens is:
you tell the object to add add a rule to its rule list
the objects checks if the rule exists, and if it doesn't, adds it
So it is guaranteed to contain the rule after the code is executed.

Categories