Calling get (array static method) from an array instance - java

New to Java, and OOP in general.
I'm doing an online Lynda course, and in the course there's an example of using Array.get to extract the 2nd item from an array:
String[] myFavoriteCandyBars = {"Twix", "Hershey's", "Crunch"};
System.out.println(Array.get(myFavoriteCandyBars, 2));
And the instructor explained that get is a static method from the "Array" class.
But when I tried defining:
`Array[] testarray = new Array[10];`
And using:
`testarray.get(testarray[10]);`
I get an error:
cannot resolve method 'get(java.lang.reflect.Array)'
But I don't understand why - the testarray is an object of class Array, and class Array has a method "get", so although it's bad practice, why can't I do it?

The Array class is an internal Java class containing only public static methods, and its intended use is to not be be directly instantiated. The following code:
testarray.get(testarray[10]);
fails because testarray is of type Array[], not Array, and therefore does not have the static method get() available. Hypothetically speaking, if you could call Array#get on an instance, it should work, but as mentioned above, Array cannot be instantiated.
A more typical way to use Array would be something like:
String[] testarray = new String[10];
testarray[1] = "Snickers";
System.out.println(Array.get(testarray, 1));
That is, create an array of the desired type, and then use Array#get to access whichever element you want.

get() is not a method in the array class, (as in a byte[] object). get() is in the Array class. Doing Array.get(testarray, 0) is what you want. Despite that, don't do this, do testarray[0] instead.
Whenever you use a static method, you shouldn't call it from an object, you should use the class instance, so instead of doing
Object o = new Object();
o.staticMethod();
Do:
Object.staticMethod();

Related

Undesrstanding clone method for arrays

I've learnt that for arrays the clone method is well-behaved and we can use it. But I thought that the type of the elemetns the arrays hold should have implemented Cloneable interface. Let me provide some example:
public class test {
public static void main(String[] args){
Test[] arr_t = new Test[1];
arr_t[0] = new Test(10);
Test[] an_arr = arr_t.clone();
an_arr[0]= new Test(5);
System.out.println(an_arr[0].test); //5
System.out.println(arr_t[0].test); //10
}
public static class Test{
public int test;
public Test(int test) {
this.test = test;
}
}
}
DEMO
I thought that 5 should have been printed twice. The reason for that is by clonning arrays we're creating new arrays containing references to the objects the first array holded (Because the type of the elemnts does not implement Cloneable). Couldn't you straighten the things out?
It's not clear if it's neccesary the array element's type implements Cloneable.
It's a simple concept, but seems hard to explain. When you clone the array, you will have two district arrays in memory, but with the same values in their indexes.
In your second array an_arr doing an_array[0] = new Test(5) you will put another reference in the slot 0.
But the index 0 of the clone is in a different place from the cloned array.
Your example is valid if you do
Test[] arr_t = new Test[1];
arr_t[0] = new Test(10);
Test[] an_arr = arr_t.clone();
an_arr[0].test = 5; // look here, I changed the object
System.out.println(an_arr[0].test); //5
System.out.println(arr_t[0].test); //5
Now both will print the same value because they hold the same reference to the same object, but the place where this reference is stored, is different.
.clone() makes what's called a "shallow copy". That means it copies as little as possible when running the method; instead of copying the contents of the array, it just creates references to the contents of the original array.
If you change the references by calling:
new Test(5)
Then you've overwritten that reference, and get new data.
The alternative is a deep copy of the array. Those can be expensive to do on bigger objects, so they're not the default.
An array's clone() does the same thing regardless of type of array: it creates a new array of the same type and size and then it assigns (=) each element of array to each element of the new array. That's it.
So if you have a 3-element array pointed to by arr, and arr.clone() returns newArr, then after the creation of the new array it simply does this:
newArr[0] = arr[0];
newArr[1] = arr[1];
newArr[2] = arr[2];
That's it. The type of array is not relevant. There is no "cloning" or anything involved in the elements. It doesn't know (or care) if the element has some kind of method to clone (in fact, there is no general API for cloning in Java, anyway, so this would be impossible).
(And by the way, even if it somehow put cloned objects into the new array, the result in your example would still be the same, because you are assigning a new value into the array, so it doesn't matter what was there before.)
So your question is basically why:
Test[] arr_t = new Test[1];
arr_t[0] = new Test(10);
Test[] an_arr = new Test[1];
an_arr[0] = arr_t[0];
an_arr[0] = new Test(5);
System.out.println(an_arr[0].test); //5
System.out.println(arr_t[0].test); //10
and you can figure it out from there.
The "problem" here is that arrays hold references to object, not objects. Further, this has nothing to do with cloning.
When you execute:
an_arr[0] = new Test(5);
You are assigning the new object's reference to the first element.
Also, each array has its own references to Test objects. When you clone the array, only the references are copied (not the objects to which they refer).

Immutable Class how to tell

I understand that immutable means that it is an object that will not change state after it is instantiated. But in this line of code I dont see Final when the array values is declared.
Is this class immutable? Can anyone explain how to find out. Thanks
public class A {
private double[] values;
public double[] getValues(){
return values;
}
}
As other have written this object is considered to be mutable in its state. What it is immutable to is that you can not exchange the array it holds. But you can change the array's content (getValues()[0] = 10;).
To convert this to a immutable object you must use List instead of an array. With List you can use Collections' method unmodifiableList to convert a given list into a version you can savely expose to the outside. If the caller of getValues() uses add or remove on a unmodifiable list it will result into a UnsupportedOpertionException keeping your object save from being modified.
If you need to stick to arrays you need to provide a copy (System.arraycopy) or a clone (clone()) of the array.
Usually a object is considered to be immutable if you can not change its properties (including inherited properties from superclasses. This usually includes the properties values as well but this is a blurred definition.
For example if you have a class that holds a File instance which points to document file and this File instance can not be changed the class is considered to be immutable (the inforamtion it provides never changes) but the document it points to can be mutated and changed every time. So its a blurred line actually (remember in your example you can not change the array but the content of the array).
Yes the code pasted is not having any final keyword associated and has no immutable behavior.
Well i would like to bring forth some key guidelines related to writing immutable classes in java :
1.) Ensure the class cannot be overridden - make the class final, or use static factories and keep constructors private
2.) Make fields private and final
force callers to construct an object completely in a single step, instead of using a no-argument constructor combined with subsequent calls to setXXX methods (that is, avoid the Java Beans convention)
3.) Do not provide any methods which can change the state of the object in any way - not just setXXX methods, but any method which can change state
4.) If the class has any mutable object fields, then they must be defensively copied when they pass between the class and its caller
A a = new A();
a.getValues()[0] = 1.2;
This would work as long as values is not empty. You will however not be able to reassign values to a new array. That is: a.getValues() = new double[5]; will not work.
The class is not immutable, as I can change values, just not reassign it.
Here is a simple verification. the values are initialized to 1,2.
Using the getter and a reference, one is able to change the values inside the first item in the array after the object is created
public class A {
private double[] values;
public double[] getValues() {
return values;
}
public static void main(String[] args) {
A test = new A();
test.values= new double[]{1, 2};
double[] valuesref = test.getValues();
valuesref[0] = 10;
for (int i = 0; i < test.values.length; i++) {
System.out.println(test.values[i]);
}
}
}
This can be avoided if getValues() returns a copy of the array.

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.

Array Clone doesn't work

what is wrong with my code?
in the main method i am doing this:
int [] test=new int[48];
test=etable(Right[]).clone();
What i want is, that the 'test' array is exactly the same like the output of the 'etable' method.
my method called 'etable':
public static int [] etable(int [] right){
int [] blabla=new int[48];
...
return blabla[]
}
Thanks for your advise
what is wrong with my code?
This line is a compilation error:
test = etable(Right[]).clone();
If right (or Right) is a variable (declared with type int[]), then you should write the method call like this:
test = etable(right).clone();
If Right is a type, then that is not the correct syntax for creating an array. (And judging from how you have written the etable method, you should not be passing it a new array.)
The second problem is that this sequence doesn't make sense:
int test[] = new int[48];
test = etable(...).clone();
You are allocating an array of 48 elements ... and then throwing it away by assigning a different array reference to the test variable.
The third problem is that the clone() is most likely redundant anyway. Your etable method is allocating a new array (in blabla) and returning it. The calling code is then copying the new array. Unless the etable saves the reference to the blabla array somewhere, the copying step doesn't achieve anything.
The final problem is that if Right really is a variable name, then that is a serious Java style violation. In Java a variable name should NOT start with an upper-case letter.
Use for instance Arrays.copy():
int[] tmp = etable(whatever);
int[] test = Arrays.copy(tmp, 0, tmp.length);
As to your original code, this, for instance:
test = ebtable(Right[]).clone();
is not legal Java (what is Right anyway?).

How can I put a Java array inside itself?

I'm attempting to create a Java object array and place the array inside itself at its second index (in order to represent a self-similar fractal with the array), but when I try to access theArray[1][1][0], I get this error:
Main.java:11: error: array required, but Object found.
This is what I've tried so far, and I'm not sure why it's not working:
import java.util.*;
import java.lang.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
Object[] theArray = new Object[2];
theArray[0] = "This array should contain itself at its second index.";
theArray[1] = theArray; //Now I'm attempting to put the array into itself.
System.out.println(theArray[1][1][0]) //Main.java:11: error: array required, but Object found
}
}
Is it actually possible to put a Java array inside itself, as I'm attempting to do here?
theArray[1] is of compile-time type Object (since it comes from an array of Objects).
You need to cast it to Object[] to use it as an array.
The fundamental problem you're encountering is that although an array that contains itself is a perfectly valid object, it isn't a valid type.
You can nest array types arbitrarily deeply – Object[][][][][][][][][][][][][] is a valid type.
However, the "bottom level" of the type can't be an array.
You're trying to create a type which is an array of itself.
Using generics, that would be possible:
class Evil extends ArrayList<Evil> { }
You're running into a casting error since you've declared theArray to be an Array of Objects. As a result, you can't promise Java that theArray[1] is an Array--it could be any kind of Object. You'll need to break up your access to do what you want:
Object[] innerArray = (Object[]) theArray[1];
System.out.println(innerArray[0] == theArray[0]); // Always true since innerArray IS theArray
while (true) {
// Careful! This loops forever!
// set innerArray = innerArray[1] = theArray = theArray[1] = innerArray...
// all of these are the exact same object (but you have to tell Java their type every time)
innerArray = (Object[]) innerArray[1];
System.out.println(innerArray[0]);
}
Your code is equivalent to
Object arr = theArray[1]; // arr is an Object here, not an array
But you could do
Object[] arr = (Object[] ) theArray[1]; // Now it is an array
This can be done quite easily with ArrayLists:
ArrayList list = new ArrayList();
list.add(list);
So now
System.out.println(list.get(0));
and
System.out.println(((ArrayList)list.get(0)).get(0)); //Casting because .get() returns an Object
Both will output the same thing.
You can take this to an arbitrarily large number of levels, if you want to:
System.out.println(((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)((ArrayList)list.get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0)).get(0));

Categories